4

I've searched a bit and can't find anything. I don't want logrotateto touch files that are currently open. I was thinking of doing something with lsof but I didn't see a way to get any of the scripts to abort an operation. Any ideas?

4
  • 1
    Isn't that how logrotate functions? It moves the files and then creates new ones before it hups the processes to get them to reopen the new file. So I don't really understand how this would work? Can you clarify what you are trying to accomplish(bigger picture)?
    – polynomial
    Oct 6, 2011 at 3:02
  • I want all the log files in a directory that are not currently open to be manipulated (moved, zipped, emailed, whatever). The process itself already handles dumping to a new file after a certain time/size. Oct 7, 2011 at 1:15
  • Does the process rename the old files? Or does it generate a unique file name for each new log file? What is the rule for the current file name? What is the rule for the previous file names?
    – Mikel
    May 20, 2012 at 18:36
  • 1
    You could make the your app not caring about rotated files if you use copytruncate the app keep the file open and you don't need to restart your app to reopen new files.
    – AndresVia
    Jun 12, 2012 at 13:59

3 Answers 3

3

If you have nosharedscripts set (the default), and the prerotate script exits with an error the affected log file will not have any further action taken on it*.

So, in theory, you could have something like (warning, untested):

/var/log/application.log {
    nosharedscripts
    prerotate
        logfile=$1
        lsof $logfile >/dev/null
        exit $?
    endscript
    ...
}

so if lsof can't find any processes with $logfile open, the prerotate script will exit with 1, and logrotate will not take any action on that log.


*From the logrotate(8) man page on linux.die.net:

nosharedscripts
Run prerotate and postrotate scripts for every log file which is rotated
(this is the default, and overrides the sharedscripts option). The absolute
path to the log file is passed as first argument to the script. If the
scripts exit with error, the remaining actions will not be executed for the
affected log only.
...
prerotate/endscript
The lines between prerotate and endscript (both of which must appear on
lines by themselves) are executed (using /bin/sh) before the log file is
rotated and only if the log will actually be rotated. These directives may
only appear inside a log file definition. Normally, the absolute path to
the log file is passed as first argument to the script. If sharedscripts is
specified, whole pattern is passed to the script. See also postrotate. See
sharedscripts and nosharedscripts for error handling.

This may be dependant on your logrotate version, but I can't find any documentation on which versions do / do not behave this way.

2
  • This looks pretty good. Except the OP wants to only rotate files that are not open, so returning the exit code of lsof directly would give the opposite effect - one would need to convert a 0 to 1 and 1 to 0 (the exit code of lsof) to make this work right.
    – chander
    Dec 7, 2015 at 15:58
  • It works fine, but messages daily errors in /var/spool/mail/root like "error: error running non-shared prerotate script for" And it's ok, it's exactly how it works but it's also ugly. It's seems to be a problem in logrotate function.
    – Pablo Luna
    Mar 21, 2022 at 16:25
0

If the application moves the files app.log to app.log.old you could use logrotate thusly:

/path/to/app/logs/*.old {
    missingok
    nocreate
    nocopytruncate
    nodelaycompress
    notifempty

     ... 
}

This would have logrotate only deal with those files that the application was done with, and thus not open.

1
  • It's a third-party logging subsystem, so I really don't have control to do something like that. But thanks! Apr 21, 2012 at 1:19
0

You could use something like this:

/path/*.log
{
  copytruncate
  missingok
  notifempty
...

You must log in to answer this question.

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