Difference between revisions of "System Logging"

From wiki.emacinc.com
Jump to: navigation, search
m (Ready for review.)
m (Last minute addition while waiting for a reviewer.)
Line 1: Line 1:
{{todo| Review (04.13.2015-14:44->BS+)(11.10.2015-18:00->MD+)(11.11.2015-10:30->MD+)(11.17.2015-18:10->MD+);(11.18.2015-12:55->MD+)|Mike Dean| project=OE 5.0,MD,Review }}
+
{{todo| Review (04.13.2015-14:44->BS+)(11.10.2015-18:00->MD+)(11.11.2015-10:30->MD+)(11.17.2015-18:10->MD+);(11.18.2015-12:55->MD+)(11.18.2015-14:50->MD+)|Mike Dean| project=OE 5.0,MD,Review }}
 
{{#seo:
 
{{#seo:
 
|title=System Logging
 
|title=System Logging
Line 494: Line 494:
 
<br /><br />
 
<br /><br />
 
This function takes no arguments.
 
This function takes no arguments.
 +
}}
 +
 +
{{function | name=setlogmask |
 +
<code>'''int setlogmask( int mask )'''</code>
 +
<br /><br />The <code>setlogmask()</code> function controls what messages get sent to the <code>syslog</code> server.  While the <code>syslog</code> server does message filtering of its own, this function prevents the messages from ever reaching the <code>syslog</code> server.  This type of filtering is good to use in conjunction with debug macros in order to reduce the overhead caused by having ample log messages spread throughout your software.
 +
<br /><br />
 +
Each bit set in the <code>mask</code> represents a priority level.  If the bit is set, a message of the corresponding priority level will be sent to syslog; otherwise, it won't.  The <code>LOG_MASK</code> macro is used to translate priority levels into appropriate bits, such as <code>LOG_MASK( LOG_ERROR )</code>.
 +
<br /><br />
 +
Using the <code>LOG_UPTO</code> macro is the easiest way to set the mask.  Since the most critical error message has a value of zero, and every less critical message has a value greater than zero, the <code>LOG_UPTO</code> macro will create a mask which passes the given priority level and anything more severe.  For example, to pass messages which have a severity of Warning or worse, you may use: <code>LOG_UPTO( LOG_WARN )</code>.
 +
:;<code>mask</code>
 +
:: The <code>mask</code> parameter is used to determine what messages to pass to <code>syslog</code>, as described above.
 +
:;''Returns'': <code>int</code>
 +
:: The previously set log mask is returned by the function.  You may safely discard it if you don't intend to restore it later.
 +
For example:
 +
<syntaxhighlight lang=C>
 +
#include <syslog.h>
 +
 +
int main( int argc, char ** argv )
 +
{
 +
    setlogmask( LOG_UPTO( LOG_WARN ) );
 +
    syslog( LOG_INFO, "You'll never see me!" );
 +
    syslog( LOG_WARN, "Now you see me." );
 +
 +
    return 0;
 +
}
 +
</syntaxhighlight>
 
}}
 
}}
  

Revision as of 14:49, 18 November 2015

