Отслеживание файла на наличие изменений в Linux

Вопрос:

Есть ли способ отслеживать ход файла в Linux (т.е. новый файл/файл сохранения)?

Подробности:

Мне известен inotify, который можно использовать для отслеживания целых папок на предмет создания, удаления и изменения файлов. . Однако это очень низкий уровень. Текстовые редакторы часто при сохранении файла записывают измененный буфер во временное место, затем перемещают его и перезаписывают исходный файл. inotify увидит это как CREATE и MOVE, тогда как мне нужно MODIFY.

Мне кажется нелогичным, что каждый раз, когда файл сохраняется, он будет интерпретироваться как новый файл. Есть ли какое-либо идентифицирующее значение файла, которое я могу использовать, чтобы отличить создание нового нового файла от сохранения существующего файла? Другой способ задать этот вопрос: «Как работают такие программы, как Beagle, Spotlight, Поиск Windows и Google Desktop обойти Эта проблема"?

Цель:

Вот хороший способ описать то, что я хочу: используя Vim, если я открою файл и сохраню его (:w), этот файл будет записан во временный файл, а затем перемещен в исходный файл, обманывая inotify, заставляя его поверить, что был создан совершенно новый файл, который затем использовался для перезаписи исходного файла. Однако, если добавить файл в subversion (svn), а затем открыть этот файл с помощью Vim и сохранить его (:w), svn будет знать, что сохраненный файл на самом деле является измененным файлом, а не новым. Откуда svn это знает?


person puk    schedule 10.05.2012    source источник


Ответы (2)


Я попытаюсь объяснить, в то время как новое или сохраненное может выглядеть так же в Linux. Одно большое отличие Linux от Windows заключается в том, что время создания файла не сохраняется вместе с индексным узлом, сохраняется только время доступа, модификации (изменения содержимого файла) и изменения (изменения индексного узла). Поэтому, если вы не храните информацию в другом месте, например, внутри самого файла в качестве метаданных, вы не можете сказать, был ли файл только что создан или только что изменен.

person johnshen64    schedule 10.05.2012
comment
Даже если время создания было сохранено, не будет ли оно перезаписано текстовым редактором в этом случае? Что, если бы текстовый редактор вместо этого сохранял файлы вот так cp a.txt a.txt~; rm a.txt; cp a.txt~ a.txt? Есть ли способ обойти это, что вы можете придумать? - person puk; 11.05.2012
comment
Моя проблема не в том, что я не знаю, когда файл был создан, а в том, что такие программы, как vim, записывают во временный файл, а затем перемещают его в исходный файл, поэтому невозможно сказать, когда файл перезаписывается полностью или просто случайно изменен. - person puk; 11.05.2012
comment
Правда, временные файлы затрудняют определение. Вас беспокоит безопасность или что-то другое? Если безопасность то могут помочь программы типа tripwire, хотя я точно не знаю как они определяют когда файл меняется тоже. - person johnshen64; 11.05.2012
comment
Пожалуйста, посмотрите пример, который я добавил выше. Безопасность сейчас не проблема. Я добавляю файлы в базу данных и хочу знать, когда создается новый файл (в этом случае я добавляю новую строку) или когда файл сохраняется 100 000 раз (в этом случае я НЕ хочу добавлять 100 000 раз). новые строки) - person puk; 11.05.2012
comment
svn хранит собственные метаданные и сравнивает содержимое файла между репозиторием и рабочим каталогом. поэтому, чтобы сделать то же самое, вы должны перед вставкой записи сделать что-то подобное, чтобы проверить, существует ли уже строка. уникально ли ваше имя файла или хотя бы полный путь? вам нужно сохранить какой-то уникальный ключ, чтобы идентифицировать новый файл. - person johnshen64; 11.05.2012
comment
Я думал об этом, но что представляет собой уникальный ключ для файла? Когда кто-то модифицирует файл, все уникальное в нем было изменено. Есть ли что-то уникальное в иноде? Существует ли пакет Linux, который изменяет индексные дескрипторы таким же образом, как ACL изменяют базовые разрешения Linux? - person puk; 11.05.2012
comment
да, это будет inode. если вы вставите строку только тогда, когда будет создан новый файл (inode), вам придется где-то хранить все узлы, а затем, когда вы обнаружите файл, вы сравните его с вашим db и посмотрите, есть ли там inode или нет. это также позволит избежать вставки строки из-за создания ссылки. не зная вашей точной системы хранения, я думаю, что это лучшее, что я могу придумать, хотя проблема звучит довольно интересно и сложно. - person johnshen64; 11.05.2012
comment
на самом деле номер инода (i-число) может монотонно увеличиваться (не уверен, что это применимо ко всем файловым системам), поэтому на самом деле вам может потребоваться сохранить только текущий наибольший номер инода, что значительно упростит задачу. вам, возможно, придется заглянуть в исходный код, чтобы быть уверенным. - person johnshen64; 11.05.2012
comment
простите меня, но я не вижу, как индексный дескриптор поможет мне определить, когда перезапись на самом деле является замаскированными временными файлами. Я думал о том, чтобы иметь базу данных действий с файлами (create, modify, move), и когда есть move, я просматриваю трассировку и смотрю, совпадает ли move_to с возможным move_from (и файл move_from был без редактирования), то я могу с уверенностью сказать, что это была операция save. Хотя БД может быть не лучшим выбором, так как это будет рекурсивный поиск - person puk; 11.05.2012
comment
См. здесь дополнительную информацию о том, что лежит в основе моей проблемы stackoverflow.com/a/10544487/654789 - person puk; 11.05.2012
comment
Вы правы, чтобы разобраться с временными файлами, надо что-то делать самому. Не уверен, что трассировка — лучший способ, но если вы знаете временное место для создания файла, скажем, /var/tmp и /tmp, вы также можете просто игнорировать эти места, когда есть путь к файлу. Обычно приложение хранит временные файлы в определенных местах. - person johnshen64; 11.05.2012
comment
Например, Vim использует временный файл 4913, но я бы предпочел общее решение. Хотя я бы не стал отказываться от какой-либо программы, чтобы разделить файл, записать его в два файла подкачки, а затем объединить их обратно в исходный файл... - person puk; 11.05.2012
comment
@ johnshen64 Чтение данных файла не должно быть обязательным. Если open(2) посылает общесистемный сигнал, данные файловой системы вообще не задействованы. - person user877329; 24.08.2013

