为什么在使用subprocess.call()时我的简单Python-CGI总是出现500错误?

2 投票
1 回答
890 浏览
提问于 2025-04-18 14:35

我尝试通过一个简单的Python 2.7 CGI脚本来触发系统调用:

import subprocess

print 'Content-Type:text/html'
print
print '<!DOCTYPE html>'
print '<html>'
print '<body>'
print '<pre>'

try:
    subprocess.check_call('/bin/ls')
except:
    pass

print '</pre>'
print '</body>'
print '</html>'

这个脚本在命令行中运行得很好(即使是用Apache用户来运行),但是当我通过网络服务器运行CGI时,我总是收到一个500错误。我尝试设置shell=True,但这并没有改变什么。我在Apache的错误日志中只看到这条信息:

malformed header from script.

不过,如果我取消注释标签中的子进程调用,Apache就不再抱怨头部信息了,我得到了预期的结果(状态200,但当然没有系统调用)。

我是不是漏掉了什么?我需要配置Apache以允许CGI进行系统调用吗?这样的配置是要在本地(.htaccess)还是全局(/etc/apache2/...)进行?有没有什么建议可以解决这个问题?任何帮助都很感激。

1 个回答

3

这件事发生的原因是,子进程产生了输出,但这个输出没有通过调用者的标准输出(stdout)传递,反而是直接被输出了。因此,ls 的输出就变成了CGI头信息,这就是导致500错误的原因。

os.popen 能够正常工作,因为它会为你处理好标准输出的传递。

不过,你也可以用另一种(更推荐的)方式来做到这一点:

p = subprocess.Popen('/bin/ls')

(注意:现在子进程是异步运行的,这和你最开始用的 subprocess.check_call 不一样。如果你需要同步调用(比如你需要子进程的输出...),你可以这样做:

out, err = p.communicate()
print(out)

等等,以接近最初的同步控制流程。别忘了在 Popen() 调用中加上 stdout=PIPE。)

撰写回答