TODO: {{#todo: Review (04.13.2015-14:44->BS+)(11.10.2015-18:00->MD+)(11.11.2015-10:30->MD+)(11.17.2015-18:10->MD+);(11.18.2015-12:55->MD+)(11.18.2015-14:50->MD+)|Mike Dean|OE 5.0,MD,Review}}

This document provides an overview of how system logging works in Linux, and provides guidance on how to work with and configure system logging so that it meets your needs.

Background

System Logging services exist on Linux systems to provide a central logging facility. This central logging service can store logged messages in files on the local machine, can forward the log messages to a remote machine for remote storage and display, and can output the log messages as they arrive to a terminal.

The syslog facility is standardized by POSIX and, as a result, there is a great deal of support for the syslog facility. There are APIs for logging to the syslog facility from C, C++, Python, Java, PHP, Perl, Bash, the commandline, and many other languages. Using the commandline tool, it is even possible to write to the syslog facility from the commandline.

Facilities

In syslog terminology, a facility is a category for log messages. There are generally at least seven standard syslog facilities on any Linux syslog system. The following list shows the standard seven as well as some which are rarely used anymore (especially in embedded systems). The name of the facility is followed, in parenthesis, by the integer facility code associated with the facility, which is then followed by a description of the facility. The ones you should not expect to find on an embedded system are demarcated with an asterisk (*):

kern(0)
Kernel messages
user(1)
User Level Messages
mail(2)*
Mail System Messages
daemon(3)
System Daemon Messages
auth(4)
Security/Authentication Messages
syslog(5)
Internally Generated Syslog Messages
lpr(6)*
Line Printer Subsystem Messages
news(7)*
Network News Subsystem Messages
uucp(8)*
UUCP Subsystem Messages
cron(15)
Cron Scheduling Daemon Messages
local(16-23)
Locally Defined Usage, Messages

Severity

Each of these facilities accepts messages which will have an associated severity level. The severity level is important for filtering messages. The following list shows the eight available severity levels:

emerg(0)
Emergency - System is now unusable
alert(1)
Alert - Immediate Attention is Required
crit(2)
Critical - The System is in a Critical Condition, which may be caused by a failure in the primary appliction.
err(3)
Error - An Error has occurred.
warning(4)
Warning - An unusual, but not erroneous, event has occurred. For example: "Warning: Could not check for updates."
notice(5)
Notice - Uncommon but generally expected messages. For example: "Network Interface eth0 received IP address of 192.168.0.100 from DHCP server."
info(6)
Informational - Common, expected events generate these messages. For example: "Application XYZ started successfully."
debug(7)
Debug - Debugging messages belong at this level.

Storage

By default, the log messages on an EMAC OE Linux machine are stored in a local ramdisk. This type of storage prevents excessive wear of the flash, and works when all of the flash partitions are mounted read-only. However, by storing the messages in a ramdisk, all messages in the ramdisk will be lost as soon as the machine resets, powers off, or reboots for any reason.

Alternate Logging Locations

The syslog server can be configured to log to alternate locations. This is useful for configuring the server to log to persistent storage, such as a writable partition on the local flash or a partition on an SD card. The alternate logging locations can even be remote machines.

Remote Logging

The /var/log directory is the standard location for holding local log messages. This directory usually contains either one file per facility or one directory per facility. If a facility has a directory, it may contain different files which all belong to the facility. The system logging facility directs messages to these files based on rules set in its configuration. The configured rules use the facility level and the severity level to direct the syslogger's filters regarding to which file to send any particular message. There are several different implementations of the syslogger facility, each with its own configuration mechanisms and level of flexibility.

The system logger is also able to send messages to a remote syslog server over a network. The remote syslog server will be able to filter the messages using all of the same criteria as above, but also by source. A remote syslog server configuration can be very useful for remotely debugging deployed machines. While an embedded machine stores its logs on a ramdisk, the remote machine may store them to a traditional hard disk or SSD, allowing them to be preserved through power cycles.

The remote syslog server can be on any normal server, it can be on a developer's desktop, or it can be on another embedded machine. Sending debug messages to a central syslog server ensures the debug messages will be available even if the machine of interest freezes or resets. The use of a remote syslog server can also assist with looking for trends and outliers among a group of deployed machines since the log messages for the entire group of machines can be located in one place.

Log Rotation

Syslog servers incorporate a feature called log rotation. Log rotation is a process which prevents log files from growing beyond a certain size while preserving log messages for later reference. The syslog server (or logrotate system) can be configured with a maximum file size and a maximum number of rotated logs to keep. When the maximum file size is reached, the file will be "rotated." When the maximum number of logs to keep is exceeded, the oldest one will be deleted. There is more information on how this process works below.


General Information

Your Daemons

When developing a software daemon, syslog is a very useful tool for monitoring and debugging your software. The syslog daemon is highly configurable, allowing filters to be altered to suit the current needs of a developer without recompiling software. This capability allows developers to deploy software which sends ample debugging messages to the syslog server without fear of overwhelming the system with debug messages. Using the eight local facilities syslog recognizes, these debug messages can be categorized by developers to allow them to selectively choose the amount of log information they store from each of up to eight different subsystems. This is extremely useful when a system in the field is experiencing intermittent issues. By enabling maximum debugging output for only the subsystem responsible for the feature which is misbehaving, the developers have the greatest chance of seeing the messages they need to diagnose the source of the problem without overwhelming the system (or the storage) with messages. If eight facilities is not enough, the developers can always repurpose dedicated facilities which aren't in use by their intended systems. For instance, the line printing facility is rarely used on an embedded system, and may be safely repurposed by developers.

Web Development

When providing a web interface for an embedded system, the syslog daemon is often the only way to debug a variety of issues with the web server. When links don't work, certain browsers have issues, pages load slowly, or any of a myriad of other issues crop up, the logs are generally the first place people turn for answers. This is just as true on embedded systems as it is on any large scale web server or server farm. On embedded systems, however, the configuration for the logging system may need to be altered due to the volatile nature of the logs in the default configuration. This document provides information on how to solve the issues which may be encountered as a result of this.

Machine Startup

When configuring a machine to start up all the necessary services in the correct sequential order, when the machine is powered on, the syslog server is very helpful in performing the following tasks:

  • Ensuring that process X really did start before process Y.
  • Checking to see if any errors or warnings were reported by processes starting up.
  • Ensuring that processes really did start, at all.
  • Checking to see what configuration was chosen by a process which is capable of choosing its configuration dynamically.
  • Checking the messages reported by device drivers as they start up.
  • Determining the IP address used by a system which gets its network configuration via DHCP.

Startup scripts log their activity to the syslog daemon. Any daemon process launched by these startup scripts should also log startup messages to indicate that they're starting, how they're configured, and that they've finished the startup sequence and are now running. The system logs enable the engineer to assure that a machine has started as intended.

Malfunctioning Systems

When a proven system is malfunctioning, the system logs can be essential in determining the cause of the malfunction. In cases such as this, the system logs are helpful for:

  • Looking to see who logged into a machine, and when.
  • Looking for signs of attacks directed at the machine.
  • Looking for signs of failing hardware.
  • Looking for error and warning messages coming from system processes, daemons, and/or your custom application.

Without these logs, it may be nearly impossible to diagnose these malfunctions.

In Brief

This guide provides enough background information to enable you to handle any of the situations described above. Using the information contain herein, you will be able to approach any of the above listed problems with the tools you need to solve the problems you are facing.



NOTE
To make best use of the log files, a working knowledge of grep is highly beneficial. Experience with crafting and using regular expressions with grep prior to writing system logging messages in your application and init scripts can make the diagnosis process simpler, since a little forethought into a syntax for the messages can make filtering the messages through grep much easier to accomplish correctly.


System Logging

EMAC OE Linux 5.0 uses Busybox's syslog daemon, syslogd, by default. However, the syslog-ng package can be installed to provide a much more capable system logging daemon, when needed.

Default Syslog Daemon

The Busybox syslog daemon is used by default.

About

The standard syslog daemon supports the following configuration capabilities:

  • Maximum size limit for log files.
  • Maximum number of log files to keep, when rotated.
  • Minimum priority level for messages to log.
  • Duplicate dropping (not usually recommended).
  • Log to remote and local files simultaneously, just to local files, or to a memory buffer which needs to be read by a special utility.

Working With

The Busybox syslog daemon is configured, by default, to log to files in the RAMDISK mounted on /var/log/. The files contained in this directory will be capped in size and rotated according to the configuration of the syslog daemon.

The Busybox syslog daemon is configured with the file, /etc/syslog-startup.conf. This file is used for backwards compatibility, because the Busybox syslog daemon recently began reading the /etc/syslog.conf file. The /etc/syslog-startup.conf comes from OE rather than from Busybox.

The standard /etc/syslog-startup.conf configuration is shown below:

# This configuration file is used by the busybox syslog init script,
# /etc/init.d/syslog[.busybox] to set syslog configuration at start time.

DESTINATION=file                # log destinations (buffer file remote)
LOGFILE=/var/log/messages       # where to log (file)
REMOTE=loghost:514              # where to log (syslog remote)
REDUCE=no                       # reduce-size logging
DROPDUPLICATES=no               # whether to drop duplicate log entries
#ROTATESIZE=0                   # rotate log if grown beyond X [kByte]
#ROTATEGENS=3                   # keep X generations of rotated logs
BUFFERSIZE=64                   # size of circular buffer [kByte]
FOREGROUND=no                   # run in foreground (don't use!)
#LOGLEVEL=5                     # local log level (between 1 and 8)
DESTINATION
This configures where the syslog messages will be sent.
buffer
The buffer option will cause the messages to be stored in an internal circular buffer, in RAM. This buffer must be read with logread.
file
The file option will cause the messages to be stored in a file in the location specified by the LOGFILE parameter, listed below.
remote
The remote option will cause syslog messages to be sent to a remote syslog daemon.
LOGFILE
The LOGFILE parameter specifies the location of the logfile which should be used with the file destination.
REMOTE
The REMOTE parameter specifies the host and port to which to send remote log messages. The two part format for this variable provides the destination host followed by the destination port number, with a colon as the delimiter between the two. The destination may be specified as a hostname, or as an IP address. The destination port number should be the port on which the remote syslog server listens.



NOTE
If the destination is specified as a hostname, it is best to create an entry in /etc/hosts for the hostname so that it will resolve to an IP address even if there is a problem with the DNS servers.


REDUCE
The REDUCE option takes a yes or no argument. When set to yes, the syslog server will neglect to log the hostname, facility, and severity level with each log message. This is only recommended for severely resource constrained systems, since the facility and severity level are often used for filtering messages through grep.
DROPDUPLICATES
The DROPDUPLICATES option takes a yes or no argument. When set to yes, the syslog server will ignore messages which duplicate the preceeding message. This can be useful when an errant process keeps sending the same message over and over again, and swamps out the other messages as a result (due to the maximum size setting for the log files). It is best to keep this option off unless it is absolutely needed for a situation like the one just described, because having it turned on can cause other problems to be hidden (generally leading to frustration and/or embarrassment).
ROTATESIZE
The ROTATESIZE option takes a numeric argument. This argument is the maximum desired size for a log file, specified in kibibytes. When a log file has grown to the point where it exceeds this high water mark, it will be rotated.
ROTATEGENS
The ROTATEGENS option takes a numeric argument. This argument specifies the number of older generations of log files to keep in existence. By generations, it means the number of log files which have already been renamed with a sequencing number as a postfix. See the note below for more information.



NOTE
Logfile rotation is a process which renames log files sequentially, to preserve older log messages while keeping incoming messages writing to the same location. For instance, for the /var/log/messages file, this might look like:

messages -> messages.0 +messages Or, if one were to perform this rotation manually at a terminal, it may look like:

root@som9x25:/var/log# mv messages messages.0
root@som9x25:/var/log# touch messages

If there already is a messages.0 file, and the number of generations to keep is set to 2, then a manual version of the rotation might look something like this:

root@som9x25:/var/log# rm -f messages.2
root@som9x25:/var/log# mv messages.1 messages.2
root@som9x25:/var/log# mv messages.0 messages.1
root@som9x25:/var/log# mv messages messages.0
root@som9x25:/var/log# touch messages


BUFFERSIZE
The BUFFERSIZE option takes a numeric argument. This argument specifies the size of the internal circular buffer to use for holding log messages in an internal RAM buffer. This argument only matters when the DESTINATION is set to buffer. The size is specified in kibibytes.
FOREGROUND
The FOREGROUND option takes a yes or no argument. This argument specifies whether the syslogd process should run in the foreground or as a daemon. It is strongly recommended for this option to always be set to, no, to run syslogd as a daemon. This option mostly exists for the developers of Busybox to debug their syslogd implementation.
LOGLEVEL
The LOGLEVEL option takes a numeric argument. This argument specifies the highest numbered severity level which should be logged (see severity above). By default, this is set such that messages with a severity of notice, or more severe, will be logged.

Optional syslog-ng With logrotate

The optional syslog-ng and logrotate option provides everything that's provided by the Busybox syslog daemon, plus:

  • Sophisticated filters for directing log traffic.
  • The ability to act as a central syslog server which receives log messages from remote syslog machines.
  • Enhanced control over the destination(s) for log messages, allowing (for example) messages to be logged to a local RAMDISK, a local SD card (if available), and to a remote syslog server (if available) simultaneously.
  • The ability to configure logrotate to automatically e-mail log files when they're rotated.
  • Same syslog server software is readily available for Linux desktops and servers.

As can be expected, the potential drawback of syslog-ng is the steeper learning curve required to make use of its more sophisticated features. However, those already familiar with syslog-ng will be able to benefit from its extra sophistication immediately.

The official manual page for syslog-ng has more details: http://www.syslog.org/syslog-ng/v1/

Please contact EMAC for details on how to install syslog-ng and logrotate if you have trouble finding and installing them with opkg.

Examples

Evaluating Log Messages

Log messages are stored in /var/log/ by default. This directory contains at least one log file, messages. There are usually (at least) a few other small log files which where generated by the kernel before syslogd started. When syslog-ng is used, you may have several log files which are continually growing, depending on how you configured it.

Showing All the Messages

When the log is rotated, a sequence of additional files will be generated from it, such as messages.0, messages.1, etc. The highest numbered file is the oldest. If you wish to look for messages through as much of the log history as possible, you will need to look through all of the available log files. Fortunately, this is simple. Say you have two rotated versions of the messages file, messages.0 and messages.1. You can output all of the messages from these three files, in order, with the following command:

root@som9x25:/var/log# cat messages.1 messages.0 messages

Nov 17 19:00:21 ipac9x25 user.notice kernel: klogd started: BusyBox v1.23.1 (2015-07-02 12:53:54 CDT) Nov 17 19:00:21 ipac9x25 user.notice kernel: Linux version 3.10.0-emac-standard+23f12b107c (developer@OEBuilder) (gcc ersion 4.9.2 (GCC) ) #1 Tue Jul 21 21:46:40 CDT 2015 Nov 17 19:00:21 ipac9x25 user.warn kernel: CPU: ARM926EJ-S [41069265] revision 5 (ARMv5TEJ), cr=00053177 Nov 17 19:00:21 ipac9x25 user.warn kernel: CPU: VIVT data cache, VIVT instruction cache Nov 17 19:00:21 ipac9x25 user.warn kernel: Memory policy: ECC disabled, Data cache writeback etc.

root@som9x25:/var/log#

You can combine this with grep to see only what you're interested in:

root@som9x25:/var/log# cat messages.1 messages.0 messages | grep authpriv

Nov 17 19:01:11 ipac9x25 authpriv.notice login[1046]: ROOT LOGIN on '/dev/ttyS5'

root@som9x25:/var/log#

Here, we can see that someone logged into the machine as the root user on November 17 at 7:01pm, on the serial console (/dev/ttyS5). This is the only login on the machine since it booted. Had there been other logins, they would also have been shown.

Say you want to see a certain type of message, but there are a lot of results. You can add less to make it easier to read through them:

root@som9x25:/var/log# cat messages.1 messages.0 messages | grep user.notice | less
Nov 17 19:00:21 ipac9x25 user.notice kernel: klogd started: BusyBox v1.23.1 (2015-07-02 12:53:54 CDT) Nov 17 19:00:21 ipac9x25 user.notice kernel: Linux version 3.10.0-emac-standard+23f12b107c (developer@OEBuilder) (gcc version 4.9.2 (GCC) ) #1 Tue Jul 21 21:46:40 CDT 2015 Nov 17 19:00:21 ipac9x25 user.warn kernel: CPU: ARM926EJ-S [41069265] revision 5 (ARMv5TEJ), cr=00053177 Nov 17 19:00:21 ipac9x25 user.warn kernel: CPU: VIVT data cache, VIVT instruction cache Nov 17 19:00:21 ipac9x25 user.warn kernel: Memory policy: ECC disabled, Data cache writeback Nov 17 19:00:21 ipac9x25 user.warn kernel: Clocks: CPU 400 MHz, master 133 MHz, main 12.000 MHz Nov 17 19:00:21 ipac9x25 user.warn kernel: Built 1 zonelists in Zone order, mobility grouping on. Total pages: 32512 Nov 17 19:00:21 ipac9x25 user.notice kernel: Kernel command line: console=ttyS5,115200 root=/dev/mmcblk0p1 rootfstype=ext4 w rootwait Nov 17 19:00:21 ipac9x25 user.notice kernel: Memory: 124820k/124820k available, 6252k reserved, 0K highmem Nov 17 19:00:21 ipac9x25 user.notice kernel: klogd started: BusyBox v1.23.1 (2015-07-02 12:53:54 CDT) Nov 17 19:00:21 ipac9x25 user.notice kernel: Linux version 3.10.0-emac-standard+23f12b107c (developer@OEBuilder) (gcc ersion 4.9.2 (GCC) ) #1 Tue Jul 21 21:46:40 CDT 2015 Nov 17 19:00:21 ipac9x25 user.notice kernel: Kernel command line: console=ttyS5,115200 root=/dev/mmcblk0p1 rootfstype=ext4 rw rootwait Nov 17 19:00:21 ipac9x25 user.notice kernel: Memory: 124820k/124820k available, 6252k reserved, 0K highmem Nov 17 19:00:21 ipac9x25 user.notice kernel: Virtual kernel memory layout: Nov 17 19:00:21 ipac9x25 user.notice kernel: vector : 0xffff0000 - 0xffff1000 ( 4 kB) Nov 17 19:00:21 ipac9x25 user.notice kernel: fixmap : 0xfff00000 - 0xfffe0000 ( 896 kB) Nov 17 19:00:21 ipac9x25 user.notice kernel: vmalloc : 0xc8800000 - 0xff000000 ( 872 MB) Nov 17 19:00:21 ipac9x25 user.notice kernel: lowmem : 0xc0000000 - 0xc8000000 ( 128 MB)

Helper Functions

When it gets to the point where there are several rotated log files, the command to cat them all can be a lot to type. Let's create a couple of helper functions to make our lives easier. We can enter these at the shell, as shown here. To save them permanently, put them in your ~/.bashrc or /etc/profile file.

root@som9x25:/var/log# function genseq() { logfn=$1; max=$2; for i in $(seq $max -1 0); do printf "${logfn}.${i} "; done;
printf "$logfn\n"; }

This function generates a sequence of log file names for us to use, like this:

root@som9x25:/var/log# genseq messages 5

messages.5 messages.4 messages.3 messages.2 messages.1 messages.0 messages

root@som9x25:/var/log#

While we could use this list directly, it's still a bit awkward to type:

root@som9x25:/var/log# cat $(genseq messages 5)

Especially when piping to grep and maybe less, so let's make a helper function:

root@som9x25:/var/log# function catseq() { cat $(genseq $1 $2); }

Okay, now we can just type:

root@som9x25:/var/log# catseq messages 5

Much easier to type. We'll use this function from here on.

Sifting Through Messages

Here are a few ways you may wish to sift through messages.

Checking for Errors, Only

If you only want to look for error messages, you might type something like:

root@som9x25:/var/log# catseq messages 3 | grep '\.err '

The regular expression used here is to avoid false positives. Note the trailing space in the regular expression.

Checking for Errors and Worse

If you want to scan for messages which are of these categories (only):

  • Emergency
  • Alert
  • Critical
  • Error

You might do the following:

root@som9x25:/var/log# catseq messages 3 | egrep '\.(emerg|alert|crit|err) '

Note the use of egrep here; it is required for this extended regular expression to work.

Looking for Certain local Facility Messages

Perhaps you're making use of several of the local log facilities, and you wish to see all of the messages from just a few of them. In this example, we'll filter out all but two local facilities: local3 and local5:

root@som9x25:/var/log# catseq messages 3 | grep ' local[35]\.'

Note the leading space in the regular expression. The 3 and 5 are listed in between square brackets. You can list numbers you're interested in individually and/or use ranges. If you wanted to list all local facility messages except for local4, you could write:

root@som9x25:/var/log# catseq messages 3 | grep ' local[0-35-7]\.
Looking for local Facility Messages of a Certain Priority

While you're debugging your application, you find that you need to see all events from certain local facilities which are of a subset of priority levels, because you're sure you'll figure out what's going wrong if you can get these specific messages. So, you ignore the mumblings of your coworkers about, "famous last words," and such, and you type:

root@som9x25:/var/log# catseq messages 3 | egrep ' local([0-246]\.(err|notice|warn)|[357]\.(emerg|alert)) '

By cleverly crafting this complex regular expression, you were able to filter out exactly the right messages you needed to see the sequence of events leading up to the catastrophic failure you were experiencing and save the day. Your coworkers cheer and hoist you on their shoulders, singing your praises.

Okay, so in reality, nobody notices and you go to lunch happily, knowing that you're not going to get yelled at for a major fault. You treat yourself to some dessert (because, hey, why should Fido be the only one who gets a treat for doing something right?), and everyone's happy.

Of course, you wouldn't have been able to properly diagnose what went wrong without having generated good log messages from your software in the first place. The next section shows you how to generate the messages; you'll have to figure out how to make them good messages on your own, though.

Writing to Syslog from Programs and Scripts

As mentioned previously, many languages support writing to the Linux system logging daemon. There are many handy libraries and functions which provide this capability. Some of the most commonly used ones are shown here.

Shell Utility: logger

Whether you are writing a shell script, or simply wishing to enter something into the system logs from the commandline, the logger utility will give you the capability you need. This simple command takes a few options, but it can also be run with the only argument being the message to log.

Arguments to logger

The following options are available for logger:

-t TAG
Takes a TAG as an argument. This option specifies a tag to use for labeling the message. Tags are useful for sorting through logs later on.
-p Priority
Takes a Priority as an argument. The priority may be specified as just a numeric priority level, identifying the severity of the message, or it can be specified as a tuple containing a facility name and a priority level, delimited by a dot (.). If no facility is specified, the facility defaults to, user. The severity levels are specified in severity above. The facility names are specified in facilities above.
-s
This option sets a boolean which enables logging messages to stdout as well as to the system logger. This is especially useful in interactive shell scripts, since it allows the developer to use one function to output a message to the screen and to the system logs simultaneously.
Examples of Using logger

To send a message to the system log as simply as possible:

root@som9x25:~# logger "Default settings message example"
root@som9x25:~# tail -n 1 /var/log/messages
Nov 17 19:20:23 ipac9x25 user.notice root: Default settings message example

To send a message to the system log with severity 3 (err):

root@som9x25:~# logger -p 3 "This is an example error message"
root@som9x25:~# tail -n 1 /var/log/messages

Nov 17 19:22:06 ipac9x25 user.err root: This is an example error message

To send a message with the facility, local5, and the severity 4 (warn):

root@som9x25:~# logger -p local5.4 "This is a local5 facility warning message example."
root@som9x25:~# tail -n 1 /var/log/messages
Nov 17 19:23:51 ipac9x25 local5.warn root: This is a local5 facility warning message example.

To add a tag (highly recommended) to the above, use -t. Here, we use the tag, EXAMPLE:

root@som9x25:~# logger -t EXAMPLE -p local5.4 "This is a local5 facility warning message example."
root@som9x25:~# tail -n 1 /var/log/messages

Nov 17 19:25:19 ipac9x25 local5.warn EXAMPLE: This is a local5 facility warning message example.

Notice that the username (root) was replaced by the tag (EXAMPLE). When using tags in a script or program, it is best to come up with a unique tag and create a function for sending messages to the system log with this tag. That way, you can easily find all messages from just your program/script. If you have a complex program or set of scripts to debug, you could use multiple tags, but this will be more difficult to search for unless you use the optional syslog-ng to redirect the messages from your software to distinct files. In an interactive script, you might use logger like this:

root@som9x25:~# logger -t EXAMPLE -p local3.6 -s "Successfully wrote new configuration file."

EXAMPLE: Successfully wrote new configuration file.

root@som9x25:~# tail -n 1 /var/log/messages

Nov 17 19:25:19 ipac9x25 local5.warn EXAMPLE: This is a local5 facility warning message example.

Notice that the message isn't visible in the system log? This is because the syslogd daemon on this machine is only configured to log messages which have a severity of 5 or lower. We might modify the example so that it will be logged, like this:

root@som9x25:~# logger -t EXAMPLE -p local3.5 -s "Successfully wrote new configuration file."

EXAMPLE: Successfully wrote new configuration file.

root@som9x25:~# tail -n 1 /var/log/messages

Nov 17 19:31:37 ipac9x25 local3.notice EXAMPLE: Successfully wrote new configuration file.

Now the message has been saved to the system logs as well as displayed on stdout.

Writing to Syslog from a C Program

There is a standard C function call on Linux for writing to the system logger. This function, syslog(), uses a persistent connection to the log facility which can be opened and closed using the associated openlog() and closelog() functions. However, if the syslog() function is called without first calling openlog(), the syslog() function will open the connection implicitly.

Essential Elements

The header file required for these functions is syslog.h.

The relevant functions are:



openlog()

void openlog( const char * ident, int option, int facility )

The openlog() function is used to (optionally) open a connection to the log daemon before writing log messages. If the openlog() function is called, the closelog() function must also be called before exiting.

The following parameters are accepted by this function:

ident
The ident parameter is an identification string to use for log messages. This is just like the tag option to the logger command available from the shell. If this parameter is null, the identification string defaults to the name of the process sending the messages.
option
The option parameter is a bit string which accepts the following single bit masks:
LOG_PERROR
If on, any log messages sent will also go to the stderr stream associated with the current process.
LOG_CONS
This useful flag causes any messages which were unable to be sent to the system logger (due to any kind of failure) will be sent to the system console instead.
LOG_PID
When on, the process ID of the current process will be printed with each log message. This is especially useful for programs which call fork() at some point in their lifetime.
LOG_NDELAY
This option forces the connection to be established immediately, rather than deferred to a later point (such as at the beginning of the first call to the syslog() function.)
facility
This is the facility to which the log messages should be directed. The available facilities were described earlier in this document; see facilities.




syslog()

void syslog( int facility_priority, const char * format, ... )

The syslog() function is the core function for writing messages to the system log. This function may be called in between calls to openlog() and closelog(), or standalone. Using this function is very similar to using the standard printf() function, or is (perhaps) even more similar to the standard fprintf() function.

The following parameters are accepted by this function:

facility_priority
The facility_priority argument is an integer which will accept any of the following predefined macros:
  • LOG_USER
  • LOG_MAIL
  • LOG_DAEMON
  • LOG_AUTH
  • LOG_SYSLOG
  • LOG_LPR
  • LOG_NEWS
  • LOG_UUCP
  • LOG_CRON
  • LOG_AUTHPRIV
  • LOG_FTP
  • LOG_LOCAL0
  • LOG_LOCAL1
  • LOG_LOCAL2 through 7...
These facility priorities correspond to the facilities discussed earlier in facilities.

format
The format parameter accepts a string with formatting parameters identical to the kind used for the standard printf() function. For information on how to craft such formatting strings, see the printf() documentation.

... (ellipsis operator)
Any arguments needed for the formatting string are passed here, just like with the standard printf() function.




closelog()

void closelog( void )

The closelog() function must be called before exiting the program, but only if the openlog() function was called earlier. The openlog() and closelog() functions should be treated the same as fopen() and fclose(), or malloc() and free().

This function takes no arguments.




setlogmask()

int setlogmask( int mask )

The setlogmask() function controls what messages get sent to the syslog server. While the syslog server does message filtering of its own, this function prevents the messages from ever reaching the syslog server. This type of filtering is good to use in conjunction with debug macros in order to reduce the overhead caused by having ample log messages spread throughout your software.

Each bit set in the mask represents a priority level. If the bit is set, a message of the corresponding priority level will be sent to syslog; otherwise, it won't. The LOG_MASK macro is used to translate priority levels into appropriate bits, such as LOG_MASK( LOG_ERROR ).

Using the LOG_UPTO macro is the easiest way to set the mask. Since the most critical error message has a value of zero, and every less critical message has a value greater than zero, the LOG_UPTO macro will create a mask which passes the given priority level and anything more severe. For example, to pass messages which have a severity of Warning or worse, you may use: LOG_UPTO( LOG_WARN ).

mask
The mask parameter is used to determine what messages to pass to syslog, as described above.
Returns
int
The previously set log mask is returned by the function. You may safely discard it if you don't intend to restore it later.

For example:

#include <syslog.h>

int main( int argc, char ** argv )
{
    setlogmask( LOG_UPTO( LOG_WARN ) );
    syslog( LOG_INFO, "You'll never see me!" );
    syslog( LOG_WARN, "Now you see me." );

    return 0;
}


Examples of Using the C syslog() Function (and Friends)

The most simple use of this function is found in the following Hello, World style program:

#include <syslog.h>

int main( int argc, char ** argv )
{
    syslog( LOG_INFO, "Hello, World from syslog()!" );

    return 0;
}

Note the lack of a newline character. You should not pass newlines to syslog. If you do, they will be stripped off.

A slightly more sophisticated use of syslog follows:

#include <syslog.h>
#include <unistd.h>

int main( int argc, char ** argv )
{
    int i;
    // Use "MyEXAMPLE" as the "tag" for messages.  Log output to stderr and to the system log, and include my PID.
    openlog( "MyEXAMPLE", LOG_PERROR | LOG_PID );
    // Let's generate some output.
    syslog( LOG_WARN, "You have until the count of ten, Mr..." );

    for( i = 10; i > 0; --i )
    {
        syslog( LOG_WARN, "%d", i );
        sleep( 1 );
    }

    syslog( LOG_ERR, "I warned you, sir and/or madam.  You almost made an error.  If you'd broken out of this with" );
    syslog( LOG_ERR, "Control-C, the closelog() call never would have been made.  Whew.  That was a close one.  Next" );
    syslog( LOG_ERR, "time make sure to catch the SIGINT signal (at the least) and call the closelog() function in" );
    syslog( LOG_ERR, "your signal handler to such avoid wasteful behavior." );

    closelog();

    return 0;
}

Conclusion

This article covered quite a bit of territory. You were given an overview of how logging works on Linux systems. We then talked about a variety of ways in which people make use of these logs to solve real world problems. We covered the basics of the standard syslog system for EMAC OE Linux as well as the alternative, syslog-ng, and gave an overview of what extras you can gain by installing syslog-ng. Next, we went through several examples of searching through messages to find the ones which are relevant to your current needs. Finally, we covered ways to send messages to the syslog service from software, and from the commandline as well. We didn't cover all programming languages, but the information presented here should provide a solid enough foundation for you to perform a search on the Internet for a syslog client library for other programming languages, and to make use of what you find quickly and easily.

Further Information

Where to Go Next
Pages with Related Content