`inotify` уведомляет только о первом изменении в файле

#linux #file #inotify

Вопрос:

Я хотел бы написать простую программу на языке Си, которая обнаруживает изменения в обычном файле. Я решил использовать inotify . Проблема в том, что моя программа обнаруживает только первое изменение в файле. Это мой код:

 #include <sys/types.h>
#include <sys/inotify.h>
#include <unistd.h>

#define EVENT_SIZE  (sizeof(struct inotify_event))
#define BUF_LEN     (1024*(EVENT_SIZE   16))


int main()
{
    int length, i = 0;
    int fd;
    int wd;
    char buffer[BUF_LEN];

    fd = inotify_init();

    if (fd < 0) {
        perror("inotify_init");
    }

    wd = inotify_add_watch(fd, "/path/to/my/file.txt", IN_MODIFY);

    while(1)
    {
        length = read(fd, buffer, BUF_LEN);
        if (length < 0) {
            perror("read");
        }  
        
        while (i < length) {
            struct inotify_event* event = (struct inotify_event*) amp;buffer[i];
            if (event->len) {
                if (event->mask amp; IN_MODIFY) {
                        printf("The file %s was modified.n", event->name);
                }
            }
            i  = EVENT_SIZE   event->len;
        }
    }
    inotify_rm_watch(fd, wd);
    close(fd);

    return 0;
}
 

read() возвращает 0, поэтому моя программа никогда не выходит из while(i<length){} строя . Когда я прокомментировал этот цикл, кажется, что read() он возвращает любое значение только с первым изменением в файле, а затем он ждет вечно.

У вас есть какие-либо идеи, почему я не могу обнаружить изменения в файле? Заранее благодарю вас за любую помощь.

РЕДАКТИРОВАТЬ Я проверил версию cli inotify, и она также работает не так, как ожидалось. Я позвонил inotifywait -m file.txt , и там написано, что мой файл удален, но единственное изменение, которое я сделал, — это добавил в него несколько букв и сохранил. Вот полный вывод команды:

 Setting up watches.
Watches established.
file.txt OPEN 
file.txt CLOSE_WRITE,CLOSE 
file.txt ATTRIB 
file.txt DELETE_SELF 
 

Комментарии:

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

2. У меня все еще есть файл на диске, я могу открыть и отредактировать его.

3. Какие у вас есть доказательства того, что это один и тот же файл?

4. То же имя, то же место. Может ли быть так, что этот файл удаляется после каждого сохранения? Это очень странно для меня. Что же мне тогда делать, чтобы иметь возможность использовать inotify ?

5. Запустите ls -i (строчная буква «i») против файла и посмотрите, изменится ли номер индекса. Обратите внимание, что если номер индекса остается прежним, это не означает, что ваш редактор все равно не удалял файл — это просто означает, что новый файл с тем же именем мог получить тот же номер индекса. Если это происходит, вам придется установить наблюдение за каталогом inotify, следить за созданием файлов и отслеживать их тоже. Но это зависит от условий гонки и пропустит соревнования.

Ответ №1:

Во-первых, вы не выполняете сброс i в цикле, поэтому при первом его увеличении EVENT_SIZE последующие считывания длины EVENT_SIZE не будут учитываться.

Кроме того, вы проверяете, не является ли длина имени event->len файла ненулевой, но, по крайней мере, на справочной странице указано, что:

Поле имя присутствует только при возврате события для файла в отслеживаемом каталоге; оно идентифицирует имя файла в отслеживаемом каталоге.

поэтому он не будет заполнен, когда вы просматриваете только отдельный файл.

Если вы исправите его для сброса i ; и посмотрите весь каталог или не смотрите event->name , то это сработает.

Комментарии:

1. Спасибо, что указали на ошибки. Я уже исправил их. Однако у меня все еще есть проблема, из-за которой после первого изменения файла программа останавливается на read() . Из любопытства я проверил, как будет работать консольная версия inotify, позвонил inotifywait -m file.txt , и оказалось, что она тоже работает не так, как ожидалось. Я добавил результат консоли к вопросу.

2. @userr019283, ну, ваш запуск с inotifywait показывает, что файл не был изменен, а удален. Вероятно, заменен другим файлом, переименованным сверху. Вот в чем твоя проблема.