Detecting that log file has been deleted or truncated on POSIX systems?

て烟熏妆下的殇ゞ 提交于 2019-12-01 06:41:29

Checking that fstat() returns a link count of zero would fail if the file was hard linked or renamed. I would probably instead periodically compare stat()'s inode number against fstat()'s.

I'm not sure about truncation.

tail -F checks for deletion and maybe truncation, so I'd check its source to see how it implements it.

Suppose the careless system administrator kills the process. Do you really want to protect against the admin doing random things? I guess you're just looking for a way to start a new logfile from time to time, like using logrotate. There it is enough to provide a way to manually let the program reopen the logfile. The standard way to do this is to listen for the HUP-Signal in the program, and reopen the logfile if it arrives:

#include <signal.h>

volatile int f_sighup;

void sighup_handler() {
  f_sighup = 1;
}

void trap_sighup() {
  struct sigaction sa;
  int rv;

  memset(&sa, 0, sizeof(struct sigaction));
  sa.sa_handler = &sighup_handler;
  rv = sigaction(SIGHUP, &sa, NULL);
  if (-1 == rv) {
    fprintf(stderr, "warning: setting SIGHUP signal handler failed");
  }
}

int main() {
  f_sighup = 0;
  trap_sighup();
  ...
}

Then regularly check the f_sighup flag in the main program to see if the logfile should be reopened. This plays nice with tools like logrotate, which can rename the old logfile and then call kill -s HUP $PID. And the careless sysadmin can do this manually, after deleting (or better renaming) the old logfile.

You could use inotify to watch your log file, monitoring it for file system events.

BMDan

In response to søren-holm's answer

When a file is closed the modification time is changed.

that doesn't appear to be correct:

import os
from time import sleep

TMPF = '/tmp/f'

def print_stats():
    print("%s, %s" % (os.stat(TMPF).st_mtime, os.stat(TMPF).st_ctime))
    sleep(1.1)

print("Opening...")
with open(TMPF, 'w') as f:
    print_stats()
    print("Writing...")
    os.write(f.fileno(), 'apple')
    print_stats()
    print("Flushing...")
    f.flush()
    print_stats()
    print("Closing...")

print_stats()

Produces:

Opening...
1483052647.08, 1483052647.08
Writing...
1483052648.18, 1483052648.18
Flushing...
1483052648.18, 1483052648.18
Closing...
1483052648.18, 1483052648.18

Admittedly, there's a bit of Python magic going on in there; that write() is not reasonably guaranteed to be flushed automatically, but the point stands that mtime is updated when the file is modified, not when the file is closed. The behavior of ctime is going to depend on your filesystem and its mount options.

When a file is closed the modification time is changed. So check periodically on the mtime using stat() will work.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!