Python CGI脚本IOError破管
我有一个旧的基于Python的网页表单,我正在更新它,让它使用GPG来加密,而不是使用一个已经不再支持的Python包。当我通过命令行调用这个脚本时,一切都很好,但通过网页浏览器和CGI调用时却出现了一个错误:IOError: [Errno 32] Broken pipe。这个错误在我使用gnupg包或者直接通过子进程与gpg通信时都会出现。
版本信息:
Python 2.4.1
gnupg 0.2.2 (python GPG wrapper)
Apache/2.2.9
gpg 1.4.9
这里有一个简化的脚本:
#!/usr/bin/python
import sys
# send python tracebacks out to the web browser
sys.stderr = sys.stdout
import gnupg
gpg = gnupg.GPG()
gpgkey = 'np'
message = 'Our secret message!'
print "Content-type: text/html\r\n"
print '''<html><head><title>Test GPG access via cgi</title>
</head><body><pre>'''
print 'message in the clear:'
print message
encrypted = str(gpg.encrypt(message, 'np'))
print 'message encrypted:'
print encrypted
print '''</pre></body></html>'''sf
当通过命令行调用上面的脚本时,它运行得很好,但通过CGI调用时却产生了以下错误:
message in the clear:
Our secret message!
Traceback (most recent call last):
File "/home/dkmaster/www/nickads/secure-cgi/gpgtest.py", line 23, in
encrypted = str(gpg.encrypt(message, 'np'))
File "/home/dkmaster/www/nickads/secure-cgi/gnupg.py", line 517, in encrypt
return self.encrypt_file(StringIO(data), recipients, **kwargs)
File "/home/dkmaster/www/nickads/secure-cgi/gnupg.py", line 467, in encrypt_file
self._handle_io(args, file, result, passphrase=passphrase)
File "/home/dkmaster/www/nickads/secure-cgi/gnupg.py", line 201, in _handle_io
_copy_data(file, stdin)
File "/home/dkmaster/www/nickads/secure-cgi/gnupg.py", line 75, in _copy_data
outstream.write(data)
IOError: [Errno 32] Broken pipe
我还尝试直接通过子进程与GPG通信,而不是使用gnupg模块。
#!/usr/bin/python
import sys
import subprocess
sys.stderr = sys.stdout
print "Content-type: text/html\r\n"
print '''<html><head><title>Test subprocess via cgi</title>
</head><body><pre>'''
plain_text = 'the quick fox ' * 10
print plain_text
gpgCommand = "/usr/bin/gpg --quiet -a -e -r 'np' "
gpgProcess = subprocess.Popen(
gpgCommand,
stdin=subprocess.PIPE,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
shell=True
)
encrypted_text = gpgProcess.communicate(plain_text)[0]
print encrypted_text
同样,这在命令行中运行良好,但通过CGI调用时会产生类似的错误:
Traceback (most recent call last):
File "/home/dkmaster/www/nickads/secure-cgi/subprocesstest.py", line 20, in
encrypted_text = gpgProcess.communicate(plain_text)[0]
File "/usr/lib/python2.5/subprocess.py", line 670, in communicate
return self._communicate(input)
File "/usr/lib/python2.5/subprocess.py", line 1220, in _communicate
bytes_written = self._write_no_intr(self.stdin.fileno(), buffer(input, input_offset, 512))
File "/usr/lib/python2.5/subprocess.py", line 999, in _write_no_intr
return os.write(fd, s)
OSError: [Errno 32] Broken pipe
那么,我该如何修复CGI中的管道问题呢?
2 个回答
0
这是个好问题 - 我不太确定这是不是 python-gnupg
的问题,或者说 gpg
的问题。可能是 subprocess
或 cgi
的问题,或者是它们之间的某种互动。你可以试试用一个非常简单的脚本,读取标准输入(stdin)并把输出写到一个文件里,这样能正常工作吗?
另外,开启日志记录也是个好主意,这样可以看看有没有什么错误信息。可以参考 test_gnupg.py
脚本,里面有关于如何做的例子。
2
我知道我的回答可能来得有点晚,但我最近也遇到了同样的问题,我想我找到了解决办法。
GPG似乎会在终端输出一些信息(比如“你需要一个密码”之类的),即使你把标准输出重定向了——别问我怎么回事 :)
不过,出现“Broken Pipe”的问题似乎是因为在cgi环境下,gpg无法输出这些信息(我在使用uwsgi时遇到的)。即使你加上了--quiet
,它还是会打印这些信息。只有当你额外加上--batch
时,它才会真的安静下来。