我有一个命令,我将运行以生成随机字符串:
var=`< /dev/urandom tr -dc _A-Z-a-z-0-9 | head -c8`
当我在交互式bash会话中运行此命令时,我绝对没有错误。但是,当我将此命令放入脚本并将其作为脚本运行时,我得到了由tr指示的Broken pipe错误。我已经阅读了几个相关的主题,但仍然没有答案为什么脚本和交互行为是不同的,有没有办法用shell选项或其他东西来控制它?
编辑I:
关于给出的评论,我发现可以通过以下方式控制管道损坏错误:
trap - SIGPIPE # to ignore errors
和
trap "" SIGPIPE # to display errors
编辑II:
好吧,我提供了有关复制条件的错误信息。最后,似乎问题是python包装器使用os.system()调用脚本:
python -c "import os; os.system('sh -c \"< /dev/urandom tr -dc _A-Z-a-z-0-9 | head -c8\"')"
给定的行会产生与使用过的操作系统无关的管道错误。
编辑III:
此主题已在此处讨论: https://mail.python.org/pipermail/python-dev/2005-September/056341.html
答案 0 :(得分:5)
如果其中一个父进程陷阱sigpipe
,那么管道将继承ignore
信号处理,这将导致您遇到此问题。
这可以(安全地)复制:
( trap '' pipe; var=`< /dev/urandom tr -dc _A-Z-a-z-0-9 | head -c8 )
通常,head -c8
命令很快就会完成,stdin
关闭。由于stdin
是与stdout
的{{1}}连接的管道,因此tr
写入其tr
现在不再有意义了。一旦尝试,系统将使用stdout
将其终止。
除非SIGPIPE
忽略此信号或已从其父级继承此信号的tr
(ignore
)处置。然后,SIG_IGN
到write
已损坏的tr
只会导致定期错误,并将stdout
设置为errno
,此时EPIPE
最多可能会将此错误字符串化并输出到tr
并退出。
答案 1 :(得分:1)
This answer提供了从Python到head
的管道问题的一个很好的总结,并显示了一些解决方法。
答案 2 :(得分:0)
问题似乎是 head
从输入流中读取指定(或默认)行数,打印它们,然后退出。因此,仍在写入的管道中的上游程序发现输出流已关闭。在我看来,这是 head
本身设计的一个限制。您可以改为使用 sed
,它读取整个流:sed -n "1,10p"
等效于 head -n10
。