如何在管道关闭时提前退出?

Ksh*_*rma 5 scripting bash pipe

我使用 golang 来编写过于复杂而无法表达为 bash 函数的程序。程序逐行读取标准输入并将修改后的输出写入标准输出。

在 stdin 方法中迭代所有行的问题在于它不会提前退出。例如,以下命令将处理所有行而不是 10 行:

cat largefile | custom-program | head -n 10
Run Code Online (Sandbox Code Playgroud)

本机 unix 应用程序如何设法提前退出,我如何在自定义脚本中执行相同操作?

Sté*_*las 14

yes | head,yes下一次在管道的另一端关闭后(head退出时)写入一行时,由 SIGPIPE 信号终止。

在:

(seq 20; sleep 10; seq 10) | head
Run Code Online (Sandbox Code Playgroud)

子shell 和子shell 将能够将前20 行写入管道(适合管道缓冲区),然后会安然入睡10 秒。同时,head将已死亡,但只有当子shell 向管道写入更多行时,它才会被杀死。

如果您希望您的命令在head返回后立即被终止,而不是在返回后第一次向管道写入内容headbash您可以这样做:

{ head; kill "$!"; } < <(exec custom-program < large-file)
Run Code Online (Sandbox Code Playgroud)

bash恰好将进程替换的 pid 存储在 中$!)。

另请参阅Grep 在找到匹配项后缓慢退出?对于更便携的方法,或限制查找输出并避免将信号 13应用到find

或者相反,这个答案(run_under_watch函数)与类似的问答类似,一旦它的标准输入变成一个破损的管道就杀死一个进程。