我使用以下函数在Python中运行命令:
def run_proc(cmd):
child = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
stdout, stderr = child.communicate()
returncode = child.returncode
return stdout, stderr, returncode
它一直运行良好,但是现在我尝试使用yes
程序将输出管道传输到stdin。我尝试运行的命令如下:
yes '' | apt-get -y -o Dpkg::Options::="--force-confdef" -o Dpkg::Options::="--force-confold" dist-upgrade
但我相信它可以用一般的例子代替,例如:
yes | head -3 | cat
我的问题是,如果我尝试运行其中包含yes |
的任何命令,则上述subprocess.Popen将包含错误消息:
yes: standard output: Broken pipe
yes: write error
对我而言,似乎管道仍然有效,从yes | head -3 | cat
的答案可以看出:y y y
。
我有以下问题:
答案 0 :(得分:7)
问题在于subprocess
模块before Python 3.2+ doesn't restore SIGPIPE
signal handler to default action。这就是你得到EPIPE
写错误的原因。
在Python 3.2 +
中>>> from subprocess import check_output
>>> check_output("yes | head -3", shell=True)
b'y\ny\ny\n'
当yes
退出时,<SIGPIPE
被head
杀死。
在Python 2中:
>>> from subprocess import check_output
>>> check_output("yes | head -3", shell=True)
yes: standard output: Broken pipe
yes: write error
'y\ny\ny\n'
yes
写入了EPIPE
错误。忽略错误是安全的。 It communicates the same information as SIGPIPE
要解决此问题,您可以使用restore_signals
参数在Python 2中模拟preexec_fn
:
>>> from subprocess import check_output
>>> import signal
>>> def restore_signals(): # from http://hg.python.org/cpython/rev/768722b2ae0a/
... signals = ('SIGPIPE', 'SIGXFZ', 'SIGXFSZ')
... for sig in signals:
... if hasattr(signal, sig):
... signal.signal(getattr(signal, sig), signal.SIG_DFL)
...
>>> check_output("yes | head -3", shell=True, preexec_fn=restore_signals)
'y\ny\ny\n'
答案 1 :(得分:3)
另一个问题回答了原因......我会试着给你一个解决方法
你能不能做像
这样的事情proc = subprocess.Popen(cmd, shell=True,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
stdin = subprocess.PIPE)
for i in range(10): #send 10 y's
time.sleep(1) # 1 second apart
proc.stdin.write("y") #you may also need to send a newline ...
print proc.communicate()
见下文(由于头部没有做太多事情,我没有理会延迟)
>>> import subprocess
>>> proc = subprocess.Popen("head -3",
... shell = True,
... stdout = subprocess.PIPE,
... stderr=subprocess.PIPE,
... stdin=subprocess.PIPE)
>>> for i in range(10):
... proc.stdin.write("y\n")
...
>>> proc.communicate()
('y\ny\ny\n', '')
答案 2 :(得分:2)
话说:
yes | head -3
导致head
在读完3行输入后向SIGPIPE
发送yes
,即它会发送信号以终止yes
。
$ yes | head -3
y
y
y
$ echo "${PIPESTATUS[@]}"
141 0
解决方案是避免使用SIGPIPE
!