Sending STDERR to the Registrar

Im writing a bash - script to do an offsite backup using rsync via SSH. I can send STDOUT to the registrar, for logs via

rsync --del -az -e 'ssh -i mycrt.crt' /home/gnutt/backup/ me@offisite:backup | logger -i

But I want to send STDERR instead, so if there is a problem such as this offsite is not available, this output should be sent to the log and logged.

+5
source share
3 answers

If you want stderr instead of stdout (and not stderr AND stdout), you can do the following:

  • open another file descriptor (9)
  • redirect stdout (1) to a new file descriptor (9)
  • redirect stderr (2) to stdout (1)

Which looks like this:

rsync --del -az -e 'ssh -i mycrt.crt' /home/gnutt/backup/ me@offisite:backup 9> /dev/null 1>&9 2>&1 | logger -i

Alternatively, you can use process overriding:

logger -i <( rsync --del -az -e 'ssh -i mycrt.crt' /home/gnutt/backup/ me@offisite:backup > /dev/null )
+5

STDERR (2) STDOUT (1), 2>&1, :

rsync --del -az -e 'ssh -i mycrt.crt' /home/gnutt/backup/ me@offisite:backup  2>&1 | logger -i
+6

script, rsync - - :

#!/bin/bash

set -eu
set -o pipefail

exec 1>/dev/null 2> >(logger -t "stderr-from-my-script")

: do some interesting things

rsync --del -az -e 'ssh -i mycrt.crt' /home/gnutt/backup/ me@offisite:backup

: do some other interesting things

Now all data written to stderr will be written, not just from rsync. However, ignoring stdoutit is usually a bad idea when it comes to debugging, as it may be useful information that could suggest the cause of the error. If you want to distinguish between stderr and stdout, just don't cross the threads:

exec 1> >(logger -t "stdout-from-my-script") 2> >(logger -t "stderr-from-my-script")

To explicitly close or restore descriptors, consider the following:

exec {OLD_STDOUT}>&1 {OLD_STDERR}>&2 1> >(logger -t "stdout-from-my-script") 2> >(logger -t "stderr-from-my-script")

: Do some interesting things

eval exec 1>&${OLD_STDOUT} 2>&${OLD_STDERR} ${OLD_STDOUT}>&- ${OLD_STDERR}>&-

For older versions of bash, you might need a little more stupidly:

exec 3>&1 4>&2 1> >(logger -t "stdout-from-my-script") 2> >(logger -t "stderr-from-my-script")

: Do some interesting things

exec 1>&3 2>&4 3>&- 4>&-
+2
source

All Articles