- strace — отслеживаем выполнение процесса
- КОМАНДА STRACE LINUX
- ПРИМЕРЫ ИСПОЛЬЗОВАНИЯ STRACE
- 1. ЗАПУСК ПРОГРАММЫ
- 2. ПОДКЛЮЧЕНИЕ К ЗАПУЩЕННОЙ ПРОГРАММЕ
- 3. ФИЛЬТРАЦИЯ СИСТЕМНЫХ ВЫЗОВОВ
- 4. ВОЗВРАЩЕНИЕ ОШИБКИ
- 5. ФИЛЬТРАЦИЯ ПО ПУТИ
- 6. СТАТИСТИКА СИСТЕМНЫХ ВЫЗОВОВ
- 7. ОТСЛЕЖИВАНИЕ ВРЕМЕНИ ВЫПОЛНЕНИЯ
- Write strace output to a file
- 2 Answers 2
strace — отслеживаем выполнение процесса
Thank you for reading this post, don’t forget to subscribe!
strace — утилита для Linux, которая позволяет отследить выполнение системных вызовов ( system call ) и сигналов к ядру системы
КОМАНДА STRACE LINUX
Как я уже сказал, команда strace показывает все системные вызовы программы, которые та отправляет к системе во время выполнения, а также их параметры и результат выполнения. Но при необходимости можно подключиться и к уже запущенному процессу. Перед тем, как перейти к практике, разберём опции утилиты и её синтаксис:
$ strace опции команда аргументы
В самом простом варианте strace запускает переданную команду с её аргументами и выводит в стандартный поток ошибок все системные вызовы команды. Давайте разберём опции утилиты, с помощью которых можно управлять её поведением:
- -i — выводить указатель на инструкцию во время выполнения системного вызова;
- -k — выводить стек вызовов для отслеживаемого процесса после каждого системного вызова;
- -o — выводить всю информацию о системных вызовах не в стандартный поток ошибок, а в файл;
- -q — не выводить сообщения о подключении о отключении от процесса;
- -qq — не выводить сообщения о завершении работы процесса;
- -r — выводить временную метку для каждого системного вызова;
- -s — указать максимальный размер выводимой строки, по умолчанию 32;
- -t — выводить время суток для каждого вызова;
- -tt — добавить микросекунды;
- -ttt — добавить микросекунды и количество секунд после начала эпохи Unix;
- -T — выводить длительность выполнения системного вызова;
- -x — выводить все не ASCI-строки в шестнадцатеричном виде;
- -xx — выводить все строки в шестнадцатеричном виде;
- -y — выводить пути для файловых дескрипторов;
- -yy — выводить информацию о протоколе для файловых дескрипторов;
- -c — подсчитывать количество ошибок, вызовов и время выполнения для каждого системного вызова;
- -O — добавить определённое количество микросекунд к счетчику времени для каждого вызова;
- -S — сортировать информацию выводимую при опции -c. Доступны поля time, calls, name и nothing. По умолчанию используется time;
- -w — суммировать время между началом и завершением системного вызова;
- -e — позволяет отфильтровать только нужные системные вызовы или события;
- -P — отслеживать только системные вызовы, которые касаются указанного пути;
- -v — позволяет выводить дополнительную информацию, такую как версии окружения, статистику и так далее;
- -b — если указанный системный вызов обнаружен, трассировка прекращается;
- -f — отслеживать также дочерние процессы, если они будут созданы;
- -ff — если задана опция -o, то для каждого дочернего процесса будет создан отдельный файл с именем имя_файла.pid.
- -I — позволяет блокировать реакцию на нажатия Ctrl+C и Ctrl+Z;
- -E — добавляет переменную окружения для запускаемой программы;
- -p — указывает pid процесса, к которому следует подключиться;
- -u — запустить программу, от имени указанного пользователя.
Вы знаете основные опции strace, но чтобы полноценно ею пользоваться, нужно ещё разобраться с системными вызовами, которые используются чаще всего. Мы не будем рассматривать все, а только основные. Многие из них вы уже и так знаете, потому что они называются так же, как и команды в терминале:
- fork — создание нового дочернего процесса;
- read — попытка читать из файлового дескриптора;
- write — попытка записи в файловый дескриптор;
- open — открыть файл для чтения или записи;
- close — закрыть файл после чтения или записи;
- chdir — изменить текущую директорию;
- execve — выполнить исполняемый файл;
- stat — получить информацию о файле;
- mknod — создать специальный файл, например, файл устройства или сокет;
А теперь разберём примеры strace Linux.
ПРИМЕРЫ ИСПОЛЬЗОВАНИЯ STRACE
1. ЗАПУСК ПРОГРАММЫ
Самый простой способ запуска утилиты — просто передать ей в параметрах имя команды или исполняемый файл программы, которую мы хотим исследовать. Например, uname:
Как и ожидалось, мы видим список системных вызовов, которые делает утилита, чтобы узнать версию ядра. Синтаксис вывода такой:
имя_системного_вызова (параметр1, параметр2) = результат сообщение
Имя системного вызова указывает, какой именно вызов использовала программа. Для большинства вызовов характерно то, что им нужно передавать параметры, имена файлов, данные и так далее. Эти параметры передаются в скобках. Далее идет знак равенства и результат выполнения. Если всё прошло успешно, то здесь будет ноль или положительное число. Если же возвращается отрицательное значение, делаем вывод, что произошла ошибка. В таком случае выводится сообщение.
Например, в нашем выводе есть сообщения об ошибке:
openat(AT_FDCWD, «/usr/local/cuda-6.5/lib64/tls/x86_64/libc.so.6», O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
Здесь результат выполнения -1 и сообщение говорит, что файл не найден. Но на работу программы это не влияет. Это проблема подключения сторонних библиотек и к этой утилите она не имеет отношения. А основная работа программы выполняется строчкой:
И здесь ядро вернуло положительный результат.
2. ПОДКЛЮЧЕНИЕ К ЗАПУЩЕННОЙ ПРОГРАММЕ
Если программа, которую нам надо отследить, уже запущена, то не обязательно её перезапускать с нашей утилитой. Можно подключиться к ней по ее идентификатору PID . Для тестирования этой возможности запустим утилиту dd, которая будет записывать нули из /dev/zero в файл file1:
Теперь узнаем PID нашего процесса, поскольку он такой один, можно воспользоваться pidof, вы же можете использовать ps:
И осталось подключиться к нашему процессу:
В выводе утилиты мы видим, что она читает данные из одного места с помощью вызова read и записывает в другое через write. Чтобы отсоединится от процесса, достаточно нажать Ctrl+C. Дальше рассмотрим примеры strace Linux для фильтрации данных.
3. ФИЛЬТРАЦИЯ СИСТЕМНЫХ ВЫЗОВОВ
Утилита выводит слишком много данных, и, зачастую, большинство из них нас не интересуют. С помощью опции -e можно применять различные фильтры для более удобного поиска проблемы. Мы можем отобразить только вызовы stat, передав в опцию -e такой параметр trace=stat:
sudo strace -e trace=stat nautilus
Кроме непосредственно системных вызовов, в качестве параметра для trace можно передавать и такие значения:
- file — все системные вызовы, которые касаются файлов;
- process — управление процессами;
- network — сетевые системные вызовы;
- signal — системные вызовы, что касаются сигналов;
- ipc — системные вызовы IPC ;
- desc — управление дескрипторами файлов;
- memory — работа с памятью программы.
4. ВОЗВРАЩЕНИЕ ОШИБКИ
Можно попросить strace вернуть программе ошибку по нужному системному вызову -e, но с параметром fault. Синтаксис конструкции такой:
fault=имя_вызова:error=тип_ошибки:when=количество
С именем вызова всё понятно, тип ошибки, номер ошибки, которую надо вернуть. А с количеством всё немного сложнее. Есть три варианта:
- цифра — вернуть ошибку только после указанного количества запросов;
- цифра+ — вернуть ошибку после указанного количества запросов и для всех последующих;
- цифра+шаг — вернуть ошибку для указанного количества и для последующих с указанным шагом.
Например, сообщим uname, что системного вызова uname не существует:
sudo strace -e fault=uname uname
В выводе видим, что система вернула программе нашу ошибку, а потом та с помощью вызова write говорит пользователю, что узнать версию и называние системы невозможно.
5. ФИЛЬТРАЦИЯ ПО ПУТИ
Если вас интересует не определённый вызов, а все операции с нужным файлом, то можно выполнить фильтрацию по нему с помощью опции -P. Например, меня интересует, действительно ли утилита lscpu обращается к файлу /proc/cpuinfo, чтобы узнать информацию о процессоре:
strace -P /proc/cpuinfo lscpu
И в результате мы видим, что действительно обращается. Она открывает его для чтения с помощью вызова openat.
6. СТАТИСТИКА СИСТЕМНЫХ ВЫЗОВОВ
С помощью опции -с вы можете собрать статистику для системных вызовов, которые использует программа. Например, сделаем это для nautilus:
Во время работы утилита ничего выводить не будет. Результат будет рассчитан и выведен, когда вы завершите отладку. В выводе будут такие колонки:
- time — процент времени от общего времени выполнения системных вызовов;
- seconds — общее количество секунд, затраченное на выполнение системных вызовов этого типа;
- calls — количество обращений к вызову;
- errors — количество ошибок;
- syscall — имя системного вызова.
Если вы хотите получать эту информацию в режиме реального времени, используйте опцию -C.
7. ОТСЛЕЖИВАНИЕ ВРЕМЕНИ ВЫПОЛНЕНИЯ
Чтобы отображать время выполнения каждого системного вызова, используйте опцию —t:
Можно также отображать микросекунды:
Или отображать время в формате UNIX :
Чтобы добавить время выполнения вызова, добавьте —T:
Для примера возьмем простую программу на С, которая выводит содержимое указанного файла:
[codesyntax lang=»php» blockstate=»collapsed»]
Write strace output to a file
I’m trying to write the output of strace ls to a file. I know that I need to use > in order to forward output of a command to a file, but it doesn’t work. It creates a file but the command prints the output of strace ls to stdout but writes the file name into the file.
$ strace ls > ls_sys.txt . strace output . $ cat ls_sys.txt ls_sys.txt
Related: piping strace to grep however it will likely be simpler to use the strace -o option rather than shell redirection
2 Answers 2
By default strace outputs to stderr. By simply typing man strace , you will have the full documentation of strace . In the manual page, it states that the -o option can be used to output it to a file instead of stderr. You can type man [insert command here] for the vast majority of programs, and have all the documentation you will need to effectively use them.
By default strace outputs to stderr, which is not accessible via grep or file redirection . Good to know! And I looked at the manual page of strace but I didn’t see the -o option, my fault. Thanks!
no problem, I actually just figured out this strace option myself yesterday. When you are in a man page, you can press / and it will bring a dialog that you can search. In my case, I simply searched for output and found the part of the man page I was looking for.
What on Earth makes you think that you cannot redirect standard error or arrange for it to be sent through a pipe to grep ?