I have a program (let's name it middle
) which I can't modify.
This program performs the following sequence of steps:
middle
sends some text to stdout (echo Text1
)middle
invokes shell scriptinner.sh
passing some text string (4 KBytes or less) as argument (inner.sh "Deferred Message"
)middle
sends some text to stdout (echo Text2
)
My task is to create two bash scripts outer.sh
and inner.sh
to arrange deferred message after all the other messages generated by middle
process.
The resulting stdout must be the following:
Text1
Text2
Deferred Message
The requirements:
outer.sh
should invokemiddle
(andmiddle
will invokeinner.sh
).inner.sh
must remember its argument (deferred message) somewhere- After
middle
is terminated,outer.sh
must recall the deferred message and print it to stdout - There will be a lot of
outer.sh
processes running simultaneously. The deferred message must be stored in a place which is local to current instance ofouter.sh
process - Creation of temporary objects in file system is prohibited. (Is it possible to store the deferred message somewhere in memory?)
inner.sh
# Where should I save message "$1"?
outer.sh
middle "$@"
# How should I recall and print the deferred message?
Where should I save the deferred message in child process and how to read it back in parent process?
Best Answer
inner.sh
could be:and in
outer.sh
, you could do:The inner text is passed via a pipe (in the command substitution) and stored in a shell variable. That assumes
middle
doesn't close that fd 3 before invokinginner.sh
(no reason it would do that though).Explanation:
{ ... } 4>&1
. In that command group, initially, both fd 1 and 4 point to the original stdout. IOW, we've made a copy of outer.sh's stdout onto fd 4 to be able to recover it inside the command substitution$(...)
. Inside that command substitution, stdout (fd 1) is a pipe. That's the point of command substitution. It wants to grab the output of the command. But here, we don't want the stdout ofmiddle
, we want what it (or more exactly its childinner.sh
) writes on fd 3, so:middle 3>&1 >&4 4>&-
: formiddle
, we make fd 3 the cmdsubst pipe, so that whatinner.sh
writes there goes into$inner
, and we restoremiddle
's stdout onto the saved original stdout on fd 4. We close fd 4 after it has served it's purpose asmiddle
doesn't need to do anything with it.