Configuring and fine-tuning your system-logging facilities is extremely important for system security and general diagnostics. But if your logs grow too large and fill up their filesystem, all that work may come to naught.
As with syslog itself, most Linux distributions come with a preconfigured log-rotation scheme. As with syslog, while this scheme tends to work adequately for many users, it's too important a mechanism to take for granted: it behooves you to understand, periodically evaluate, and, if necessary, customize your log-management setup.
Both Red Hat 7 and Debian 2.2 use a binary program called logrotate to handle system-log growth. In fact, they use very similar implementations of logrotate: global options and low-level (system) log files are addressed in /etc/logrotate.conf, and application-specific configuration scripts are kept in /etc/logrotate.d/.
When logrotate is run, all scripts in /etc/logrotate.d are included into logrotate.conf and parsed as one big script. This makes logrotate's configuration very modular: when you install an RPM or DEB package (of software that creates logs), your package manager automatically installs a script in /etc/logrotate.d, which will be removed later if you uninstall the package.
|
There are really only two types of elements in logrotate.conf and its included scripts: directives (i.e., options) and log-file specifications. A directive is simply a parameter or a variable declaration; a log-file specification is a group of directives that apply to a specific log file or group of log files.
In Example 10-25, we see a simple /etc/logrotate.conf file.
# Very simple logrotate.conf file # Global options: rotate logs monthly, saving four old copies and sending # error-messages to root. After "rotating out" a file, touch a new one monthly rotate 4 errors root create # Keep an eye on /var/log/messages /var/log/messages { size 200k create postrotate /bin/kill -HUP `cat /var/run/syslog-ng.pid 2> /dev/null` 2> /dev/null || true endscript }
In Example 10-25, the global options at the top may be thought of as the default log-file specification. Any directive for a specific log file takes precedence over the global options. Accordingly, we see in this example that although by default logs are rotated once a month and that four archives will be kept, the file /var/log/messages will be rotated not on the basis of time, but on size.
However, the other global directives will still apply: four old copies will be kept; immediately after a log is renamed (which is how they're "rotated"), a newly empty current log file will be created ("touched"); and error messages will be emailed to root.
logrotate supports a large number of different directives, but in practice, you'll probably spend more time tweaking the subscripts placed in logrotate.d than you will writing scripts from scratch. With that in mind, Table 10-12 lists some commonly encountered logrotate directives. A complete list is provided in the manpage logrotate(8).
Directive |
Description |
---|---|
/path/to/logfile { directive1 directive2 etc. } |
Log file specification header/footer (i.e., "apply these directives to the file /path/to/logfile"). Whitespace is ignored. Applicable global directives are also applied to the log file, but when a given directive is specified both globally and locally (within a log file specification), the local setting overrules the global one. |
rotate number |
Tells logrotate to retain number old versions of the specified log file. Setting this to zero amounts to telling logrotate to overwrite the old log file. |
daily | weekly | monthly | size=number_bytes |
The criterion for rotating the specified file: either because one day or week or month has passed since the last rotation, or because the file's size has reached or exceeded number_bytes since the last time logrotate was run. Note that if number_bytes is a number, bytes are assumed; if expressed as a number followed by a lowercase "k," Kilobytes are assumed; if expressed as a number followed by a capital "M," Megabytes are assumed. |
mail [username|mail@address] |
Email old files to the specified local user or email address rather than deleting them. |
errors [username|email@address] |
Email logrotate error messages to the specified local user or email address. |
compress |
Use gzip to compress old versions of log files. |
copytruncate |
Instead of renaming the current log file and creating a new (empty) one, move most of its data out into an archive file. Accommodates programs that can't interrupt logging (i.e., that need to keep the log file open for writing continuously). |
create [octalmode owner group] |
Recreate the (now empty) log file immediately after rotation. If specified, set any or all of these properties: octalmode (file-mode in octal notation ? e.g., 0700), owner, and group properties. |
ifempty | notifempty |
By default, logrotate will rotate a file even if it's empty. notifempty cancels this behavior; ifempty restores it (e.g., overriding a global notifempty setting). |
include file_or_directory |
When parsing logrotate.conf, include the specified file or the files in the specified directory. |
missingok | nomissingok |
By default, logrotate will return a message if a log file doesn't exist. nomissingok cancels this behavior (i.e., tells logrotate to skip that log file quietly); missingok restores the default behavior (e.g., overriding a global nomissingok setting). |
olddir dir | noolddir |
Tells logrotate to keep old versions of a log file in dir, whereas noolddir tells logrotate to keep old versions in the same directory as the current version (noolddir is the default behavior). |
postrotate line1 line2 etc. endscript |
Execute specified lines after rotating the log file. Can't be declared globally. Typically used to send a SIGHUP to the application that uses the log file. |
prerotate line1 line2 etc. endscript |
Execute specified lines before rotating the log file. Can't be declared globally. |
Just What Do We Mean By "Rotate?"All log-management mechanisms involve periodically moving/renaming a log file to an archive copy and creating a new (empty) log file. Rotation is necessary when multiple archive copies are maintained. In the most common log-rotation scheme, a set of static filenames is maintained. For example, messages, messages.1, messages.2, messages.3 is a typical three-archive filename set ? messages being the "current" log file and messages.3 being the oldest archive. In this scheme, rotation is achieved by coping the second-to-oldest file over the oldest file (e.g., mv messages.2 messages.3). The third-oldest file's name is then changed to that of the second-oldest file's, and so forth, until the current file is renamed and a new (empty) "current" log file is created (e.g., mv messages messages.1; touch messages). This is how logrotate behaves when its rotate parameter is set to a nonzero value. In the second common mechanism, archive filenames are unique (e.g., messages, messages.20010807, messages.20010708, etc.). In this case, rotation is a simple matter of changing the current file's name and then creating a new (empty) "current" log file (e.g., mv messages messages.20010928; touch messages). The final step is to compare the age of the oldest log archive file to a "maximum age" setting and to delete it if it's reached that age. This second scheme is used by SuSE's aaa_base_rotate_logs script (covered later in this chapter). |
In both Red Hat 7 and Debian 2.2, logrotate is invoked by the script /etc/cron.daily/logrotate, which consists of a single command:
/usr/sbin/logrotate /etc/logrotate.conf
This doesn't necessarily mean that logs are rotated daily; it means that logrotate checks each log file daily against its configuration script and rotates or doesn't rotate the log file accordingly.
If you want logrotate to be run less frequently, you can move this script to /etc/cron.weekly or even /etc/cron.monthly (though the latter is emphatically not recommended unless logrotate is, for some strange reason, configured to rotate each and every file monthly).
Log rotation in SuSE, as with so much else, is configured at a gross level in /etc/rc.config (the configuration file for suseconfig, which is the primary backend engine of yast). This file contains a variable called MAX_DAYS_FOR_LOG_FILES, which you can use to set the maximum number of days system logs are kept (by default, 365). In addition, the log-rotation tools themselves come preconfigured and preactivated.
Chances are, however, that you'll need to tweak SuSE's log-management setup more granularly than MAX_DAYS_FOR_LOG_FILES, especially if you install Syslog-ng and disable syslog. As it happens, SuSE's log-rotation scheme is less powerful but also much simpler than Red Hat's and Debian's logrotate.
SuSE uses a script called /etc/cron.daily/aaa_base_rotate_logs for day-to-day log rotation. This script shouldn't be manually edited; its behavior is controlled by the file /etc/logfiles, which is simply a list of the files you wish to rotate along with the maximum sizes you want them to reach, the permissions and ownerships they should have, and the startup script (if any) that should be restarted after rotation is done.
Example 10-26 is an excerpt from the default /etc/logfiles from SuSE 7.1.
# /etc/logfiles - This file tells cron.daily, which log files have to be watched # # File max size mode ownership service # (reload if changed) /var/log/mgetty.* +1024k 644 root.root /var/log/messages +4096k 640 root.root /var/log/httpd/access_log +4096k 644 root.root apache /var/squid/logs/access.log +4096k 640 squid.root
In the first noncomment line, all log files whose name begins /var/log/mgetty will be rotated after exceeding 1,024 kilobytes, after which they'll be rotated to new files whose permissions are -rw-r--r-- and that are owned by user root and group root.
The third line states that the file /var/log/httpd/access_log should be rotated after exceeding 4,096 kilobytes, should be recreated with permissions -rw-r--r--, owned by user root and group root, and after rotation is done, the startup script /etc/init.d/apache should be restarted.
Since the maximum age of all log files is set globally in /etc/rc.config, take care not to set the maximum size of a frequently written-to file (such as /var/log/messages) too high. If this happens and if the maximum age is high enough, your logs may fill their volume.
Speaking of which, I highly recommend the use of a dedicated /var partition on any machine that acts as a server; a full /var partition is much less likely to cause disruptive system behavior (e.g., crashing) than a full root partition.