Sending STDERR to logger
Im writing a bash-script to perform an offsite backup, using rsync over SSH. 开发者_如何学JAVAI'm able to send STDOUT to logger, 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 that offsite is unavailable, that output should be sent to logger and logged.
You can redirect the STDERR descriptor (2) to STDOUT (1) by adding 2>&1
, for example:
rsync --del -az -e 'ssh -i mycrt.crt' /home/gnutt/backup/ me@offisite:backup 2>&1 | logger -i
If you want stderr instead of stdout (rather than stderr AND stdout), you can do the following:
- open another file descriptor (9)
- redirect stdout (1) to the 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
Alternately, you could employ process substitution:
logger -i <( rsync --del -az -e 'ssh -i mycrt.crt' /home/gnutt/backup/ me@offisite:backup > /dev/null )
One other way of ensuring your script errors are captured as well as the rsync errors, is to do something like this:
#!/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 the data written to stderr will be logged, not just that from rsync. However, ignoring stdout
is typically a bad idea when it comes to debugging, since useful information that could highlight the cause of an error could be logged there. If you want to differentiate between stderr and stdout, just don't cross the streams:
exec 1> >(logger -t "stdout-from-my-script") 2> >(logger -t "stderr-from-my-script")
To explicitly close the handles or restore them, 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 have to be a bit more blunt:
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>&-
精彩评论