nullByteMe
nullByteMe

Reputation: 6391

Redirect stderr to logger and then to file

I'm trying to take stderr from a command and redirect it to the logger -s command (which writes its input to syslog and the -s option sends a copy of the input to logger's standard error) and then finally to a file like this:

#!/bin/bash

ping foobar 2> logger -s 2>> ~/mylog.log

Unfortunately, this creates a logger file and a mylog.log file. So I'm assuming the initial 2> creates a logger file and then the 2>> creates a new mylog.log file.

Is there anyway to redirect stderr to the logger command?

EDIT

I'm trying to avoid using | because I want to use the redirection in if tests as well.

I also tried this way:

ping foobar 2> $(logger -s 2>> ~/mylog.log)

And that didn't work either.

Upvotes: 2

Views: 5900

Answers (3)

Jonathan Leffler
Jonathan Leffler

Reputation: 755104

Given the manual page for logger, you were looking for bash's process substitution and:

ping foobar 2> >(logger -s 2>> ~/mylog.log)

This runs ping foobar with standard error going to the process logger -s via process substitution. The logger process writes the information to syslog (the primary purpose of logger) and also writes the output to standard error (the -s option). The second I/O redirection appends the standard error from logger to the file ~/mylog.log.

The return status of the command is the return status from ping. This avoids pipes, so you can use the command as written in if tests, etc.

Upvotes: 7

ctn
ctn

Reputation: 2930

You can't normally redirect to multiple files. That's what tee is for. Also, if you're gonna use tee you need to use a pipe.

ping foobar 2>&1 >/dev/null | tee -a ~/mylog.log | logger

This redirects stderr to stdout and then stdout to /dev/null. tee appends its input to file ~/mylog.log (-a is for append) and also copies it to output, which is then piped to logger.

If you want to use any resulting complex command in an if test you can put the command in a function. You can use bash's $PIPESTATUS to check each exit status in the pipe (and return it from the function):

function bla {
    ping | successful_cmd   # ... or whatever
    [ 0 -eq ${PIPESTATUS[0]} ]   # return 0 (true) if the exit status of ping was 0 (true)
}

The return status of the function will be the the return status of the last command executed. You can use the function like this:

if bla; then echo true; else echo false; fi
# or
bla && echo success

Upvotes: 1

ferhtgoldaraz
ferhtgoldaraz

Reputation: 1863

If you only want stderr...

ping foobar  3>&1 1>&2 2>&3 | logger >> ~/mylog.log

This should swap sderr and stdout.

Upvotes: 2

Related Questions