Каков наилучший способ определить, какие файлы используются / изменены / созданы / удалены процессом?

Я хочу написать программное обеспечение, которое будет обнаруживать все используемые / созданные / измененные / удаленные файлы во время выполнения процесса (и его дочерних процессов). Процесс еще не запущен - пользователь предоставляет командную строку, которая впоследствии будет подвергнута дополнительной обработке через bash, поэтому мы можем делать что-то до и после выполнения и контролировать среду, в которой запускается команда.

До сих пор я думал о четырех методах, которые могут быть полезны:

  • Разобрать командную строку, чтобы определить упомянутые файлы и каталоги. Предположим, что все файлы, указанные явно, используются. Проверьте каталоги до / после для созданных / удаленных файлов. MD5 существующие файлы до / после, чтобы увидеть какие-либо изменения. Это работает во всех операционных системах и средах, но, очевидно, имеет серьезные ограничения (не работает, когда команда "./script.sh")
  • Запустите процесс через другой процесс, такой как strace (dtruss для OSX и есть эквивалентные программы для Windows), который прослушивает системные вызовы. Разобрать выходной файл, чтобы найти используемые / измененные / удаленные / созданные файлы. Плюсы в том, что он более чувствителен, чем метод MD5, и может работать с script.sh. Минусы в том, что она очень специфична для ОС (dtruss требует привилегий суперпользователя, даже если процесс не запускается - выходные данные инструментов различны) Может также создавать огромные файлы журнала, если есть много операций чтения / записи, и, безусловно, замедлит работу.
  • Интегрируйте что-то похожее в ядро. Очевидно, что все еще зависит от ОС, но, по крайней мере, сейчас мы вызываем кадры, создавая общий формат вывода для всех ОС. Не будет создавать огромные файлы журналов и даже может прекратить перехватывать системные вызовы, скажем, read() после того, как процесс запросит первое чтение () для файла. Я думаю, что это то, что делает инструмент inotify, но я не знаком с ним вообще, ни с программированием ядра!
  • Запустите процесс, используя трюк LD_PRELOAD (называемый DYLD_INSERT_LIBRARIES в OSX, не уверенный, существует ли он в Windows), который в основном перезаписывает любой вызов open() процессом с нашей собственной версией open(), которая регистрирует то, что мы открываем. То же самое для записи, чтения и т. Д. Это очень просто сделать и очень эффективно, так как вы по сути учите процесс регистрации самого себя. Недостатком является то, что он работает только для динамически связанных процессов, и я понятия не имею о распространенности динамически / статически связанных программ. Я даже не знаю, возможно ли перед выполнением определить, является ли процесс динамически или статически связанным (с намерением использовать этот метод по умолчанию, но отступить к менее производительному методу, если это невозможно).

Мне нужна помощь в выборе оптимального пути для спуска. Я уже реализовал первый метод, потому что он был прост и дал мне возможность поработать с бэкэндом журналирования ( http://ac.gt/log), но на самом деле мне нужно перейти на один из других методов. Ваш совет был бы неоценимым:)

1 ответ

Решение

Посмотрите на исходный код "strace" (и его -f для отслеживания детей). Это в основном то, что вы пытаетесь сделать. Он фиксирует все системные вызовы процесса (или его дочерние элементы), поэтому вы можете использовать grep для таких операций, как "open" и т. Д.

Следующая ссылка содержит несколько примеров реализации вашего собственного strace с помощью системного вызова ptrace:

https://blog.nelhage.com/2010/08/write-yourself-an-strace-in-70-lines-of-code/

Другие вопросы по тегам