Я не собираюсь прибегать к сложным инструментам, таким как режим жалоб AppArmor, мне нужны простые инструменты, чтобы сказать мне, к каким файлам обращается определенная программа.
fstat()
или получение lstat()
информации и т. Д.
Я не собираюсь прибегать к сложным инструментам, таким как режим жалоб AppArmor, мне нужны простые инструменты, чтобы сказать мне, к каким файлам обращается определенная программа.
fstat()
или получение lstat()
информации и т. Д.
Ответы:
Согласно Крису Дауну, вы можете использовать strace -p
для изучения уже запущенного процесса, чтобы увидеть, какие файлы он открывает с этого момента до момента, когда вы завершите работу strace или завершится сам процесс.
Если вы хотите, чтобы файлы открывались на протяжении всего процесса, с самого начала используйте его strace
с именем исполняемого файла. Добавление -f
гарантирует, что о любых разветвленных подпроцессах также будет сообщено. пример
# strace -e open -f /bin/id
open("/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
open("/lib64/libselinux.so.1", O_RDONLY|O_CLOEXEC) = 3
open("/lib64/libc.so.6", O_RDONLY|O_CLOEXEC) = 3
open("/lib64/libpcre.so.1", O_RDONLY|O_CLOEXEC) = 3
open("/lib64/libdl.so.2", O_RDONLY|O_CLOEXEC) = 3
open("/lib64/libpthread.so.0", O_RDONLY|O_CLOEXEC) = 3
open("/usr/lib/locale/locale-archive", O_RDONLY|O_CLOEXEC) = 3
open("/proc/thread-self/attr/current", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("/proc/self/task/1581/attr/current", O_RDONLY|O_CLOEXEC) = 3
open("/usr/share/locale/locale.alias", O_RDONLY|O_CLOEXEC) = 3
open("/usr/share/locale/en_US.UTF-8/LC_MESSAGES/coreutils.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
open("/usr/share/locale/en_US.utf8/LC_MESSAGES/coreutils.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
open("/usr/share/locale/en_US/LC_MESSAGES/coreutils.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
open("/usr/share/locale/en.UTF-8/LC_MESSAGES/coreutils.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
open("/usr/share/locale/en.utf8/LC_MESSAGES/coreutils.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
open("/usr/share/locale/en/LC_MESSAGES/coreutils.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
open("/etc/nsswitch.conf", O_RDONLY|O_CLOEXEC) = 3
open("/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
open("/lib64/libnss_files.so.2", O_RDONLY|O_CLOEXEC) = 3
open("/etc/passwd", O_RDONLY|O_CLOEXEC) = 3
open("/etc/group", O_RDONLY|O_CLOEXEC) = 3
open("/etc/group", O_RDONLY|O_CLOEXEC) = 3
uid=0(root) gid=0(root) groups=0(root) context=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023
+++ exited with 0 +++
#
Использование lsof
для просмотра файлов , открытых в данный момент у процесса
# lsof -p $(pidof NetworkManager)
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
NetworkMa 722 root cwd DIR 253,0 224 64 /
NetworkMa 722 root rtd DIR 253,0 224 64 /
NetworkMa 722 root txt REG 253,0 2618520 288243 /usr/sbin/NetworkManager
NetworkMa 722 root mem REG 253,0 27776 34560 /usr/lib64/libnss_dns-2.17.so
[...]
#
Если у вас есть SystemTap, вы можете контролировать весь хост на наличие открываемых файлов.
[root@localhost tmp]# cat mon
#!/usr/bin/env stap
probe syscall.open { printf ("pid %d program %s opened %s\n", pid(), execname(), filename) }
# ./mon
pid 14813 program touch opened "/etc/ld.so.cache"
pid 14813 program touch opened "/lib64/libc.so.6"
pid 14813 program touch opened 0x7f7a8c6ec8d0
pid 14813 program touch opened "foo2"
[...]
#
open
не единственный соответствующий системный вызов. Например, можно передавать файловые дескрипторы между процессами через сокет Unix, и существует openat
системный вызов, который также может открыть файл.
strace
, см. Строки ENOENT в примере.
Вы можете использовать opensnoop
из BCC, который использует eBPF под капотом:
# ./opensnoop -p 1576
PID COMM FD ERR PATH
1576 snmpd 11 0 /proc/sys/net/ipv6/conf/lo/forwarding
1576 snmpd 11 0 /proc/sys/net/ipv6/neigh/lo/base_reachable_time_ms
1576 snmpd 9 0 /proc/diskstats
1576 snmpd 9 0 /proc/stat
1576 snmpd 9 0 /proc/vmstat
[...]
Это довольно эффективно, так как он использует kprobes вместо перезапуска системных вызовов, как это strace
происходит.
Вы также можете сделать это с strace
(возможно, с помощью -f
для отслеживания дочерних элементов отслеживаемого процесса), но его способ работы, включающий перезапуск системных вызовов как часть ptrace , несколько замедлит ваше приложение:
# strace -e open -p 15735
open("/usr/lib/locale/locale-archive", O_RDONLY|O_CLOEXEC) = 3
open("/usr/lib/gconv/gconv-modules.cache", O_RDONLY) = -1 ENOENT (No such file or directory)
open("/usr/lib/gconv/gconv-modules", O_RDONLY|O_CLOEXEC) = 3
open("/usr/lib/python2.7/site-packages", O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC) = 4
open("/usr/lib/locale/locale-archive", O_RDONLY|O_CLOEXEC) = 3
open("/etc/localtime", O_RDONLY|O_CLOEXEC) = 8
[...]
При желании вы также можете запустить свое приложение, используя strace [executable]
или strace -f [executable]
.
Мой любимый инструмент для отслеживания файлов, которые открывает приложение, - это мощная инфраструктура мониторинга sysdig
.
Для мониторинга всех открытых файлов, открытых программой с именем exe_file
:
sudo sysdig -p "proc.name=exe_file %12user.name %6proc.pid %12proc.name %3fd.num %fd.typechar %fd.name" evt.type=open
Отслеживание всех файлов, открытых на сервере:
sudo sysdig -p "%12user.name %6proc.pid %12proc.name %3fd.num %fd.typechar %fd.name" evt.type=open
Создание файла трассировки, который будет содержать только записи событий в домашних каталогах (которые мы можем проверить позже sysdig -r writetrace.scap.gz
):
sudo sysdig -p "%user.name %proc.name %fd.name" "evt.type=write and fd.name contains /home/" -z -w writetrace.scap.gz
Видя все на уровне системного вызова, процесс по имени exe_file
делает:
sudo sysdig proc.name=exe_file
У Sysdig есть много долот, см. Более интересные вещи, которые он может сделать:
У вас также есть dtrace
то, что мало используется в Linux, но все еще широко используется с операционными системами * BSD:
# Files opened by process,
dtrace -n 'syscall::open*:entry { printf("%s %s",execname,copyinstr(arg0)); }'
Кроме того sysdig
, strace
и у dtrace
вас также есть ltrace
, какие записи / перехватывает сигналы / динамические библиотеки / системные вызовы, которые вызываются / принимаются процессом:
ltrace
это программа, которая просто запускает указанную команду до ее выхода. Он перехватывает и записывает динамические библиотечные вызовы, которые вызываются исполняемым процессом, и сигналы, полученные этим процессом. Он также может перехватывать и распечатывать системные вызовы, выполняемые программой.
$ltrace exe_file
_libc_start_main(0x400624, 1, 0x7ffcb7b6d7c8, 0x400710 <unfinished ...>
time(0) = 1508018406
srand(0x59e288e6, 0x7ffcb7b6d7c8, 0x7ffcb7b6d7d8, 0) = 0
sprintf("mkdir -p -- '/opt/sms/AU/mo'", "mkdir -p -- '%s'", "/opt/sms/AU/mo") = 28
system("mkdir -p -- '/opt/sms/AU/mo'" <no return ...>
--- SIGCHLD (Child exited) ---
<... system resumed> ) = 0
rand(2, 0x7ffcb7b6d480, 0, 0x7f9d6d4622b0) = 0x2d8ddbe1
sprintf("/opt/sms/AU/mo/tmp.XXXXXX", "%s/tmp.XXXXXX", "/opt/sms/AU/mo") = 29
mkstemp(0x7ffcb7b6d5c0, 0x40080b, 0x40081a, 0x7ffffff1) = 3
sprintf("/opt/sms/AU/mo/tmp.XXXXXX", "%s/tmp.XXXXXX", "/opt/sms/AU/mo") = 29
mkstemp(0x7ffcb7b6d5c0, 0x40080b, 0x40081a, 0x7ffffff1) = 4
+++ exited (status 0) +++
Если программа небольшая, вы можете также рассмотреть возможность ее дизассемблирования objdump -d exe_file
или дизассемблирования / декомпиляции Hopper
, чтобы увидеть все файлы , с которыми она имеет дело.
Для более подробной информации смотрите: Понимание того, что делает бинарный файл Linux
В качестве первого подхода я бы также сделал:
strings exe_file
Это недорогой подход, и в случае удачи некоторые имена файлов могут просто присутствовать в режиме ASCII в двоичном файле, если повезет.
См. Также связанный ответ. Почему истина и ложь так велики?
Если двоичные файлы / файлы поставляются вместе с дистрибутивом, вы также можете получить исходные коды из репозиториев исходных текстов дистрибутива или из официальных репозиториев реальной утилиты.
В качестве последнего ресурса вы всегда можете использовать такие инструменты, как gdb или rr для отладки двоичного файла в режиме реального времени.
sysdig
ошибке (вы используете ARM?), Пожалуйста, напишите новый вопрос.