4

I'm testing a logrotate configuration in /tmp. I'd like

  1. to configure a default logrotate policy for /tmp/*.log files using my test configuration file /tmp/logrotate.conf
  2. to handle a particular log file /tmp/special.log with a different policy configured in a separate logrotate config test file: /tmp/logrotate.d/included

But logrotate's response to my configuration is to say:

error: /tmp/logrotate.d/included:1 duplicate log entry for /tmp/special.log

What should I do differently?

Here's my /tmp/logrotate.conf

compress
missingok
notifempty
size 512k
copytruncate
rotate 2
su

# here's my attempt at applying the default policy to all /tmp/*.log
/tmp/*.log {}

# and here I intend to include any overrides
include /tmp/logrotate.d/included

And here's /tmp/logrotate.d/included

/tmp/special.log {
    size 300
}

Here's the debug output.

$ sudo logrotate -d ./logrotate.conf

reading config file ./logrotate.conf
including /tmp/logrotate.d/included
reading config file /tmp/logrotate.d/included
error: /tmp/logrotate.d/included:1 duplicate log entry for /tmp/special.log

Handling 2 logs

rotating pattern: /tmp/*.log  524288 bytes (2 rotations)
empty log files are not rotated, old logs are removed
considering log /tmp/normal.log
  log does not need rotating
considering log /tmp/special.log
  log does not need rotating

rotating pattern: /tmp/special.log  300 bytes (2 rotations)
empty log files are not rotated, old logs are removed
No logs found. Rotation not needed.
  1. The error surprises me because I thought according to the man page "Later config files may override the options given in earlier files, so the order in which the logrotate config files are listed is important."
  2. Why does it say at the end when handling pattern /tmp/special.log that no logs were found? The file /tmp/special.log exists and is larger than 300 bytes.
3
  • Are your config files really in /tmp/logrotate.d - are you just testing from there rather than /etc/logrotate.d? Can you post the command you used when you tested?
    – javabrett
    Commented May 12, 2015 at 0:27
  • I'm just testing in /tmp. With the current working directory of /tmp I run this command: sudo logrotate -d ./logrotate.conf <next sentence:> normal.log and special.log are owned by me. logrotate.conf and logrotated.d/included are owned by root because when everything had been owned by me there was a permissions issue in changing some property while logrotate was running. Commented May 12, 2015 at 16:37
  • The permissions issue (when everything was owned by me and run non-sudo) was this: switching euid to 0 and egid to 0 ... error: error switching euid to 0 and egid to 0: Operation not permitted Commented May 12, 2015 at 16:44

2 Answers 2

2

The developers of logrotate have intentionally forbidden overlapping log-file definitions, so whilst more-specific rules are allowed to follow general rules in the configuration, log-file path overlaps still generate an error. This is partly for the benefit of package-maintainers who include logrotate rules, and the users of those packages, so that overlaps become obvious and can be reported.

If the specific-rule and generic-rule log files must reside in the same directory (can you reconfigure to move them?), then you have to create and maintain an explicit exclusion to the generic rule for each overlapping path. logrotate.conf doesn't provide for this explicitly, but if your logrotate runs in an environment with shell extglob glob-extensions enabled, the exclusion is possible. You can check whether extglob is enabled by running shopt extglob in the same root environment your crontab logrotate will run, and it can be explicitly enabled (if required) with shopt -s extglob.

Once extglob is enabled, it allows for constructs such as:

/tmp/!(special).log {}

... which will prevent the overlap with your more-specific later rule, avoiding the error.

1

As @javabrett already wrote, logrotate conciously appears to forbid overlapping rules. I've found another way to prioritise one of the overlapping rules though:

The rules of the logrotate.conf are executed from top to bottom, so make sure to put the more specific match rule above the generic one.

Then you can use the ignoreduplicates directive to make logrotate ignore additional rules further down the file for things matched by this rule.

In your example:

compress
missingok
notifempty
size 512k
copytruncate
rotate 2
su

/tmp/special.log {
    size 300
    ignoreduplicates
}

# here's my attempt at applying the default policy to all /tmp/*.log
/tmp/*.log {}

For simplicity, I've put all the rules into the same file. I have not checked whether including from another file still works by just moving the include directive higher up.

In nowadays world where the periodical logrotate job might run as a systemd timer without a proper shell, this is a more robust solution than messing around with shell globbing.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .