Redirect stdout and stderr to file permanently but keep printing them

Viewed 2343

By doing the following(1):

 exec >> log_file
 exec 2>&1
 ls

stdout and stderr is permanently redirected for the next commands but not anymore displayed on terminal. Here, ls output will be in log_file but not displayed in terminal

By doing the following(2):

command | tee log_file

command output will be both in log_file and printed on terminal but this will work only for command and not for the next commands as method 1.

How to redirect permanently stdout and stderr output in a file for a given terminal like method 1 and, keep stdout and stderr printed on the terminal instance like method 2 ?

2 Answers

I currently use this in my scripts:

exec > >(tee -a "${FILE_Log}" )
exec 2> >(tee -a "${FILE_Log}" >&2)

Basically you are telling bash to send the output (both stdout and stderr) to tee's stdin, and since tee is running in the subshell (within the parentheses), it will live as long as your script does.

Put that somewhere near the top, then any and all command output, echo, print, and, printf will be logged.

This saves having to create a LOG() function and constantly piping commands to tee

Hope that helps!

Using tee and redirection combined:

(exec 2>&1) | tee file.txt

Here's an example

[root@box ~]# (ll 2>&1) | tee tmp.txt
total 4
-rw-------. 1 root root 1007 Apr 26  2017 anaconda-ks.cfg
[root@box ~]# cat tmp.txt
total 4
-rw-------. 1 root root 1007 Apr 26  2017 anaconda-ks.cfg

The reason the command is inside paranthesis is to keep the order of the prints, since stdout is buffered. It causes the ll command to be executed in a subshell, and then return the output of stdout + stderr in-order.

Related