我正在尝试启动几个bash例程来自基于GUI的软件。我面临的问题是管道问题。这里是测试bash脚本(bashScriptTest.sh):
#!/bin/bash
#---------- Working
ls | sort | grep d > testFile.txt
cat testFile.txt
#---------- NOT working
echo $RANDOM > testFile2.txt
for i in `seq 1 15000`; do
echo $RANDOM >> testFile2.txt
done
awk '{print $1}' testFile2.txt | sort -g | head -1
这里是创建错误的python脚本:
import subprocess
#
with open('log.txt','w') as outfile:
CLEAN=subprocess.Popen("./bashScriptTest.sh", stdout=outfile, stderr=outfile)
print CLEAN.pid
OUTSEE=subprocess.Popen(['x-terminal-emulator', '-e','tail -f '+outfile.name])
正如您在运行python脚本时看到的那样,会遇到Broken pipe错误不是在前三个管道(第一行),而是在awk完成了巨大的工作之后。我需要在bash中管理大量的例程和子例程同时使用shell==True标志也不会改变任何事情。我试着用最蟒蛇的方式写所有的东西,但不幸的是没有我有机会重写python中的所有管道步骤。另一件需要提及的事情是,如果您在终端内测试bash脚本一切都很好。如有任何帮助,我们将不胜感激。提前感谢!
编辑1:
包含错误的日志文件显示:
bashScriptTest.sh
log.txt
stack.txt
testFile2.txt
test.py
3
sort: write failed: standard output: Broken pipe
sort: write error
好吧,这有点模糊,但碰巧我不久前在研究python导师邮件列表上的一个问题时遇到了类似的问题。
当通过子进程模块(在python中)运行脚本与直接运行bash时,您会看到不同的行为,原因是python会覆盖所有子进程(全局)的SIGPIPE到SIG_IGN(忽略)的处理。
执行以下管道时。。。
awk '{print $1}' testFile2.txt | sort -g | head -1
由于-1
标志,head
将在打印sort
命令的第一行stdout后退出。当sort
命令试图向其stdout写入更多行时,会引发一个SIGPIPE。
SIGPIPE的默认操作;例如,当管道在类似shell的bash中执行时;是终止排序命令。
如前所述,python使用SIG_IGN(忽略)覆盖默认操作,因此我们最终会出现这种奇怪的、有些莫名其妙的行为。
一切都很好,但你可能想知道现在该怎么办?这取决于您使用的python版本。。。
对于Python 3.2及更高版本,您已经设置好了。3.2中的subprocess.Popen
添加了restore_signals
参数,默认为True
,有效地解决了问题,无需进一步操作。
对于以前的版本,可以为subprocess.Popen
的preexec_fn
参数提供可调用的,如。。。
import signal
def default_sigpipe():
signal.signal(signal.SIGPIPE, signal.SIG_DFL)
# ...
with open('log.txt','w') as outfile:
CLEAN=subprocess.Popen("./bashScriptTest.sh",
stdout=outfile, stderr=outfile
preexec_fn=default_sigpipe)
我希望这能有所帮助!
编辑:可能需要注意的是,您的程序实际上运行正常,AFAICT也是如此。您只是看到了在shell中直接执行脚本时通常不会看到的其他错误消息(由于上述原因)。
另请参阅:
- https://mail.python.org/pipermail/python-dev/2007-July/073831.html
- https://bugs.python.org/issue1652