Утилита strace
Утилита strace отслеживает системные вызовы и сигналы.
strace – инструмент диагностики, обучения и отладки.
Он очень полезен для решения проблем с программами, для которых источник недоступен,
поскольку их не нужно перекомпилировать для отслеживания.
Поскольку системные вызовы и сигналы являются событиями, которые происходят в интерфейсе пользователя/ядра, тщательное изучение этой границы очень полезно для изоляции ошибок, проверки работоспособности и попыток получения условий гонки.
- Установка утилиты
- Синопсис команды
- Особенности работы strace и обозначения в трассировке стека
- Диагностика
- Установка Setuid
- Замечания о работе strace
- Известные недостатки
Установка утилиты
Для установки утилиты на устройство следует выполнить следующее:
-
Подключиться к устройству по ssh. По умолчанию имя пользователя
defaultuser.ssh defaultuser@<device_ip> -
Убедиться, что интернет и репозитории доступны:
ssu domainПример успешного вывода:
Device domain is currently: salesЕсли домен не указан, следует его настроить. Если вывод успешен, можно переходить к следующему пункту.
-
Найти пакет
strace:pkcon search straceВ списке доступных пакетов должен появиться
strace. -
Установить пакет
strace:devel-su pkcon install strace
Синопсис команды
strace [-ACdffhikqrtttTvVxxy] [-ACdffhiqrtttTvVxxy] [-I n]
[-b execve] [-e expr]... [-a column] [-o file] [-s strsize]
[-X format] [-P path]... [-p pid]... { -p pid | [-D]
[-E var[=val]]... [-u username] command [args] }
strace -c [-df] [-I n] [-b execve] [-e expr]... [-O overhead]
[-S sortby] [-P path]... [-p pid]... { -p pid | [-D]
[-E var[=val]]... [-u username] command [args] }
В простейшем случае strace запускает указанную команду и работает до её завершения.
Она перехватывает и записывает системные вызовы, вызываемые процессом, и сигналы,
принимаемые процессом.
Имя каждого системного вызова, его аргументы и возвращаемое значение выводятся по стандартному пути
вывода ошибок или в файл, указанный с помощью опции -o.
strace без аргументов записывает все сообщения трассировки событий STREAMS от всех драйверов
и модулей в свой стандартный вывод.
Эти сообщения получены из драйвера журнала STREAMS.
Если аргументы предоставлены, они должны быть в триплетах в форме mid, sid, level,
где mid – это идентификационный номер модуля STREAMS, sid – это номер sub-ID,
а level – уровень приоритета трассировки.
Каждый триплет указывает, что сообщения трассировки должны быть получены от данного
модуля/драйвера, идентификатора подчинённого (обычно указывающего на вспомогательное устройство)
и уровня приоритета, равного или меньшего, чем данный уровень.
Маркер all может использоваться для любого члена, чтобы указать отсутствие ограничений для этого атрибута.
Формат каждого вывода сообщения трассировки:
<seq> <time> <ticks> <level> <flags> <mid> <sid> <text>
<seq>– порядковый номер трассировки;<time>– время сообщения в hh:mm:ss;<ticks>– время сообщения в машинных тиках с момента загрузки;<level>– уровень приоритета трассировки;<flags>– E: сообщение также находится в журнале ошибок, F: указывает на фатальную ошибку, N: письмо было отправлено системному администратору (жестко закодировано как root);<mid>– идентификационный номер модуля источника;<sid>– субидентификационный номер источникаsub-ID;<text>– форматированный текст сообщения трассировки.
После запуска strace продолжит выполнение до тех пор, пока пользователь не прекратит работу.
Примеры
В следующем примере выводятся все сообщения трассировки от модуля или драйвера с идентификатором
модуля 41:
strace 41 all all
В следующем примере выводятся сообщения трассировки для драйвера или модуля с идентификатором 41
и субидентификаторами 0, 1 или 2:
strace 41 0 1 41 1 1 41 2 0
Сообщения для субидентификаторов 0 и 1 должны иметь уровень трассировки меньше или равный 1.
Сообщения для субидентификатора 2 должны иметь уровень трассировки 0.
Особенности работы strace и обозначения в трассировке стека
Каждая строка в трассировке содержит имя системного вызова, сопровождаемое его аргументами в скобках и его возвращаемым значением.
Пример использования команды cat /dev/null:
open("/dev/null", O_RDONLY) = 3
К ошибкам (обычно возвращаемое значение -1) добавляются символ ошибки и строка ошибки.
open("/foo/bar", O_RDONLY) = -1 ENOENT (No such file or directory)
Сигналы печатаются как символ сигнала и декодированная структура siginfo.
Выдержка из прерывания команды sleep 666:
sigsuspend([] <unfinished ...>
--- SIGINT {si_signo=SIGINT, si_code=SI_USER, si_pid=...} ---
+++ killed by SIGINT +++
Если выполняется системный вызов, в то время как другой вызов вызывается из другого
потока/процесса, то strace попытается сохранить порядок этих событий и пометить текущий вызов
как незавершённый.
Когда вызов вернется, он будет помечен как возобновлённый.
Прерывание (перезапускаемого) системного вызова доставкой сигнала обрабатывается по-разному, поскольку ядро завершает системный вызов и также организует его немедленное повторное выполнение после завершения обработчика сигнала.
Аргументы печатаются в символической форме.
В этом примере показана оболочка, выполняющая перенаправление вывода >>xyzzy:
open("xyzzy", O_WRONLY|O_APPEND|O_CREAT, 0666) = 3
Здесь третий аргумент open декодируется путём разбиения аргумента flag на три составляющие
побитового ИЛИ и печати значения режима по традиции в восьмеричном формате.
Иногда традиционное или собственное использование отличается от ANSI или POSIX,
но эти формы предпочтительнее.
В некоторых случаях вывод данных strace оказывается более читабельным, чем исходный.
Указатели на структуру разыменовываются, и элементы соответствующим образом отображаются.
В большинстве случаев аргументы форматируются в максимально возможной степени в стиле C.
Например, сущность команды ls -l /dev/null записывается как:
lstat("/dev/null", {st_mode=S_IFCHR|0666, st_rdev=makedev(1, 3), ...}) = 0
Следует обратить внимание, как разыменовывается аргумент struct stat и как символически
отображается каждый элемент.
В частности, как элемент st_mode тщательно декодируется в побитовое ИЛИ символических
и числовых значений.
Также следует обратить внимание, что в этом примере первый аргумент lstat является входом
для системного вызова, а второй аргумент является выходным.
Поскольку выходные аргументы не изменяются в случае сбоя системного вызова, аргументы не всегда
могут быть разыменованы.
Например, повторная попытка примера ls -l с несуществующим файлом приводит к следующей строке.
lstat("/foo/bar", 0xb004) = -1 ENOENT (No such file or directory)
Основные опции
-D– запускать процесс трассировки как отдельный "внук", а не как родитель трассировки. Это уменьшает видимый эффектstrace, сохраняя трассировку прямым потомком вызывающего процесса.-d– показать некоторые отладочные данные самогоstraceдля стандартной ошибки.-f– отследить дочерние процессы по мере того, как они создаются отслеживаемыми в настоящее время процессами в результате системного вызоваfork(2).-q– подавлять сообщения о присоединении, отсоединении и т. д. Это происходит автоматически, когда вывод перенаправляется в файл и команда запускается непосредственно вместо присоединения.-u username– запустить команду с идентификатором пользователя, идентификатором группы и дополнительными группами имени пользователя. Эта опция полезна только при запуске от имени пользователя root и позволяет правильно выполнять двоичные файлыsetuidиsetgid. Если не используется эта опция, программыsetuidиsetgidвыполняются без действующих привилегий.
Опции выходного формата
-a column– выравнивать возвращаемые значения в определённом столбце (по умолчанию40);-i– распечатать указатель на инструкции во время системного вызова;-k– вывести трассировку стека выполнения отслеживаемых процессов после каждого системного вызова;-o имя_файла– записать вывод трассировки в файл, а не вstderr. Формаfilename.pidиспользуется, если указана опция-ff. Если аргумент начинается с '|' или '!', остальная часть аргумента обрабатывается как команда, и весь вывод передается по ней. Это удобно для передачи результатов отладки в программу без влияния на перенаправление исполняемых программ. Последнее не совместимо с опцией-ffв настоящее время.-A– открыть файл, указанный в опции-o, в режиме добавления;-q– подавлять сообщения о присоединении, отсоединении и т. д. Это происходит автоматически, когда вывод перенаправляется в файл и команда запускается непосредственно вместо присоединения.-qq– подавить сообщения о состоянии завершения процесса;-s strsize– указать максимальный размер строки для печати (по умолчанию32). Следует обратить внимание, что имена файлов не считаются строками и всегда печатаются полностью;-t– префикс каждой строки трассировки со временем настенных часов.
Опции статистики
-c– подсчитывать время, вызовы и ошибки для каждого системного вызова и сообщать сводные данные о выходе из программы, подавляя обычный вывод. Команда пытается показать системное время (процессорное время, потраченное на работу в ядре) независимо от времени настенных часов. Если-cиспользуется с-f, сохраняются только совокупные итоги для всех отслеживаемых процессов.-S sortby– сортировать выходные данные гистограммы, напечатанной параметром-c, по указанному критерию. Допустимые значения:time,calls,nameиnothing(по умолчаниюtime).-w– суммировать разницу во времени между началом и концом каждого системного вызова. По умолчанию суммируется системное время.
Опция фильтрации
-e expr– уточняющее выражение, которое изменяет, какие события отслеживать или как их отслеживать.
Диагностика
При выходе из команды strace выходит с тем же статусом выхода, что и команда.
Если команда завершается сигналом, strace завершает себя тем же сигналом, так что strace может
использоваться как процесс-обёртка, прозрачный для вызывающего родительского процесса.
Следует обратить внимание, что отношения родитель-потомок (уведомления о прекращении сигнала,
значение getppid() и т. д.) между отслеживаемым процессом и его родителем не сохраняются,
если не используется -D.
При использовании -p без команды состояние выхода strace равно нулю, если не было присоединено
ни одного процесса или произошла непредвиденная ошибка при выполнении трассировки.
Установка Setuid
Если для strace установлен setuid как root, то вызывающий пользователь сможет подключаться
и отслеживать процессы, принадлежащие любому пользователю.
Кроме того, программы setuid и setgid будут выполняться и отслеживаться с правильными
действующими привилегиями.
Эти действия могут быть разрешены только тем пользователям, которым доверены полные права
суперпользователя.
Поэтому имеет смысл устанавливать strace в качестве setuid для root, когда пользователи,
которые могут его выполнять, ограничены теми пользователями, которым доверяют.
Например, имеет смысл установить специальную версию strace с режимом rwsr-xr--, root
пользователя и трассировкой группы, где члены группы трассировки являются
доверенными пользователями.
При использовании этой функции рекомендуется установить не setuid-версию strace
для обычных пользователей.
Замечания о работе strace
- Полезно думать о входах и выходах системного вызова как о потоке данных через границу пространств пользователя/ядра. Поскольку пространство пользователя и пространство ядра являются отдельными и защищёнными адресами, иногда можно сделать дедуктивные выводы о поведении процесса, используя входные и выходные данные в качестве предложений.
- В некоторых случаях системный вызов будет отличаться от задокументированного поведения
или иметь другое имя.
Например, в системах, производных от System V, системный вызов
time(2)не принимает аргументов, а функцияstatназываетсяxstatи принимает дополнительный ведущий аргумент. Эти несоответствия являются нормальными, но уникальными характеристиками интерфейса системных вызовов и учитываются функциями оболочки библиотеки C. - На некоторых платформах процесс, к которому применяется системная трассировка вызовов
с параметром
-p, получитSIGSTOP. Этот сигнал может прервать системный вызов, который не может быть перезапущен. Это может оказать непредсказуемое влияние на процесс, если процесс не предпримет никаких действий для перезапуска системного вызова.
Известные недостатки
- Программы, использующие бит
setuid, не имеют действующих привилегий пользователя с заданным идентификаторомIDво время отслеживания. - Отслеживаемый процесс игнорирует
SIGSTOP, за исключением платформSVR4. - Отслеживаемому процессу, который пытается заблокировать
SIGTRAP, будет отправленSIGSTOPв попытке принудительного продолжения трассировки. - Отслеживаемый процесс работает медленно.
- Отслеживаемые процессы, которые произошли от команды, могут остаться запущенными
после сигнала прерывания (
CTRL -C). - В Linux отслеживание процесса инициализации запрещено.
- Опция
-iслабо поддерживается.