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

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

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

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

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


person J.J    schedule 22.09.2015    source источник
comment
Круто, тогда я так и сделаю :)   -  person J.J    schedule 22.09.2015
comment
Отлично, тогда я преобразую свой комментарий в ответ :)   -  person rkachach    schedule 22.09.2015


Ответы (1)


Взгляните на исходный код «strace» (и его -f для трассировки дочерних элементов). Он делает в основном то, что вы пытаетесь сделать. Он фиксирует все системные вызовы процесса (или его дочерних элементов), поэтому вы можете найти такие операции, как «открыть» и т. д.

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

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

person rkachach    schedule 22.09.2015