从子 shell 读取 stdout/stderr 到父 shell

从子 shell 读取 stdout/stderr 到父 shell

在 shell 脚本中,我想使用命名管道写入外部进程 X 的 stdin,并且想将 stdout/stderr 从另一个命名管道发送到当前终端。

外部进程 X 通过 PIPEIN 接收 stdin,并将其 stdout/stderr 发送到 PIPEOUT。

tail -f $(tail -F PIPEOUT) &  # (1) this is completely wrong, need help here

for i; do
    echo "${i}" > PIPEIN  # send stdin to X
done

echo "[stdin end]" > PIPEIN  # signal that we are done writing (there might be a better way lol)

所以在上面的脚本中,我们已经启动了进程X,它已经运行了一段时间。但是现在,当我们运行上面的脚本时,我们想要向 X 发送一些标准输入,并且我们想要使用 PIPEOUT 从进程 X 中读取标准输出。

我上面想做的是在将 stdin 发送到 X 之前设置对 PIPEOUT 的读取,以确保捕获 X 的所有 stdout/stderr 。问题是我不知道如何运行某些后台进程(tail 或 cat 从 PIPEOUT 读取)并将该 stdio 发送到当前终端。

有谁知道我在说什么。如果我没有记错的话,我只需要修复标记为 (1) 的行,并以某种方式在后台设置一个读取,可以从 PIPEOUT 读取并将该 stdio 以某种方式发送到当前终端/tty。

答案1

我不清楚你想做什么tail -f $(tail -F PIPEOUT) &。这是tail -fing 文件是的结果 tail -F,通常永远不会终止。我的假设是您希望输出通过管道的所有内容,无论需要多长时间。

just 的问题tail -f是它必须在输出任何内容之前找到文件的末尾,而对于管道来说这永远不会发生。你可以给出tail一个明确的起点,而不是-n +x,选择起始行(从头开始,从 1 开始索引)。tail -n 1 -f foo将显示它可以从中获取的所有内容foo

tr 'a-z' 'A-Z' < PIPEIN > PIPEOUT & # for example
tail -n +1 -f PIPEOUT &
for i in a b c d ; do
    echo $i > PIPEIN
done
echo "[stdin end]" > PIPEIN

但请注意,这echo > foo将在写入该行后关闭 foo — 另一端的命令需要乐意处理该问题。如果这个例子是人为的并且真实的输入来自其他地方,你可以忽略它。


另请注意tail过程永远不会终止——它一直期待着更多的东西可能会通过管道。您必须自己显式地杀死它,也许可以使用 shell 的作业控制。如果输出中有某种模式表明它已完成,您可能会发现retail(“带有正则表达式的尾部”)有用 -retail -n +1 -f -u REGEX PIPEOUT当出现匹配的行时将终止REGEX(作为免责声明,我retail几年前为此目的撰写了这篇文章)

答案2

仅打开 PIPEIN 进行写入一次,程序就会终止 - 即使有 2 秒的延迟:

mkfifo PIPEIN PIPEOUT
tr 'a-z' 'A-Z' < PIPEIN > PIPEOUT & # for example
tail -n +1 -f PIPEOUT &
(
for i in a b c d ; do
    echo $i
done
sleep 2
echo "[stdin end]"
) > PIPEIN

如果您多次打开 fifo,则 fifo 的读取器可能会认为它已关闭,因此写入器将被挂起,直到另一个读取器从 fifo 读取数据。

所以保存的赌注是只打开 PIPEIN 一次。否则您可能会看到程序锁定。

相关内容