管道连接导致 shell 从 python 调用的脚本中的管道损坏
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 指示的 Broken pipe 错误。我已经阅读了几个相关主题,但仍然没有答案为什么脚本和交互行为不同,有没有办法通过 shell 选项或其他方式来控制它?
编辑我:
关于给出的评论,我发现指示破损的管道错误可以通过以下方式控制:
trap - SIGPIPE # to ignore errors
和
trap "" SIGPIPE # to display errors
编辑二:
好吧,我提供了有关复制条件的错误信息。最后,问题似乎是由 python 包装器引起的,该包装器使用 os.system():
调用脚本
python -c "import os; os.system('sh -c \"< /dev/urandom tr -dc _A-Z-a-z-0-9 | head -c8\"')"
给定的行会独立于使用的 OS.
产生损坏的管道错误
编辑三:
这里讨论了这个话题:
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
并退出。
This answer 很好地总结了从 Python 到 head
的管道问题,并显示了一些解决方法。
问题似乎是 head
从输入流中读取指定(或默认)行数,打印它们,然后退出。因此,仍在写入的管道中的上游程序发现输出流已关闭。在我看来,这是head
本身设计的一个局限。您可以改为使用 sed
,它读取整个流:sed -n "1,10p"
等同于 head -n10
.
我有一个命令 运行 生成随机字符串:
var=`< /dev/urandom tr -dc _A-Z-a-z-0-9 | head -c8`
当我在交互式 bash 会话中 运行 此命令时,我绝对没有错误。但是,当我将此命令放入脚本并将其作为脚本 运行 时,我得到了 tr 指示的 Broken pipe 错误。我已经阅读了几个相关主题,但仍然没有答案为什么脚本和交互行为不同,有没有办法通过 shell 选项或其他方式来控制它?
编辑我:
关于给出的评论,我发现指示破损的管道错误可以通过以下方式控制:
trap - SIGPIPE # to ignore errors
和
trap "" SIGPIPE # to display errors
编辑二:
好吧,我提供了有关复制条件的错误信息。最后,问题似乎是由 python 包装器引起的,该包装器使用 os.system():
调用脚本 python -c "import os; os.system('sh -c \"< /dev/urandom tr -dc _A-Z-a-z-0-9 | head -c8\"')"
给定的行会独立于使用的 OS.
产生损坏的管道错误编辑三:
这里讨论了这个话题: 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
并退出。
This answer 很好地总结了从 Python 到 head
的管道问题,并显示了一些解决方法。
问题似乎是 head
从输入流中读取指定(或默认)行数,打印它们,然后退出。因此,仍在写入的管道中的上游程序发现输出流已关闭。在我看来,这是head
本身设计的一个局限。您可以改为使用 sed
,它读取整个流:sed -n "1,10p"
等同于 head -n10
.