繁体   English   中英

管道到头导致从 python 调用的 shell 脚本中的管道损坏

[英]Piping to head results in broken pipe in shell script called from python

我有一个命令可以运行以生成随机字符串:

var=`< /dev/urandom tr -dc _A-Z-a-z-0-9 | head -c8`

当我在交互式 bash 会话中运行此命令时,我绝对没有错误。 但是,当我将此命令放入脚本并将其作为脚本运行时,我收到 tr 指示的管道损坏错误。 我已经阅读了几个相关主题,但仍然没有答案为什么脚本和交互行为不同,有没有办法用 shell 选项或其他东西来控制它?

编辑我:

关于给出的评论,我发现可以通过以下方式控制指示损坏的管道错误:

 trap - SIGPIPE # to ignore errors

 trap "" SIGPIPE # to display errors

编辑二:

好吧,我提供了有关繁殖条件的错误信息。 最后,问题似乎是由使用 os.system() 调用脚本的 python 包装器引起的:

 python -c "import os; os.system('sh -c \"< /dev/urandom tr -dc _A-Z-a-z-0-9 | head -c8\"')"

给定的行会产生与使用的操作系统无关的断管错误。

编辑三:

这个话题在这里讨论过: https : //mail.python.org/pipermail/python-dev/2005-September/056341.html

如果其中一个父进程陷阱sigpipe ,那么管道将继承ignore信号处理,这将导致您遇到此问题。

这可以(安全地)复制:

( trap '' pipe; var=`< /dev/urandom tr -dc _A-Z-a-z-0-9 | head -c8 )

通常, head -c8命令很快就会完成,此时stdin将关闭。 由于它的stdin连接到管道stdouttr ,它现在不再是有道理的, tr写入其stdout 一旦尝试,系统将使用SIGPIPE杀死它。 除非tr忽略此信号或从其父级继承了此信号的ignoreSIG_IGN )处置。 然后write tr的破坏stdout将简单地导致常规错误并将errnoEPIPE ,此时tr很可能会串行化并将此错误输出到其stderr并退出。

这个答案提供了从Python到head管道问题的一个很好的总结,并展示了一些解决方法。

https://stackoverflow.com/a/30091579/456550

问题似乎是head从输入流中读取指定(或默认)行数,打印它们,然后退出。 因此,仍在写入的管道中的上游程序发现输出流已关闭。 在我看来,这是head本身设计的一个限制。 您可以改为使用sed ,它读取整个流: sed -n "1,10p"等效于head -n10

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM