Mario
Mario

Reputation: 1042

catch error message and create Journal entry

The following code I put on top of many scripts I am using...

#!/bin/bash

# redirect all error messages to the protocol,
# then print the same message to stdout
exec 1> >(logger -i -s -t $0 -p 4) 2>&1

This line of code will make protocol entries of errors occurred while running my scripts. But this code doesn't work like I want when communicate via stdin and stdout. I want to log error messages only.

And to be honest, I don't know how I managed to get this line of coding to work.

Nonetheless, I am searching for a code to replace this combination of exec and logger with a function put in trap "createErrorMessage" ERR. But I don't know how to catch/receive error messages this way.

My goal is to create protocol entries of all error messages only.

To be clear, I don't want to use $? after every piece of code and I don't want to catch every piece of code with Variable=$().

Is this even possible ?

Upvotes: 1

Views: 480

Answers (2)

clt60
clt60

Reputation: 63974

Maybe do not understand what do you want, but let say have this script mytest.sh:

date > jj
cat jj - jjj    # jj + stdin + (nonexistenxt) jjj #e.g. error too
mkdir jj        #error

so, when you will use this as script with redirections,

echo "Hello world" | bash mytest.sh > output

you will get:

1.) in the file output

Thu Apr  6 21:21:13 CEST 2017
Hello world

and on the screen - the errors

cat: jjj: No such file or directory
mkdir: jj: File exists

Now, change the above script too

((

date > jj
cat jj - jjj    # jj + stdin + (nonexistext jjj)
mkdir jj    #error

) 3>&1 1>&2 2>&3 | tee >(logger -i -t $0 -p 4)) 3>&1 1>&2 2>&3

Note, the removed the -s from the logger args.

Now when you will use it again

echo "Hello world" | bash mytest.sh > output
  • in the output will be the stdout as you expected
  • the stderr will do to screen (and you can redirect it again)
  • and the logger will log all errors.

As you sure know, it works

  • swaps the stdout and stderr
  • pipes the stdout (now the stderr) to the logger process
  • swaps the stdout/stderr back

It probably could be simpler, because the logger by using the -s could duplicate the messages into the stderr itself, but this works universally. Unfortunately, it is inefficient thus using 2 more forks. note the ((.

Using the:

somefunc() { some actions...; }
trap 'somefunc' ERR

will not help you as you expecting. Doing some fancy redirections in the somefunc is too late, because the somefunc triggered after the error happens, e.g. the error-message is already printed to stderr.

Upvotes: 1

Mark Stosberg
Mark Stosberg

Reputation: 13411

While logger sends output to syslog, systemd-cat performs the same kind of function for systemd. See for example:

echo "hello" | systemd-cat
journalctl | tail -10

If you are running your scripts as systemd service units, then there's no need to use systemd-cat: By default systemd will send STDOUT and STDERR of services it controls the journal.

See man systemd-cat for more about that tool.

Upvotes: 1

Related Questions