Logo Questions Linux Laravel Mysql Ubuntu Git Menu

bash script duplicating i/o using a file descriptor like it were tee

I would like to route a file descriptor to multiple places at the same time. For instance I would like every command in my script to print stdout to /dev/ps/9 and ./myscript.stdout at the same time.

I'm looking to achieve similar results as piping every command in a script (or a section of a script) into tee, perhaps with file descriptors. I also want the ability to restore default output behavior later in the script.

This code doesn't work, but it's an attempt at expressing my intent. To restore stdout as FD 1 later, I copy it into FD 4.

exec 3>(tee /dev/ps/9 ./myscript.stdout)
exec 4>&1
exec 1>&3

Restore normal output behavior, deleting FDs 3 and 4.

exec 1>&4
exec 4>&-
exec 3>&-
like image 587
Shane Avatar asked Mar 19 '23 13:03


1 Answers

I would like every command in my script to print stdout to /dev/ps/9 and ./myscript.stdout at the same time.

exec 1> >(tee ./myscript.stdout >/dev/ps/9)

The above combines redirection and process substitution. With redirection alone, one can send stdout to a file. For example:

exec 1> filename

However, with bash, filenames can often be replaced with commands. This is called process substitution and it looks like >(some command) or <(some command) depending on whether one wants to write-to or read-from the process. In our case, we want to write to a tee command. Thus:

exec 1> >(some command)

Or, more specifically:

exec 1> >(tee ./myscript.stdout >/dev/ps/9)

Note that we have to maintain the space between the redirect (1>) and the process substitution (>(tee ./myscript.stdout >/dev/ps/9). Without the space, it would look like we were trying to append to a file whose name starts with a parens and this would generate a bash error.

For more information on this see the sections entitled "REDIRECTION" and "Process Substitution" in man bash.

like image 117
John1024 Avatar answered Apr 07 '23 04:04