Обнаружить, что файл журнала был удален или усечен в системах POSIX? - PullRequest
4 голосов
/ 20 января 2009

Предположим, что длительный процесс записывает данные в файл журнала. Предположим, что файл журнала остается открытым бесконечно долго. Предположим, что неосторожный системный администратор удаляет этот файл журнала. Может ли программа обнаружить, что это произошло?

Безопасно ли предположить, что fstat() сообщит нулевой счетчик ссылок для удаленного файла?

Усечение, как мне кажется, немного сложнее. Частично это зависит от того, работает ли дескриптор файла в режиме O_APPEND. Если файл журнала не выполняется с O_APPEND, то текущая позиция записи дескриптора журнала программы не изменяется, и усечение удаляет начальные байты, но программа продолжает писать в конце, оставляя пробел фантомных нулевых байтов (они читаются как нули, но не обязательно занимают место на диске).

Если программа работает с O_APPEND, тогда она запишет в конец файла, как он существует в настоящее время. Единственный способ наблюдать усечение - это заметить, что позиция файла находится не там, где программа ожидала этого, что в свою очередь означает явное отслеживание этой позиции.

В целом, я не так обеспокоен усечением, как удалением, но любые мысли приветствуются.

Ответы [ 5 ]

4 голосов
/ 20 января 2009

Проверка того, что fstat() возвращает нулевой счетчик ссылок, не удалась бы, если бы файл был жестко связан или переименован. Возможно, вместо этого я бы периодически сравнивал номер инода stat() с fstat().

Я не уверен насчет усечения.

tail -F проверяет удаление и, возможно, усечение, поэтому я проверю его источник, чтобы увидеть, как он его реализует.

2 голосов
/ 20 января 2009

Предположим, неосторожный системный администратор убивает процесс. Вы действительно хотите защитить администратора от случайных действий? Я думаю, вы просто ищете способ время от времени запускать новый лог-файл, например, использовать 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. И неосторожный системный администратор может сделать это вручную, удалив (или лучше переименовав) старый файл журнала.

1 голос
/ 30 декабря 2016

В ответ на søren-holm 's answer

Когда файл закрыт, время изменения изменяется.

, что кажется неправильным:

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

По общему признанию, там происходит немного магии Питона; что write() не может быть разумно гарантированно очищено автоматически, но стоит отметить, что mtime обновляется при изменении файла, а не при его закрытии. Поведение ctime будет зависеть от вашей файловой системы и параметров монтирования.

1 голос
/ 20 января 2009

Вы можете использовать inotify для просмотра вашего файла журнала и отслеживания его событий в файловой системе.

0 голосов
/ 15 июня 2016

Когда файл закрыт, время модификации изменяется. Поэтому периодически проверяйте mtime с помощью stat ().

...