Утилита 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
слабо поддерживается.