Ego*_*off 4 bash io-redirection stdout
我有一个middle我无法修改的程序(让我们命名它)。
该程序执行以下步骤序列:
middle将一些文本发送到 stdout ( echo Text1)middle调用 shell 脚本inner.sh传递一些文本字符串(4 KB 或更少)作为参数 ( inner.sh "Deferred Message")middle将一些文本发送到 stdout ( echo Text2)我的任务是创建两个 bash 脚本outer.sh并inner.sh在middle进程生成的所有其他消息之后安排延迟消息。
生成的标准输出必须如下:
Text1
Text2
Deferred Message
Run Code Online (Sandbox Code Playgroud)
要求:
outer.sh应该调用middle(middle并将调用inner.sh)。inner.sh 必须在某处记住它的参数(延迟消息)middle被终止,outer.sh必须回顾推迟的消息,并打印到stdoutouter.sh进程同时运行。延迟消息必须存储在当前outer.sh进程实例的本地位置内部文件
# Where should I save message "$1"?
Run Code Online (Sandbox Code Playgroud)
外部文件
middle "$@"
# How should I recall and print the deferred message?
Run Code Online (Sandbox Code Playgroud)
我应该在哪里保存子进程中的延迟消息以及如何在父进程中读取它?
inner.sh 可能:
printf '%s\n' "$1" >&3
Run Code Online (Sandbox Code Playgroud)
在 中outer.sh,您可以执行以下操作:
{ inner=$(middle "$@" 3>&1 >&4 4>&-); } 4>&1
printf '%s\n' "$inner"
Run Code Online (Sandbox Code Playgroud)
内部文本通过管道(在命令替换中)传递并存储在 shell 变量中。这假设middle在调用之前不会关闭那个 fd 3 inner.sh(虽然它没有理由这样做)。
解释:
{ ... } 4>&1. 在该命令组中,最初,fd 1 和 4 都指向原始标准输出。IOW,我们已经将outer.sh的标准输出复制到fd 4上,以便能够在命令替换中恢复它$(...). 在该命令替换中,stdout (fd 1) 是一个管道。这就是命令替换的重点。它想获取命令的输出。但是在这里,我们不想要 的标准输出middle,我们想要它(或更确切地说它的孩子inner.sh)在 fd 3 上写的内容,所以:middle 3>&1 >&4 4>&-:对于middle,我们将 fd 3 设为 cmdsubst 管道,这样inner.sh写入的内容就会进入$inner,然后我们将middle的 stdout恢复到fd 4上保存的原始 stdout。我们在 fd 4 达到目的后关闭它,因为middle不需要用它做任何事情。