Dienstag, 28. Oktober 2014

Redirecting stdout and stderr into files without loosing the original file descriptors

Redirecting in Bash can be tricky. But in order to log the output of shell commands it is sometimes necessary. Sometimes it is also necessary to add some time stamps in front of the output. And sometimes it is even necessary to save the original file descriptors. The following example shows how to do all of that.

#! /bin/bash

stamp ()
{
  local LINE
  while IFS='' read -r LINE; do
    echo "$(date '+%Y-%m-%d %H:%M:%S,%N %z') $$ $LINE"
  done
}

exec {STDOUT}>&1
exec {STDERR}>&2
exec 2> >(exec {STDOUT}>&-; exec {STDERR}>&-; exec &>> stderr.log; stamp)
exec > >(exec {STDOUT}>&-; exec {STDERR}>&-; exec >> stdout.log; stamp)

for n in $(seq 3); do
  echo loop $n >&$STDOUT
  echo o$n
  echo e$n >&2
done

Some best practices followed in the code are:

  • Declare local variables as local.
  • Use named file descriptors to avoid collisions.
  • Close unused file descriptors in sub shells.

First I tied to solve my problem with the answers given at Stackexchange. But the answers where not elaborated enough for my needs. So I wrote the above answer.

BTW this is a nice overview for the different ways to redirect in Bash.

Keine Kommentare: