Objective
As described here:
Parent does not wait for child process inside process substitution. wait
command is also ignored.
Due to this, for example, following can occur:
|
|
What’s happening here is that, prompt is returning before child process cat
completes outputting all sequences from 1 to 5.
This article shows some example of implementing workaround, to wait for child.
Process substitution shines for bash logging
In bash, you can prepend message to stdout and stderr by doing below:
|
|
exec > >(prepend_info)
in this line, stdout is redirecting output to function prepend_info
.prepend_info
then calls echo_info
, outputting the passed stdout message with some additional info before it.
Similar thing is happening with exec 2> >(prepend_err)
, but with stderr.
Below those code, I further add following codes
|
|
Following is the otuput I get when executed
|
|
We now have a script which adds time and pid in from of stdout and stderr message:
2020-10-05T06:32:41+0000 117310 INFO: Hello World
2020-10-05T06:32:41+0000 117310 ERROR: Redirecting this msg to stderr
However notice that there’s two issues from in above result
- Prompt is waiting for user input before outputting all messages
- Order of echo is out of order
(1) is due to aforementioned “process substitution not waiting for child”. In the next section, I have implemented the workaround.
(2) is due to multiprocessing. Essentially the second echo is completing more faster than the first echo. It will be difficult to avoid and will not be covered in this article.
Implementing workaround
Implementing workaround is fairly simple.
You just have to wrap all your commands with { var_name=$( {
and } 3>&1 >&4 4>&-); } 4>&1
.
Here’s my full script after implementing the workaround.
|
|
When I run this, prompt now waits for parent and child process to finish.
|
|
What if I want to output to stdout and stderr without extra info
execs that forward output to function are declared to capture fd 1 (default stdout) and fd 2 (default stderr).
This means, you can avoid it by outputting to different fd.
This fd can be file, as shown in first example.
Or this fd can be a copy of stdout and stderr as shown in second example.
Example 1: Outputting stdout/stderr to file
|
|
Example 2: Making copied fd of stdout and stderr
|
|
Notice the exec 8>&1
and exec 9>&2
at the top of the script. This is making copy of fd 1 (stdout) and fd 2 (stderr).
You will redirect to fd 8 for stdout and fd 9 for stderr.