johnshen64 ответил вам, почему вы не видите его измененным. Что касается SVN (или Git), они распознают файл как измененный, поскольку сохраняют «ключ» уже управляемых файлов.

Так что для вашей базы данных вам нужно будет сделать то же самое. Например, вы можете использовать простой числовой хеш из имени файла (или самого имени файла, но сравнение строк происходит медленно) и выполнить быстрый запрос, чтобы увидеть, находится ли файл уже под управлением, прежде чем добавлять его.

person Huygens    schedule 11.05.2012
comment
то, что вы описываете, проверяя, существует ли уже файл в моей БД, не решает мою проблему: различие между удалением/перезаписью файла и косвенным редактированием существующего файла путем создания файла подкачки и перезаписывания исходного файла с помощью Это. - person puk; 11.05.2012
comment
Поэтому вам нужно сделать различие между новым файлом с тем же именем файла и обновленным файлом (который был обновлен с использованием временного файла). Я не понял этого из вашего вопроса. Вам, вероятно, нужно посмотреть возможные метаданные, которые вы можете прикрепить к файлу в файловой системе ext *, эти метаданные должны быть реплицированы временным свопом во время редактирования. Или система безопасности типа SELinux не работала бы! - person Huygens; 12.05.2012
comment
ДА! Кроме того, да, метаданные - это именно то, что я ищу, но я не знаю, с чего начать (возможно ли это вообще?) Ваше последнее предложение Или система безопасности, такая как SELinux, не будет работать, немного расплывчато. Не могли бы вы уточнить, пожалуйста. - person puk; 13.05.2012
comment
Вы должны задать другой вопрос по этому поводу. Я знаю, что это особенность файловых систем в Linux, но я не знаю, как ее использовать. Что касается SELinux, для обеспечения соблюдения правил он помечает файлы (используя метаданные) вместо использования пути, как это делает AppArmor. Это означает, что если файл будет удален и заменен, то метка будет потеряна, и SELinux ее обнаружит, а AppArmor этого не заметит. С другой стороны, при обновлении программного обеспечения вам необходимо переименовать файл с помощью SELinux, но в AppArmor это не требуется. См., например: redhat.com/f/pdf/whitepapers/Filesystem_Labeling_SELinux.pdf< /а> - person Huygens; 13.05.2012