While the world is divided on whether the humble named pipe is friend or foe, it is probably the simplest solution to your problem. It does have a few drawbacks (in that you need to create the pipes ahead of time), but it eliminates the need for a cron and allows you to used the logging pipe-filter of your choice.
Here's an example using cronolog on access.log
:
- Pick a path for our named pipe. I intend to keep my logs in
/var/log/nginx
, so I'll put my pipes there as well. The name is up to you; I append .fifo
, and it's access.log
, so mine will be at /var/log/nginx/access.log.fifo
.
- Delete the file if it exists.
Make a named pipe for the logfile:
mkfifo /var/log/nginx/access.log.fifo
Configure nginx.conf
to point the log at the pipe you just made:
access_log /var/log/nginx/access.log.fifo;
Modify your init.d script to start the log rotator listening to the pipe before we start the server:
LOGS="/var/log/nginx"
pkill -f "/usr/sbin/cronolog --symlink $LOGS/access.log"
( cat $LOGS/access.log.fifo | /usr/sbin/cronolog --symlink $LOGS/access.log "$LOGS/%Y/%m/%d/access.log" ) &
A similar commandline would be used for rotatelogs
should you prefer it to cronolog
-- see their docs for the syntax.
If your distrobution has a start-stop-daemon
, you should be using that instead, as it theoretically has whatever special knoweldge about your platform there is, and taking care of pkill
for you. Simply wrap the command in a script, and pass it as --exec
to start-stop-daemon
in your init.d/nginx
.
man logrotate
dateformat format_string
Specify the extension for dateext using the notation similar to strftime(3) function. Only %Y %m
%d and %s specifiers are allowed. The default value is -%Y%m%d. Note that also the character sep‐
arating log name from the extension is part of the dateformat string. The system clock must be set
past Sep 9th 2001 for %s to work correctly. Note that the datestamps generated by this format
must be lexically sortable (i.e., first the year, then the month then the day. e.g., 2001/12/01 is
ok, but 01/12/2001 is not, since 01/11/2002 would sort lower while it is later). This is because
when using the rotate option, logrotate sorts all rotated filenames to find out which logfiles are
older and should be removed.
Can anyone please tell me if "dateext" is correct? I want the log
filename to be something like "access.log-2010-12-04".
Insert a dateformat
directive to your configuration file, something like this:
/usr/local/nginx/logs/*.log {
daily
dateext
dateformat -%Y-%m-%d
...
One more thing: Can I do the log rotation every day on a specific time
(e.g. 11 pm)?
By default, logrotate is running via cron at 4 A.M:
/etc/cron.daily/logrotate
#!/bin/sh
/usr/sbin/logrotate /etc/logrotate.conf
EXITVALUE=$?
if [ $EXITVALUE != 0 ]; then
/usr/bin/logger -t logrotate "ALERT exited abnormally with [$EXITVALUE]"
fi
exit 0
You can move this file to somewhere and rename to logrotate.sh
, then create a new file in /etc/cron.d/
as belows:
0 23 * * * root /path/to/logrotate.sh
Best Answer
logrotate configuration file:
Out:
hour is not supported. You can use the postrotate to rename.