Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What does exec 3>&1 4>&2 1>>/tmp/output.log2>&1 do in a bash script? [duplicate]

Tags:

bash

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?

like image 694
BTR Naidu Avatar asked Mar 21 '26 15:03

BTR Naidu


1 Answers

exec 3>&1 4>&2 1>>/tmp/output.log 2>&1 does the following:

  1. make file descriptor 3 a copy of stdout
  2. make file descriptor 4 a copy of stderr
  3. redirect-append stdout to file /tmp/output.log
  4. make stderr a copy of stdout

File 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
...
like image 102
Renaud Pacalet Avatar answered Mar 25 '26 00:03

Renaud Pacalet



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!