我有一个生成随机字符串的命令:
var=`< /dev/urandom tr -dc _A-Z-a-z-0-9 | head -c8`
当我在交互式 bash session 中运行此命令时,我完全没有收到任何错误。但是当我将此命令放入脚本并将其作为脚本运行时,我得到了 tr 指示的 Broken pipe 错误。我已经阅读了几个相关主题,但仍然没有答案为什么脚本和交互行为不同,有没有办法用 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
是连接到 tr
的 stdout
的管道,所以现在 tr
不再有意义写入其 stdout
。一旦尝试,系统将使用 SIGPIPE
杀死它。
除非 tr
忽略此信号或已从其父级继承此信号的 ignore
(SIG_IGN
) 处置。然后 write
到 tr
损坏的 stdout
只会导致常规错误并将 errno
设置为 EPIPE
此时 tr
最有可能将此错误字符串化并将此错误输出到其 stderr
并退出。
关于python - 管道连接导致从 python 调用的 shell 脚本中的管道损坏,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33020759/