我有一个较旧的python 2.7.5脚本,该脚本在Red Hat Enterprise Linux Server 7.6(Maipo)上突然出现问题。毕竟,它在Red Hat Enterprise Linux Server 7.4版(Maipo)上运行良好。 该脚本基本上实现了
之类的东西 cat /proc/cpuinfo | grep -m 1 -i 'cpu MHz'
。在较新的OS版本上,cat进程保持打开状态,直到脚本终止。
似乎grep的管道以某种方式使cat进程保持打开状态,而我找不到任何有关如何明确关闭它的文档。
可以通过将此代码粘贴到python CLI中,然后检查ps进程列表中的静态进程'cat / proc / cpuinfo'来重现此问题。 该代码破坏了循环中最初发生的事情,因此请不要争论其样式。 ;-)
import shlex
from subprocess import *
cmd1 = "cat /proc/cpuinfo"
cmd2 = "grep -m 1 -i 'cpu MHz'"
args1 = shlex.split(cmd1) # split into args
args2 = shlex.split(cmd2) # split into args
# first process uses default stdin
ps1 = Popen(args1, stdout=PIPE)
# then use the output of the previous process as stdin
ps2 = Popen(args2, stdin=ps1.stdout, stdout=PIPE)
out, err = ps2.communicate()
print(out)
然后在第二个会话中检查进程列表(!),
ps -eF |grep -v grep|grep /proc/cpuinfo
在RHEL7.4上,进程列表中没有打开的进程,而在RHEL 7.6上经过一些尝试后,它看起来像这样:
[reinski@myhost ~]$ ps -eF |grep -v grep|grep /proc/cpuinfo
reinski 2422 89459 0 26993 356 142 18:46 pts/3 00:00:00 cat /proc/cpuinfo
reinski 2597 139605 0 26993 352 31 18:39 pts/3 00:00:00 cat /proc/cpuinfo
reinski 7809 139605 0 26993 352 86 18:03 pts/3 00:00:00 cat /proc/cpuinfo
仅当我关闭python CLI时,这些过程才会消失,在这种情况下,我会收到这样的错误(我将格式原样弄乱了):
cat: write error: Broken pipe
cat: write errorcat: write error: Broken pipe
: Broken pipe
为什么cat尽管它应该已经输出了完整的/ proc / cpuinfo并且应该已经终止了,但是为什么它显然仍要写入管道?
或更重要的是:如何防止这种情况发生?
感谢您的帮助!
根据VPfB的建议,事实证明,我的示例不太幸运,因为可以通过单个grep命令实现预期的结果。 因此,下面是一个修改后的示例,以另一种方式显示管道问题:
import shlex
from subprocess import *
cmd1 = "grep -m 1 -i 'cpu MHz' /proc/cpuinfo"
cmd2 = "awk '{print $4}'"
args1 = shlex.split(cmd1) # split into args
args2 = shlex.split(cmd2) # split into args
# first process uses default stdin
ps1 = Popen(args1, stdout=PIPE)
# then use the output of the previous process as stdin
ps2 = Popen(args2, stdin=ps1.stdout, stdout=PIPE)
out, err = ps2.communicate()
print(out)
这一次,结果是grep进程的单个僵尸进程(169731是python会话的pid):
[reinski@myhost ~]$ ps -eF|grep 169731
reinski 169731 189499 0 37847 6024 198 17:51 pts/2 00:00:00 python
reinski 193999 169731 0 0 0 142 17:53 pts/2 00:00:00 [grep] <defunct>
那么,这仅仅是同一问题的另一种症状,还是我在这里做错了什么?
答案 0 :(得分:0)
好吧,看来我只是从示例中找到了一个僵尸进程解决方案的解决方案: 只需要做一个
ps1.communicate()
看来,这是正确关闭管道所必需的。 我希望在第二个进程的communication()被调用并从第一个进程读取管道时会发生这种情况。
有人可以指出我,我在这里想念的是什么吗? 我一直乐于学习...;-)