我尝试使用这个简单的脚本通过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>'
脚本在shell中运行良好(即使使用Apache用户运行它),但是当通过Web服务器运行CGI时,始终会收到错误500。我尝试设置 shell = True ,但这没有什么区别。我在Apache错误日志中收到的唯一消息是:
malformed header from script.
然而,如果我取消注释 标记内的子进程调用,Apache不再抱怨标题,我收到了预期的结果(状态200,但当然没有系统调用)。
我错过了什么吗?我是否配置Apache以允许来自CGI的系统调用?是否必须在本地(.htaccess)或全局(/ etc / apache2 / ...)进行此类配置?关于如何解决这个问题的任何建议?任何帮助表示赞赏。
答案 0 :(得分:1)
这显然是因为子进程产生输出,它是不通过调用者的标准输出管道,应该是,但是将直接刷新到输出。因此,实际上,ls
的输出最终成为CGI标题,因此出现500错误。
os.popen
工作,因为它为你做了预期的stdout管道。
但你也可以这样做(首选):
p = subprocess.Popen('/bin/ls')
(注意:子进程现在异步运行,与原始subprocess.check_call
不同。如果需要同步调用(例如,您需要子进程的输出...),您可以执行类似
out, err = p.communicate()
print(out)
等。近似原始的同步控制流程。不要忘记在stdout=PIPE
电话中添加Popen()
。)