Creating logfile archives with logrotate
Posted by Steve on Tue 29 Mar 2005 at 06:11
Many of the services installed on Linux machines will produce logfiles which grow, and grow, and grow. If left unchecked you can easily fill a disk with a large collection of logfiles if you're not careful.
The most common method of keeping logfile growth in check is to use logrotate, and many Debian packages are setup to work with this by default.
The most obvious package which uses it is Apache, the webserver, which by default keeps its logfiles in the directory /var/log/apache (or /var/log/apache2).
If you examine this directory you will see that there are a bunch of logfiles which are archived:
root@mystery:~# ls -1 /var/log/apache2/ access.log access.log.1 access.log.2.gz access.log.3.gz access.log.4.gz access.log.5.gz error.log error.log.1 error.log.2.gz error.log.3.gz error.log.4.gz error.log.5.gz
Here the current logfiles access.log, error.log are kept raw as are yesterday's logfiles (access.log.1 and error.log.1). Previous logfiles are compressed with gzip and only kept for five weeks. (I know it's five weeks and not five days because I've looked at the configuration - It's not clear from this output though!)
The process that is in charge of compressing and rotating these logfiles is called logrotate and it is executed once per day upon Debian installations.
As we saw when we were looking at scheduling commands with cron there is a directory called /etc/cron.daily which contains scripts which are executed once per day. Here you will find the logrotate driver script.
Every day this script runs and examines two things:
- The configuration file /etc/logrotate.conf
- The configuration directory /etc/logrotate.d
The latter is where most of our packages are configured. This directory contains configuration files which other packages have installed. For example if you install apache the file /etc/logrotate.d/apache will be installed.
Many servers such as exim the mailserver will install their own configuration file, and you can add your own.
A typical logrotate configuration file looks like this:
/var/log/apache/*.log {
weekly
missingok
rotate 52
compress
delaycompress
notifempty
create 640 root adm
sharedscripts
postrotate
if [ -f /var/run/apache.pid ]; then
/etc/init.d/apache restart > /dev/null
fi
endscript
}
You can see several important things here. The most obvious is the list of files that will be matched by this configuration file:
/var/log/apache/*.log {
...
}
After this we have a collection of configuration terms, a different one on each line. In the example above we have:
- weekly
- The files should be rotated every week. Opposite: daily
- rotate nn
- We should keep no more than nn files.
- compress
- Compress older files with gzip. Opposite: nocompress
- delaycompress
- Don't compress yesterdays files. Opposite: compress
- notifempty
- Don't do any rotation if the logfile is empty. Opposite: ifempty
- create xx user group
- If we have to create the new file give it the given mode, owner, and group.
- sharedscripts
- Run any given prerotate or postrotate script for each logfile individually. Opposite: nosharedscripts.
- postrotate + endscript
- Anything between these is executed after the rotation process. Opposite : prerotate
Hopefully that should have made sense!
The upshot of this script is that any file which matches /var/log/apache/*.log is rotated every week, compressed, if it's non-empty. The new file is created with the file mode of 640, and after the rotation has finished the server is restarted.
If we wish to install a local service which creates a logfile we can cause it to be rotated very easily, just by adding a new logrotate configuration file.
Assuming we have a new service "fred" which produces its output in /var/log/fred/output.log we can cause this to be rotated every day with a script like this:
/var/log/fred/*.log {
daily
missingok
rotate 7
compress
delaycompress
create 640 fred fred
sharedscripts
/etc/init.d/fred restart
endscript
}
This will:
- Run daily.
- Keep no more than 7 days worth of logfiles at any one time.
- Not complain if there is a logfile missing.
- Compress the older files, but not yesterdays.
- Create the new logfiles as being owned by the user and group fred.
- Restart the service after rotating the logfiles.
Any of the existing files in the logrotate directory can be examined for more examples - and the manpage documents all the options you may use in a clear manner:
man logrotate
[ View Steve's Scratchpad | View Weblogs ]
That looks good - if you run the following command you'll get to see what will happen for your given file:
logrotate --debug --force nameofyourfile
Steve
-- Steve.org.uk
[ Parent | Reply to this comment ]
Thank you!
[ Parent | Reply to this comment ]
[ View figjam's Scratchpad | View Weblogs ]
What about if I have a directory where there are multiple files per day? I would like to create a daily archive file, keeping seven days and do something like the delaycompress option to make sure I don't compress a log file currently being written to.
There is a file every 15 minutes that looks something like 200504011800.poller, 200504011815.poller and so on.
Cheers,
[ Parent | Reply to this comment ]
[ Parent | Reply to this comment ]
[ View Steve's Scratchpad | View Weblogs ]
That is an implementation artifact, caused by the code using the rename function to deal with the files.
(I guess because this is simpler to code and avoids the common error associated with "copying and then renaming": a disk being full.)
I too get annoyed by this, and usually "fix" it by doing a move myself in the postrotate section of the script.
Steve
-- Steve.org.uk
[ Parent | Reply to this comment ]
I'm running p0f as root and it writes its output to /var/log/p0f.log. I have p0f.log in my logrotate.conf but when logrotate is run via cron, a new p0f file gets created but nothing gets written to it. It stays empty until I kill the process and re-run it from the command line. What I am doing wrong?
Here's the listing of my logrotate.conf file:
/var/log/p0f.log {
rotate 7
daily
delaycompress
missingok
create 0666 root root
}
I tried changing the create mask and the user and group but it doesn't seem to make a difference. Should I try cron as the owner?
[ Parent | Reply to this comment ]
[ View Steve's Scratchpad | View Weblogs ]
You probably want to take advantage of the pre/post-rotate actiosn to restart p0f, it might be expecting to use the old file still.
Otherwise it looks good. If you save the snippet into /etc/logrotate.d/p0f you can use the following command line to debug the issue in either case:
logrotate -d -f /etc/logrotate.d/p0f
That might be useful ..?
Steve
-- Steve.org.uk
[ Parent | Reply to this comment ]
[ Parent | Reply to this comment ]
[ View Steve's Scratchpad | View Weblogs ]
Usually most long running processes, and daemons are started via start-stop-daemon - have a look at the scripts in /etc/init.d for example uses.
This records the process ID into a file, and allows it to be killed cleanly later.
Steve
-- Steve.org.uk
[ Parent | Reply to this comment ]
It works great -- thanks for all your help. My p0f files are getting rotated daily.
Long live Debian! :)
[ Parent | Reply to this comment ]
In my case, I could not restart the task as it was a manager for a piece of hdwr. Append worked for me.
[ Parent | Reply to this comment ]
You easily need to add "copytruncate" to the settings, thats all.
Background: The Problem is, that after logrotate rotated the logfile, the pointer still is on the file - but now it is named as *.gz and apache tries to log into that file - not into the newly created one.
website that helped me out: www.thegeekstuff.com/2010/07/logrotate-examples/
(watch out for point 3.)
- Domger
[ Parent | Reply to this comment ]
[ Parent | Reply to this comment ]
I want to configure my logrotate configuration file as follows
we need keep all clients monthly logs to /var/log/apache2/logs folder
Under this folder we have different clients directories.Each directory
should contain the logfiles that is access.log and error.log files for
each folder.Every month end logrotate should run and it should keep the
log files in monthnameandyear folder with monthnameandyear.tgz file.
How to configure this in logrotate.conf
Example:-
logfiles location /var/log/apache2/logs under this folder every client is having their folder for logs
in side that apache log files are there i.e error.log,access.log.
Every month logrotate should run and it should create a folder with monthnameandyear under this monthname folder
that perticular month logfiles .tgz file shouls be there.
ex:- /var/log/apache2/logs/bahu/may2005/may2005.log.tgz
[ Parent | Reply to this comment ]
The fact is, i'm trying to rotate not a log, but a Openoffice file for backup reasons (this could be a non-common activity, but i'd like to do it). Unfortunately, logrotate's mail option sends the file in plain text on the body of the message. I'd like to send it like an attached file.
Thanks for your help.
Jader
[ Parent | Reply to this comment ]
[ Parent | Reply to this comment ]
I am using virtual apache2 hosts each with their own access log files. I have created seperate logrotate files for each host in /etc/logrotate.d/
What I experience is that my log files are being rotated but Apache keeps loging in the old logfile access.log.1 as if apache is not restarted. However I have
postrotate
if [ -f /var/run/apache2.pid ]; then
/etc/init.d/apache2 restart > /dev/null
fi
endscript
in each script.
Does anyone has a clue on how to get Apache loging into the new access.log file?
[ Parent | Reply to this comment ]
I could be wrong, but I *think* this has only been happening since I introduced a potentially rather expensive pre-rotate task (awstats.pl)...
[ Parent | Reply to this comment ]
I use awstats also, so this could be the cause of it.
[ Parent | Reply to this comment ]
I noticed something that was definitely wrong with my configuration, and that (conceivably) is to blame for the problem we're seeing: In adding the awstats 'prerotate' section, I forgot to close it off with 'endscript' (the pattern is 'prerotate {commands} endscript postrotate {commands} endscript').
Thus, upon careful perusal of the mails cron was sending me, I noticed it was complaining about 'postrotate: command not found' -- since there was no endscript after the prerotate, it continued executing each line as a prerotate command until the postrotate's 'endscript', which, as it happens, was the bit that restarts apache.
Now if this restart happens before the log rotation, it's not surprising that Apache keeps using the old file.
I'm not actually sure this will resolve the issue (I do weekly rotation and am somewhat reluctant to trigger one by hand), but I'm hopeful. :)
- P
[ Parent | Reply to this comment ]
My feeling is I use another setup. I have a logrotate cron job for every virtual host that logs its own access log file. Awstats is doing updates in a separate cron job.
[ Parent | Reply to this comment ]
The relevant file is /etc/logrotate.d/apache2:
/var/log/apache2/*.log {
weekly
missingok
rotate 52
compress
delaycompress
notifempty
create 644 root adm
sharedscripts
prerotate
[ -x /usr/lib/cgi-bin/awstats.pl -a -f /etc/awstats/awstats.conf -a -r /var/log/apache2/access.log ] && /usr/lib/cgi-bin/awstats.pl -config=awstats -update
endscript
postrotate
if [ -f /var/run/apache2.pid ]; then
/etc/init.d/apache2 restart > /dev/null
fi
endscript
}
The command in prerotate is exactly what my awstats cron job runs every 10 minutes. The problem I described was that I was missing the 'endscript' after that command, so that it considered everything until the final 'endscript' as part of the prerotate handler.If this doesn't look familiar, then maybe you do have a different problem.. could you post your apache logrotate file?
- P
[ Parent | Reply to this comment ]
For every virtual domain on my web server I use the following logrotate file in /etc/logrotate.d/virtualhostname:
/var/log/apache2/virtualhostname/*.log {
weekly
missingok
rotate 52
compress
delaycompress
notifempty
create 644 root adm
sharedscripts
postrotate
if [ -f /var/run/apache2.pid ]; then
/etc/init.d/apache2 restart > /dev/null
fi
endscript
}
[ Parent | Reply to this comment ]
Incidentally, you can use shell globs in the filename pattern for directories too -- so replacing all the different logrotate virtual-host-specific files with one that matches on /var/log/apache2/*/*.log would do the same, if I'm not mistaken.
I'll let you know if my "fix" has solved the issue for me.
- P
[ Parent | Reply to this comment ]
I think you can solve this by using the following syntax:
/var/log/apache2/virtualhostname/*.log /var/log/apache2/virtualhostname2/*.log {
(...)
}
Regards,
Auro
[ Parent | Reply to this comment ]
kern.*
syslog.*
messages.*
These log files are being rotated, yet there is no mention of them in the /etc/logrotate.conf nor /etc/logrotate.d directory
[ Parent | Reply to this comment ]
[ View Steve's Scratchpad | View Weblogs ]
Assuming plain syslogd usage then via a special cronjob /etc/cron.daily/sysklogd.
[ Parent | Reply to this comment ]
[ Parent | Reply to this comment ]
Unfortunately I have a big problem. Logrotate just does not rotate the syslog files. I have an up to date debian stable.
If I run logrotate -dvf /etc/logrotate.d/syslog-ng I get:
rotating pattern: /var/log/uucp.log forced&n bsp;from command line (4 rotations)
empty log files are not rotated, ol d logs are removed
considering log /var/log/uucp.log
log does not need rotating
rotating pattern: /var/log/syslog forced&nbs p;from command line (7 rotations)
empty log files are rotated, old lo gs are removed
considering log /var/log/syslog
log needs rotating
rotating log /var/log/syslog, log->rotateCount& nbsp;is 7
renaming /var/log/syslog.7.gz to /var/log/syslog.8 .gz (rotatecount 7, logstart 1, i 7 ),
renaming /var/log/syslog.6.gz to /var/log/syslog.7 .gz (rotatecount 7, logstart 1, i 6 ),
renaming /var/log/syslog.5.gz to /var/log/syslog.6 .gz (rotatecount 7, logstart 1, i 5 ),
renaming /var/log/syslog.4.gz to /var/log/syslog.5 .gz (rotatecount 7, logstart 1, i 4 ),
renaming /var/log/syslog.3.gz to /var/log/syslog.4 .gz (rotatecount 7, logstart 1, i 3 ),
renaming /var/log/syslog.2.gz to /var/log/syslog.3 .gz (rotatecount 7, logstart 1, i 2 ),
renaming /var/log/syslog.1.gz to /var/log/syslog.2 .gz (rotatecount 7, logstart 1, i 1 ),
renaming /var/log/syslog.0.gz to /var/log/syslog.1 .gz (rotatecount 7, logstart 1, i 0 ),
renaming /var/log/syslog to /var/log/syslog.1
running postrotate script
running script with arg /var/log/syslog: ;"
/etc/init.d/syslog-ng re load >/dev/null
"
error: unable to open /var/log/syslog.1 for compression
I have removed the other parts of the debug output, it is just the same.
The script /etc/logrotate.d/syslog-ng :
/var/log/messages {
rotate 4
weekly
missingok
notifempty
compress
}
/var/log/user.log {
rotate 4
weekly
missingok
notifempty
compress
}
/var/log/uucp.log {
rotate 4
missingok
notifempty
weekly
compress
}
/var/log/syslog {
rotate 7
daily
compress
postrotate
/etc/init.d/syslog-ng re load >/dev/null
endscript
}
Again I have stripped a lot of the config.
It just does not rename the original file.
Any help is greatly appreciated!! I am fighting this for some time....
Thank you very much.
mcs1
[ Parent | Reply to this comment ]
Sorry I have to get myself a big, big silly hat!
The problem lies in there:
logrotate -dvf /etc/logrotate.d/syslog-ng
-d debug means no changes are made!!! I am still waiting to see if it rotates with cron.
The original problem was with sysklogd, it did not want to logrotate with cron. Changed to syslog-ng, which has the logrotate setup that rotates /var/log/syslog, /var/log/auth.log etc. included in the scripts.
On another etch machine it works perfectly with sysklogd, even wqithout any additional scripts????
So still not at the bottom of this but at least it rotates now.
Thank you very much for a great resource!!
Mcs1
[ Parent | Reply to this comment ]
[ Parent | Reply to this comment ]
/var/log/httpd/*log {
missingok
notifempty
sharedscripts
postrotate
/bin/kill -HUP `cat /var/run/httpd.pid 2>/dev/null` 2> /dev/null || true
endscript
}
which doesn't seem to be doing anything at present, but I cant see any seetings for weekly rotation, but I can see a kill command on the http pid which makes me worried I won't being performing a graceful restart of the apache provess.
[ Parent | Reply to this comment ]
/bin/kill -HUP `cat /usr/local/apache/logs/httpd.pid 2>/dev/null` 2> /dev/null ææ true with /usr/sbin/apachectl graceful and it's job done. I will test using your suggestions above
[ Parent | Reply to this comment ]
However, I think the description of the sharedscripts option is backwards:
"sharedscripts
Run any given prerotate or postrotate script for each logfile individually. Opposite: nosharedscripts. "
It's nosharedscripts that runs the scripts for each logfile individually. sharedscripts runs the scripts once, no matter how many logfiles are rotated.
[ Parent | Reply to this comment ]
below is my content of logrotate.conf file
/var/lib/helloworld/test-bin/staticvoicedevel/Logs/Hello/*.log {
daily
missingok
rotate 10
size 5k
create 0777 chakma chakma
}
[ Parent | Reply to this comment ]
I want my file /var/log/auth.log to be in "append only" mode (chattr +a auth.log). Would the following be an appropiate section for logrotate.conf to achieve my purpose?
/var/log/auth.log {
weekly
rotate 4
prerotate
chattr -a /var/log/auth.log
endscript
postrotate
chattr +a /var/log/auth.log
killall -HUP syslogd
endscript
}
Thanks!
[ Parent | Reply to this comment ]