尽管管道坏了,Bash 并没有结束循环

标签 bash loops while-loop stream pipeline

简单的脚本:

while [ 1 ]; do
    cat pattern_file
done | socat - /dev/ttyS0

它使文件中包含一个流、循环模式,并通过 socat 将其发送到串行端口。该脚本还允许从串口读回数据。 不幸的是,当 socat 结束(例如被杀死)时,循环永远挂起而没有任何错误消息。
我想避免:

  • 多个脚本
  • 每隔pattern_file重新打开串口

最佳答案

您遇到的问题是,在 bash(其他 shell 可能不同)下,管道仅在管道中的所有命令完成后终止。

一种解决方案是使用:

while [ 1 ]; do
    cat pattern_file || break
done | socat - /dev/ttyS0

如果 socat 终止,那么 cat 命令在运行时将失败。但是,循环中命令的简单失败不会导致循环终止。通过添加 break 命令,我们可以确保,如果 cat 失败,则循环将终止。

另一种解决方案是完全避免管道并使用进程替换:

socat - /dev/ttyS0 < <(while true; do cat pattern_file; done)

文档

man bash 中记录了有问题的管道行为:

The shell waits for all commands in the pipeline to terminate before returning a value.

关于尽管管道坏了,Bash 并没有结束循环,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27503455/

相关文章:

bash 提示符 : highlight command being entered

azure - ForEach-Object - 尝试 for 循环变量中的每个地址

Perl,在循环外使用来自 While 循环内的变量?

java - 尝试获取代码来检查是否有偶数括号

linux - 脚本在手动运行时完全运行,但在从另一个脚本运行时会丢失命令

linux - bash 脚本可能需要 root 权限

javascript - 从颜色渐变数组构建对象

php - 数组循环假设为零数据?

oracle - PL SQL 中的 WHILE 循环有什么问题?

bash - 在 Mac 命令行上使用 sed 时无法替换换行符