Logrotate-Recursion

3 minute read

What isn’t working?

I actually wanted to use logrotate to clean up my logs daily and thus implement data economy: This way, IP addresses that I need for banning can be deleted uniformly and automatically after a short time. Otherwise, I’m not interested in the server logs at all and they just steal storage space.

Image: The way logrotate does the rotation looks all too recursive.

With my current configuration, logrotate creates one log file per day, but names it xyz.log.1, xyz.log.1.1, xyz.log.1.1.1 instead of the expected xyz.log.1, xyz.log.2, xyz.log.3. This means that the deletion routine no longer works and the number of logs keeps growing.

And why?

I suspect that my logrotate configuration is faulty. At the moment it looks like this:

## LOGROTATE file named 'blog'
blog/* {
# it's ok if the file doesn't already exist
missingok
# Sets the logs to rotate in intervals
daily
# Tells the system to remove old logs and only keep the most recent rotated logs
rotate 7
# Rotated logs will be compressed and kept on disk if they are 10 MB or less.
size 10M
# compress and delaycompress: These two options are used together and indicate that 
# rotated logs should be compressed (gzip) except for the most recent one.
compress

delaycompress
}

As usual, the first thing I do is consult the manual, which I call up in the console using man logrotate. It says that the file to be rotated can be specified directly (and not just selected using a wildcard *). In addition, a log behavior can also be applied to multiple file paths by placing them in front of the curly bracket, separated by spaces.

The asterisk seems to be causing exactly my problem with the cascading logs: This not only rotates the actual target file access.log, but also touches all the files that have already been rotated again.

The solution

According to the manual, I rewrite the processing instructions for Logrotate so that instead of five separate instructions for the respective logs, I only create two files. These are also simpler and shorter than the original version above.

Example:

# rotate webserver log files.
gitea/access.log
blog/access.log
landing/access.log
lectures/access.log
{
    # Sets the logs to rotate in intervals
    daily
    # Tells the system to remove old logs and only keep the most recent rotated logs
    rotate 7
    # compress and delaycompress: These two options are used together and indicate that 
    # rotated logs should be compressed (gzip) except for the most recent one.
    compress
    delaycompress
}

Configuration update

I can roll this out using my existing server configuration pipeline by simply pushing it into the repository on the server. Now I just have to manually copy the files there to /etc/logrotate.d.

Testing Logrotate

Now it would be nice if I could test whether the changes I made actually work. To do this, I use the logrotate user manual again and type:

logrotate -d -v <LOGROTATE-DESCRIPTOR-FILE>

With the debug and verbose flags activated, logrotate will apply the rotation rule specified in the configuration file and provide feedback, but will not actually make any changes or rotations on the file system. For me, the result of the test looks something like this:

lectures/access.log 
 after 1 days (7 rotations)
empty log files are rotated, old logs are removed
considering log gitea/access.log
  Now: 2024-11-28 17:19
  Last rotated at 2024-11-27 00:00
  log needs rotating
considering log blog/access.log
  Now: 2024-11-28 17:19
  Last rotated at 2024-11-16 00:00
  log needs rotating
considering log landing/access.log
  Now: 2024-11-28 17:19
  Last rotated at 2024-11-07 00:00
  log needs rotating
considering log lectures/access.log
  Now: 2024-11-28 17:19
  Last rotated at 2024-09-21 00:00
  log needs rotating
rotating log gitea/access.log, log->rotateCount is 7
[...]
renaming lectures/access.log.7.gz to lectures/access.log.8.gz (rotatecount 7, logstart 1, i 7), 
renaming lectures/access.log.6.gz to lectures/access.log.7.gz (rotatecount 7, logstart 1, i 6), 
renaming lectures/access.log.5.gz to lectures/access.log.6.gz (rotatecount 7, logstart 1, i 5), 
renaming lectures/access.log.4.gz to lectures/access.log.5.gz (rotatecount 7, logstart 1, i 4), 
renaming lectures/access.log.3.gz to lectures/access.log.4.gz (rotatecount 7, logstart 1, i 3), 
renaming lectures/access.log.2.gz to lectures/access.log.3.gz (rotatecount 7, logstart 1, i 2), 
renaming lectures/access.log.1.gz to lectures/access.log.2.gz (rotatecount 7, logstart 1, i 1), 
renaming lectures/access.log.0.gz to lectures/access.log.1.gz (rotatecount 7, logstart 1, i 0)
[...]

The output shows that all the desired log files are taken into account by logrotate and also that the rotation is carried out correctly on a daily basis.

Learned something new again 😃

Tags:

Updated: