检测到POSIX系统上的日志文件已被删除或截断?

时间:2009-01-20 16:51:12

标签: c unix file-io posix truncate

假设长时间运行的进程写入日志文件。假设日志文件无限期保持打开状态。假设粗心的系统管理员删除该日志文件。程序可以检测到这种情况发生了吗?

假设fstat()报告已删除文件的链接数为零是否安全?

在我看来,截断,有点棘手。在某种程度上,它取决于文件描述符是否以O_APPEND模式运行。如果日志文件没有运行O_APPEND,那么程序日志描述符的当前写入位置不会改变,截断将删除前导字节,但程序继续写入“结束”,离开幻象零字节的间隙(它们读为零,但不一定占用磁盘上的空间)。

如果程序以O_APPEND运行,则它将在文件末尾写入,因为它当前存在。观察截断的唯一方法是注意文件位置不是程序所期望的位置 - 这反过来意味着明确地跟踪该位置。

总的来说,我并不担心截断会被删除,但任何想法都会受到欢迎。

5 个答案:

答案 0 :(得分:4)

如果文件被硬链接或重命名,则检查fstat()返回链接计数为零将失败。我可能会定期将stat()的inode编号与fstat()进行比较。

我不确定截断。

tail -F检查删除和截断,所以我会检查它的来源,看看它是如何实现的。

答案 1 :(得分:2)

假设粗心的系统管理员杀死了这个过程。你真的想要防止管理员随意做事吗?我想你只是在寻找一种不时启动新日志文件的方法,比如使用logrotate。它足以提供一种手动让程序重新打开日志文件的方法。执行此操作的标准方法是在程序中侦听HUP信号,并在文件到达时重新打开日志文件:

#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();
  ...
}

然后定期检查主程序中的f_sighup标志,看是否应该重新打开日志文件。 这对于logrotate等工具很有用,它可以重命名旧的日志文件,然后调用kill -s HUP $PID。在删除(或更好地重命名)旧日志文件之后,粗心的sysadmin可以手动执行此操作。

答案 2 :(得分:1)

您可以使用inotify来查看日志文件,并针对文件系统事件进行监控。

答案 3 :(得分:1)

回复https://s24.postimg.org/45fed3pth/Screen_Shot_2016_12_30_at_10_08_01_am.png&#39; søren-holm

  

关闭文件时,修改时间会更改。

看起来不正确:

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()

产地:

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

不可否认,那里有一些Python魔法; write()没有被合理地保证自动刷新,但重点是mtime在文件被修改时更新,而不是在文件关闭时更新。 ctime的行为将取决于您的文件系统及其挂载选项。

答案 4 :(得分:-1)

关闭文件时,修改时间会更改。因此,使用stat()定期检查mtime会有效。