如何在不使用临时文件的情况下在子进程中实现延迟标准输出?

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.shinner.shmiddle进程生成的所有其他消息之后安排延迟消息。
生成的标准输出必须如下:

Text1
Text2
Deferred Message
Run Code Online (Sandbox Code Playgroud)

要求:

  • outer.sh应该调用middlemiddle并将调用inner.sh)。
  • inner.sh 必须在某处记住它的参数(延迟消息)
  • 之后middle被终止,outer.sh必须回顾推迟的消息,并打印到stdout
  • 会有很多outer.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)

我应该在哪里保存子进程中的延迟消息以及如何在父进程中读取它?

Sté*_*las 7

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不需要用它做任何事情。