写错误:管道坏了

时间:2010-04-25 21:00:44

标签: python linux unix scripting

我必须在大约300个目录上运行一个工具。每次运行大约需要1分钟到30分钟甚至更长时间。所以,我编写了一个python脚本,它有一个循环来一个接一个地在所有目录上运行该工具。

我的python脚本的代码如下:

for directory in directories:
  os.popen('runtool_exec ' + directory)

但是当我运行python脚本时,我反复收到以下错误消息:

..
tail: write error: Broken pipe
date: write error: Broken pipe
..

我所做的就是使用ssh登录远程服务器,其中保存了工具,python脚本和主题目录。当我使用以下命令从命令提示符单独运行该工具时:

runtool_exec directory

它工作正常。只有当我使用python脚本运行时,“破管”错误才会出现。 任何想法,解决方法?

2 个答案:

答案 0 :(得分:9)

您看到的错误是因为您使用os.popen()来运行命令,这意味着管道已打开并连接到命令stdout。每当命令(或其执行的任何内容而不重定向stdout)想要写入stdout时,它都会尝试写入管道。但是你没有保留管道,因为你没有在任何地方分配os.popen()的结果,所以它被Python清理并关闭。因此,尝试写入它的进程遇到管道损坏,并产生您看到的错误。 (os.popen() stderr重定向到管道,因此您仍然会看到错误。)

os.popen()来电中的另一个问题是您没有检查以确保directory不包含shell特有的任何字符。例如,如果目录包含引号,或者*,则可能会发生奇怪的事情。像这样使用os.popen()非常糟糕。

你应该使用subprocess.Popen(),并明确地告诉它你要对进程的输出(stdout和stderr)做什么。你传递subprocess.Popen()一个参数列表(包括你想要的东西)开始)而不是单个字符串,它完全避免了shell - 不需要理智 - 检查你的字符串。如果你真的想忽略输出,你可以使用类似的东西:

devnull = open(os.devnull, 'w')
for directory in directories:
    subprocess.Popen(['runtool_exec', directory], stdout=devnull)

虽然我强烈建议至少对subprocess.Popen的结果进行一些初步的检查,以查看进程是否过早执行或是否有错误代码。

答案 1 :(得分:0)

如果它对其他人有帮助,同样的问题可能是在shell命令中使用管道(|)的结果。请参阅此处了解解决方案https://stackoverflow.com/a/4106633/1904913