4

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

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

在我看来,截断有点棘手。部分取决于文件描述符是否在O_APPEND模式下运行。如果日志文件没有运行O_APPEND,那么程序的日志描述符的当前写入位置不会改变,并且截断会删除前导字节,但程序会继续在“末尾”写入,留下一个幻象零的间隙字节(它们读为零,但不一定占用磁盘空间)。

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

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

4

5 回答 5

4

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

我不确定截断。

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

于 2009-01-20T17:03:34.077 回答
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. 粗心的系统管理员可以在删除(或更好地重命名)旧日志文件后手动执行此操作。

于 2009-01-20T18:10:18.903 回答
1

您可以使用inotify监视您的日志文件,监视它的文件系统事件。

于 2009-01-20T17:06:51.167 回答
1

回应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将取决于您的文件系统及其挂载选项。

于 2016-12-29T23:09:29.340 回答
-1

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

于 2016-06-15T12:25:00.880 回答