防止自动 EOF 发送到命名管道,并在需要时发送 EOF

防止自动 EOF 发送到命名管道,并在需要时发送 EOF

我有一个程序,在读取给定流中的 EOF 时自动退出(在以下情况下为 stdin )。
现在我想制作一个 shell 脚本,它创建一个命名管道并将程序的标准输入连接到它。然后脚本写入管道几次使用echoand cat(以及其他退出时自动生成 EOF 的工具)。我面临的问题是,当第一个echo完成时,它会向管道发送一个 EOF 并使程序退出。如果我使用类似的东西tail -f,那么当我打算退出程序时我无法发送 EOF。我正在研究一个平衡的解决方案,但无济于事。
我已经找到了如何防止 EOF 以及如何手动发送 EOF,但我无法将它们结合起来。有什么提示吗?

#!/bin/sh
mkfifo P
program < P & : # Run in background
# < P tail -n +1 -f | program
echo some stuff > P # Prevent EOF?
cat more_stuff.txt > P # Prevent EOF?
send_eof > P # How can I do this?
# fg

答案1

正如其他人所指出的,一旦没有写入者,管道的读取器就会收到 EOF。因此,解决方案是确保始终有一位作家将其打开。该作者不必发送任何内容,只需将其打开即可。

由于您使用的是 shell 脚本,最简单的解决方案是告诉 shell 打开管道进行写入。然后完成后关闭它。

#!/bin/sh
mkfifo P
exec 3>P # open file descriptor 3 writing to the pipe
program < P
# < P tail -n +1 -f | program
echo some stuff > P
cat more_stuff.txt > P
exec 3>&- # close file descriptor 3

请注意,如果省略最后一行,则当脚本退出时,文件描述符 3 将自动关闭(因此读取器会收到 EOF)。除了方便之外,如果脚本以某种方式提前终止,这还提供了某种安全性。

答案2

当最后一个写入者消失时,管道会收到 EOF。为了避免这种情况,请确保始终有一个写入器(一个打开管道进行写入但实际上不写入任何内容的进程)。要发送 EOF,请让保留写入者消失。

mkfifo P
while sleep 1; do :; done >P &
P_writer_pid=$!
send_eof_to_P () {
  kill $P_writer_pid
}

答案3

程序无法区分 EOF 表示“是时候退出了”,而 EOF 表示“编写完成,但可能还有其他人的输入”。

如果您有能力修改程序的行为,则可以在无限循环中进行读取(一次迭代持续到 EOF),并向其发送一个表示“退出时间”的特定命令字符串。发送该字符串将是send_eof您问题中的命令的任务。

另外一个选择:

( echo some stuff; cat more_stuff.txt ) >P

或者

{ echo some stuff; cat more_stuff.txt; } >P

相关内容