55

In a bash script, how can I redirect all standard outputs to a log file and tee the output on the screen using exec ?

log_file="$HOME/logs/install.txt-`date +'%Y-%m-%d_%H-%M-%S'`"
[ -f "$log_file" ] || touch "$log_file"
exec 1>> $log_file 2>&1

This code redirect all the log to the log file but not to the screen .

4m1nh4j1
  • 1,873
  • 9
  • 29
  • 41
  • 2
    May be the answer looks the same, but it was not the same question. – 4m1nh4j1 Jul 21 '14 at 08:28
  • No, it is the exact same question. The first sentence describes what it's trying to do, and it's exactly what you're trying to do: "redirect all output to one file, debug log as well as to the terminal" – phemmer Jul 21 '14 at 12:44

2 Answers2

107

Use process substitution with & redirection and exec:

exec &> >(tee -a "$log_file")
echo "This will be logged to the file and to the screen"

$log_file will contain the output of the script and any subprocesses, and the output will also be printed to the screen.

  • >(...) starts the process ... and returns a file representing its standard input.

  • exec &> ... redirects both standard output and standard error into ... for the remainder of the script (use just exec > ... for stdout only).

  • tee -a appends its standard input to the file, and also prints it to the screen.

Michael Homer
  • 76,565
  • 1
    It works, but sometimes I still get output when I already have my console prompt, resulting in a mixed output. – Halfgaar Oct 28 '15 at 09:15
  • 1
    @Halfgaar - That is expected as exec replace the process including file descriptors for STDIN, STDOUT and STDERR - effectively detaching it from the terminal but tee continues to emit anything it receives. – shalomb Mar 29 '16 at 09:55
  • 1
    On Mac this just simply hangs forever! – Prav Jan 02 '21 at 16:30
  • @PraveenPremaratne that may be something to ask another question about, but in general, no, it doesn't. – Michael Homer Jan 03 '21 at 00:59
  • I thought I had the same result on Linux as Praveen, but it turned out that I was at the command prompt. If I type something, I get command not found. If I add an exit to the script, I get my command prompt back. I'm testing using a script with just a single echo statement. – Vince May 03 '21 at 04:18
  • Is $ a special command character or are you writing to a file names $log_file in the current directory? – Jonathon May 23 '22 at 04:27
  • Looks like this method fails on Alpine Linux which uses busybox sh instead of bash: sh: syntax error: unexpected redirection – xref Sep 20 '22 at 22:15
  • 1
    @xref This question is specifically about Bash, but the accepted answer in the duplicate question ought to work under POSIX sh at the cost of wrapping the body in braces, with more or less the same execution. – Michael Homer Nov 05 '22 at 02:32
8
exec >> $log_file 2>&1 && tail $log_file
Farhadix
  • 189