【问题标题】:How to configure Apache 2 to run a Python script from a Ruby CGI app with %x{}如何使用 %x{} 配置 Apache 2 以从 Ruby CGI 应用程序运行 Python 脚本
【发布时间】:2015-09-18 03:30:03
【问题描述】:

我的 Ruby CGI 应用程序非常简单,我想调用一个 Python 脚本,例如 youtube-dl,或 youtube-upload%x{youtube-dl --help}

为简单起见,我只想打印youtube-dl Python 脚本的帮助页面。所以我的Ruby脚本也很简单:

#!/usr/bin/ruby
require "cgi"

cgi=CGI.new(:accept_charset => "UTF-8")

url=cgi['url']

puts "Content-Type: text/plain; charset=\"UTF-8\""
puts "Access-Control-Allow-Origin: *"
puts

puts url
puts "-----------------------------------"
puts %x{youtube-dl --help 2>&1}

然后我可以用http://example.com/cgi-bin/ytdl?url=a_youtube_url 调用这个名为ytdl 的CGI 应用程序。不幸的是,我从 Python 解释器中只收到很多错误消息,无法导入某些包,尤其是站点包:

Traceback (most recent call last):
  File "/usr/bin/youtube-dl", line 5, in <module>
    from pkg_resources import load_entry_point
  File "/usr/lib/python3.4/site-packages/pkg_resources/__init__.py", line 36, in <module>
    import plistlib
  File "/usr/lib/python3.4/plistlib.py", line 65, in <module>
    from xml.parsers.expat import ParserCreate
  File "/usr/lib/python3.4/xml/parsers/expat.py", line 4, in <module>
    from pyexpat import *
ImportError: /usr/lib/python3.4/lib-dynload/pyexpat.cpython-34m.so: undefined symbol: XML_SetHashSalt

我想我会配置我的 Apache 2 Web 服务器来为 Python 解释器提供一些环境变量,它可以在其中找到包。不幸的是,我没有使用 Python 的经验,直到现在我才学习 Ruby。我的 Apache 服务器以用户 daemon 运行 CGI 应用程序,当我以 daemon 登录时,我可以运行 youtube-dl 脚本而不会出现错误消息。

Apache 为我的 CGI 应用程序提供这些环境(印有puts %x{env}):

UNIQUE_ID=VZN9RyX3N7MAAAs95zsAAAAI
RUBYOPT=rubygems
GEM_HOME=/home/XXXXXX/.gem/ruby/2.2.0
HTTP_USER_AGENT=Opera/9.80 (X11; Linux i686) Presto/2.12.388 Version/12.16
HTTP_HOST=xx.xxx.xx.xxx
HTTP_ACCEPT=text/html, application/xml;q=0.9, application/xhtml+xml, image/png, image/webp, image/jpeg, image/gif, image/x-xbitmap, */*;q=0.1
HTTP_ACCEPT_LANGUAGE=en-US,en;q=0.9
HTTP_ACCEPT_ENCODING=gzip, deflate
HTTP_CONNECTION=Keep-Alive
PATH=/usr/local/sbin:/usr/local/bin:/usr/bin:/usr/bin/site_perl:/usr/bin/vendor_perl:/usr/bin/core_perl:/home/XXXXXX/.gem/ruby/2.2.0/bin:/home/XXXXXX/util
LD_LIBRARY_PATH=/opt/lampp/lib:/opt/lampp/lib
SERVER_SIGNATURE=
SERVER_SOFTWARE=Apache/2.4.9 (Unix) OpenSSL/1.0.1g PHP/5.5.11 mod_perl/2.0.8-dev Perl/v5.16.3
SERVER_NAME=xx.xxx.xx.xxx
SERVER_ADDR=xx.xxx.xx.xxx
SERVER_PORT=80
REMOTE_ADDR=xx.x.xxx.xxx
DOCUMENT_ROOT=/opt/lampp/htdocs
REQUEST_SCHEME=http
CONTEXT_PREFIX=/cgi-bin/
CONTEXT_DOCUMENT_ROOT=/opt/lampp/cgi-bin/
SERVER_ADMIN=you@example.com
SCRIPT_FILENAME=/opt/lampp/cgi-bin/ytdl
REMOTE_PORT=37798
GATEWAY_INTERFACE=CGI/1.1
SERVER_PROTOCOL=HTTP/1.1
REQUEST_METHOD=GET
QUERY_STRING=
REQUEST_URI=/cgi-bin/ytdl
SCRIPT_NAME=/cgi-bin/ytdl

同时我意识到,当我设置环境变量时(在 Apache config httpd.conf 中使用 SetEnv 指令,或者在我的 Ruby 脚本中使用 ENV['PYTHONHOME']=value) 将 PYTHONHOME 调用为空字符串 "" 或 "/usr/lib" ,错误消息消失,我得到另一个:

Fatal Python error: Py_Initialize: Unable to get the locale encoding
ImportError: No module named 'encodings'

当我设置时:

ENV['PYTHONHOME']="/usr/lib"
ENV['PYTHONPATH']="/usr/lib/python3.4"

我收到另一条错误消息:

File "/usr/bin/youtube-dl", line 5, in <module>
    from pkg_resources import load_entry_point
ImportError: No module named 'pkg_resources'

所以我的问题是,我应该如何配置我的 Apache 2 网络服务器以使 Python 脚本运行并使其可从其他应用程序调用?

【问题讨论】:

    标签: python ruby apache cgi environment-variables


    【解决方案1】:

    当您在子 shell 中运行应用程序时,您必须了解为该 shell 和应用程序设置的环境。 PATH 和变量将不存在或非常有限,这会影响其查找库的能力。

    编写一个小的 CGI,输出传递给脚本的 Apache 变量和环境,可以是网页,也可以是日志或文件,并检查结果。

    此外,权限和用户将是服务器设置的任何内容,这通常是非常受限制的。

    另外,请认真考虑使用 CGI。而是使用更现代、更灵活的东西。 Sinatra 可以很好地与 Apache 配合使用,使用诸如 Passenger 之类的东西将它们粘合在一起。 Sinatra 让做 Web 服务变得非常容易,而且实际上工作得很好,你通常可以在没有像 Apache 这样的重量级服务器的情况下做到这一点,尤其是在开发、测试和早期生产阶段。我有一个内部使用的 API 可以处理大量企业关键请求,而且它只是随波逐流。

    【讨论】:

    • 谢谢,我添加了环境变量列表。事实上,这与我使用任何用户名登录时得到的几乎相同。我也会尝试这些现代技术,但我还是一个绝对的初学者,我想练习使用 AJAX 和 CGI​​ 处理 Web 表单。
    猜你喜欢
    • 2010-10-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多