如何使用标准Linux工具修复死锁脚本?

时间:2016-10-01 17:31:11

标签: python linux subprocess buffer buffer-overflow

我在Python3中有一个脚本,如果我使用subprocess.Popen.wait()我有问题 - 我的脚本多次迭代一些Linux命令,它看起来像我的应用程序没有响应。当我使用subprocess.Popen.communicate()时,我的应用程序会在一秒钟内正确完成其工作。 使用Linux解决此问题的正确方法是什么?

我认为解决方案必须在某个地方使用缓冲区的变量进行操作,但我在整个互联网上搜索并找不到合适的东西。可能是我不了解整个Linux的结构和操作。

我的问题可以重新表述如下:当我使用.wait()方法时到底发生了什么?这会导致失败吗?这么久等待的原因是什么?当我中止运行任务时,我会看到下一个日志:

Traceback (most recent call last):
  File "./test.py", line 6, in <module>
    proc.wait()
  File "/usr/lib/python3.5/subprocess.py", line 1658, in wait
    (pid, sts) = self._try_wait(0)
  File "/usr/lib/python3.5/subprocess.py", line 1608, in _try_wait
    (pid, sts) = os.waitpid(self.pid, wait_flags)
KeyboardInterrupt

我的文件看起来大概就像接下来的事情: script.py:

#!/usr/bin/python3
# -*-coding: utf-8 -*-

import subprocess
proc = subprocess.Popen(['./1.py', '1000000'], stdin=subprocess.PIPE, stderr=subprocess.PIPE, stdout=subprocess.PIPE)
proc.wait()
out = proc.stdout.read()
# out = proc.communicate()[0]
print(len(out))

1.py:

#!/usr/bin/python3
# -*-coding: utf-8 -*-

import sys

x = sys.argv[-1]

# print(x, type(x))
for i in range(int(x)):
  print(i)

UPD:据我们了解,问题是缓冲区溢出。事实证明,问题的最后一个版本是,如何使用Linux在运行脚本之前将缓冲区或重定向缓冲区扩展到文件的可能性?

UPD2:我也尝试将脚本运行为:$ python3 -u ./script.py ,但不幸的是,unbufferring不能正常工作,脚本挂起。

1 个答案:

答案 0 :(得分:1)

您的脚本正在将输出发送到其stdoutstderr管道。操作系统将缓冲一些数据,然后在管道填满时永久阻止该过程。假设我有一个很长的命令,比如

longwinded.py:

for i in range(100000):
    print('a'*1000)

以下内容因为stdout管道填充

而挂起
import sys
import subprocess as subp
p = subp.Popen([sys.executable, 'longwinded.py'], stdout=subp.PIPE,
    stderr=subp.PIPE)
p.wait()

下一个没有挂起,因为communicate将stdout和stderr管道读入内存

p = subp.Popen([sys.executable, 'longwinded.py'], stdout=subp.PIPE,
    stderr=subp.PIPE)
p.communicate()

如果你不关心stdout和err是什么,你可以将它们重定向到空设备

p = subp.Popen([sys.executable, 'longwinded.py'], 
    stdout=open(os.devnull, 'w'), 
    stderr=open(os.devnull, 'w'))
p.wait()

或将它们保存到文件

p = subp.Popen([sys.executable, 'longwinded.py'], 
    stdout=open('mystdout', 'w'), 
    stderr=open('mystderr', 'w'))
p.wait()