[ Team LiB ] Previous Section Next Section

Recipe 9.31 Sending Messages to the System Logger

9.31.1 Problem

You want to add information about interesting events to the system log.

9.31.2 Solution

Use the logger program. A simple example:

$ logger "using Ethereal to debug a network problem"

Suppose "food" is the name of a program, short for "Foo Daemon." Log a simple message:

$ logger -t "food[$$]" -p local3.warning "$count connections from $host"

Direct stdout and stderr output to syslog:

$ food 2>&1 | logger -t "food[$$]" -p local3.notice &

Send stdout and stderr to syslog, using different priorities (bash only):

$ food 1> >(logger -t "food[$$]" -p local3.info) \
       2> >(logger -t "food[$$]" -p local3.err)  &

You can also write to the system log from shell scripts [Recipe 9.32], Perl programs [Recipe 9.33], or C programs [Recipe 9.34].

9.31.3 Discussion

The system logger isn't just for system programs: you can use it with your own programs and scripts, or even interactively. This is a great way to record information for processes that run in the background (e.g., as cron jobs), when stdout and stderr aren't necessarily connected to anything useful. Don't bother to create, open, and maintain your own log files: let the system logger do the work.

Interactively, logger can be used almost like echo to record a message with the default user facility and notice priority. Your username will be prepended to each message as an identifier.

Our recipe shows a sample "Foo Daemon" (food) that uses the local3 facility and various priority levels, depending on the importance of each message. By convention, the script uses its name "food" as an identifier that is prepended to each message.

It is a good idea to add a process ID to each message, so that a series of messages can be untangled when several copies of the script are running simultaneously. For example, consider the log file entries from a computer named cafeteria:

Feb 21 12:05:41 cafeteria food[1234]: customer arrived: Alison
Feb 21 12:06:15 cafeteria food[5678]: customer arrived: Bob
Feb 21 12:10:22 cafeteria food[1234]: devoured tofu
Feb 21 12:11:09 cafeteria food[5678]: consumed beef
Feb 21 12:15:34 cafeteria food[5678]: ingested pork
Feb 21 12:18:23 cafeteria food[1234]: gobbled up broccoli
Feb 21 12:22:52 cafeteria food[5678]: paid $7.89
Feb 21 12:24:35 cafeteria food[1234]: paid $4.59

In this case, the process IDs allow us to distinguish carnivores and herbivores, and to determine how much each paid. We use the process ID of the invoking shell by appending "[$$]" to the program name.[12] Other identifiers are possible, like the customer name in our example, but the process ID is guaranteed to be unique: consider the possibility of two customers named Bob! The system logger can record the process ID with each message automatically.

[12] logger's own option to log a process ID, -i, is unfortunately useless. It prints the process ID of logger itself, which changes on each invocation.

It is a good practice to run logger before engaging in activities that might otherwise be regarded as suspicious, such as running a packet sniffing program like Ethereal. [Recipe 9.17]

Programs that don't use the system logger are unfortunately common. Our recipe shows two techniques for capturing stdout and stderr from such programs, either combined or separately (with different priorities), using logger. The latter uses process substitution, which is available only if the script is run by bash (not the standard Bourne shell, sh).

9.31.4 See Also

logger(1), bash(1).

    [ Team LiB ] Previous Section Next Section