I saw something like this in a bash script
exec 3>&1 4>&2 1>>/tmp/output.log 2>&1
As far I understand, the stdout is redirected to a new fd 3 and stderr to 4. What does 1 and 2 fd hold then and what does it mean to redirecto 1>> file as well 2>&1?
I see the output as well as err from the script is written to /tmp/output.log.
I want the script to write stdout and stderr to the /tmp/output.log as well as display in console while it is running. How should the redirection look like?
exec 3>&1 4>&2 1>>/tmp/output.log 2>&1 does the following:
stdoutstderrstdout to file /tmp/output.logstderr a copy of stdoutFile descriptors 3 and 4 are maybe used here as temporary storage, such that the initial stdout and stderr can be restored with exec 1>&3 2>&4.
The third redirection sends stdout to /tmp/output.log in append mode. The last redirection makes stderr a copy of stdout, that is, also sends stderr to /tmp/output.log in append mode. Note that the order of these 4 redirections matters.
I want the script to write stdout and stderr to the /tmp/output.log as well as display in console while it is running. How should the redirection look like?
Redirect stdout to a tee -a /tmp/output.log command using process substitution. Then redirect stderr to stdout. Example:
$ cat foo
#!/usr/bin/env bash
# redirect
exec 1> >( tee -a /tmp/output.log ) 2>&1
ls -z
echo "foo"
$ ./foo
ls: invalid option -- 'z'
Try 'ls --help' for more information.
foo
$ cat /tmp/output.log
ls: invalid option -- 'z'
Try 'ls --help' for more information.
foo
If at one point in your script you want to restore stdout and stderr to their original state you can use the same trick as in the example you found:
$ cat foo
#!/usr/bin/env bash
# redirect
exec 3>&1 4>&2 1> >( tee -a /tmp/output.log ) 2>&1
ls -z
echo "foo"
...
# restore
exec 1>&3 2>&4
...
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With