- strace
- Some of the features
- Attach to an already running process.
- Print paths and more info associated with file descriptors.
- Filter by type of syscall.
- Trace only system calls accessing given path.
- Perform a full hexadecimal and ASCII dump of all the data read from/written to file descriptors.
- Perform a syscall fault injection.
- Count time, calls, and errors for each system call.
- strace
- Some of the features
- Attach to an already running process.
- Print paths and more info associated with file descriptors.
- Filter by type of syscall.
- Trace only system calls accessing given path.
- Perform a full hexadecimal and ASCII dump of all the data read from/written to file descriptors.
- Perform a syscall fault injection.
- Count time, calls, and errors for each system call.
- Strace в Linux: история, устройство и использование
- Содержание
- Происхождение видов
- Устройство strace в двух словах: Piglet Trace
- Азы: запуск программы под управлением strace
- Азы: присоединение к процессу на лету
- Пример: отслеживание дочерних процессов
- Пример: пути к файлам вместо дескрипторов
- Пример: отслеживание обращений к файлам
- Пример: многопоточные программы
- Мастер-класс: стек процесса в момент системного вызова
- Мастер-класс: инъекция ошибок
- Послесловие
strace
linux syscall tracer
- Official repositories are at GitHub and GitLab.
- You can get latest binary packages from Fedora rawhide, OBS, Sisyphus.
- The latest officially signed release tarball can be found here.
- Development takes place on the mailing list (archive). Everyone is welcome to send bug reports, feature requests, comments and patches there.
- IRC channel: #strace@oftc.
- strace is released under the GNU Lesser General Public License license version 2.1 or later. strace mascot is CC BY-SA 4.0, by Vitaly Chaykovsky.
strace is a diagnostic, debugging and instructional userspace utility for Linux. It is used to monitor and tamper with interactions between processes and the Linux kernel, which include system calls, signal deliveries, and changes of process state.
System administrators, diagnosticians and trouble-shooters will find it invaluable for solving problems with programs for which the source is not readily available since they do not need to be recompiled in order to trace them.
The operation of strace is made possible by the kernel feature known as ptrace.
Some of the features
Attach to an already running process.
Print paths and more info associated with file descriptors.
Filter by type of syscall.
Trace only system calls accessing given path.
Perform a full hexadecimal and ASCII dump of all the data read from/written to file descriptors.
Perform a syscall fault injection.
Count time, calls, and errors for each system call.
Based on a Github Pages theme — minimal
Источник
strace
linux syscall tracer
- Official repositories are at GitHub and GitLab.
- You can get latest binary packages from Fedora rawhide, OBS, Sisyphus.
- The latest officially signed release tarball can be found here.
- Development takes place on the mailing list (archive). Everyone is welcome to send bug reports, feature requests, comments and patches there.
- IRC channel: #strace@oftc.
- strace is released under the GNU Lesser General Public License license version 2.1 or later. strace mascot is CC BY-SA 4.0, by Vitaly Chaykovsky.
strace is a diagnostic, debugging and instructional userspace utility for Linux. It is used to monitor and tamper with interactions between processes and the Linux kernel, which include system calls, signal deliveries, and changes of process state.
System administrators, diagnosticians and trouble-shooters will find it invaluable for solving problems with programs for which the source is not readily available since they do not need to be recompiled in order to trace them.
The operation of strace is made possible by the kernel feature known as ptrace.
Some of the features
Attach to an already running process.
Print paths and more info associated with file descriptors.
Filter by type of syscall.
Trace only system calls accessing given path.
Perform a full hexadecimal and ASCII dump of all the data read from/written to file descriptors.
Perform a syscall fault injection.
Count time, calls, and errors for each system call.
Based on a Github Pages theme — minimal
Источник
Strace в Linux: история, устройство и использование
В Unix-подобных операционных системах общение программы с внешним миром и операционной системой происходит через небольшой набор функций — системных вызовов. А значит, в отладочных целях полезно бывает подсмотреть за выполняемыми процессами системными вызовами.
Следить за «интимной жизнью» программ на Linux помогает утилита strace , которой и посвящена эта статья. К примерам использования «шпионского» оборудования прилагаются краткая история strace и описание устройства подобных программ.
Содержание
Происхождение видов
Главный интерфейс между программами и ядром OC в Unix — системные вызовы (англ. system calls, syscalls), взаимодействие программ с внешним миром происходит исключительно через них.
Но в первой публичной версии Unix (Version 6 Unix, 1975 год) удобных способов отслеживания поведения пользовательских процессов не было. Для решения этой проблемы Bell Labs к следующей версии (Version 7 Unix, 1979 год) предложили новый системный вызов — ptrace .
Разрабатывался ptrace прежде всего для интерактивных отладчиков, но к концу 80-х (в эпоху коммерческого уже System V Release 4) на этой основе появились и получили широчайшее распространение узконаправленные отладчики — трассировщики системных вызовов.
Первая же версия strace была опубликована Полом Кроненбургом в рассылке comp.sources.sun в 1992 году в качестве альтернативы закрытой утилите trace от Sun. Как клон, так и оригинал предназначались для SunOS, но к 1994 году strace была портирована на System V, Solaris и набирающий популярность Linux.
Сегодня strace поддерживает только Linux и опирается на всё тот же ptrace , обросший множеством расширений.
Современный (и весьма активный) мейнтейнер strace — Дмитрий Левин. Благодаря ему утилита обзавелась продвинутыми возможностями вроде инъекции ошибок в системные вызовы, поддержкой широкого спектра архитектур и, главное, маскотом. Неофициальные источники утверждают, что выбор пал на страуса из-за созвучности русского слова «страус» и английского «strace».
Немаловажно и то, что системный вызов ptrace и трассировщики так и не были включены в POSIX, несмотря на долгую историю и наличие реализации в Linux, FreeBSD, OpenBSD и традиционных Unix.
Устройство strace в двух словах: Piglet Trace
«You are not expected to understand this» (Деннис Ричи, комментарий в исходном коде Version 6 Unix)
С раннего детства я терпеть не могу чёрные ящики: с игрушками я не играл, а пытался разобраться в их устройстве (взрослые употребляли слово «ломал», но не верьте злым языкам). Возможно, поэтому мне так близки неформальная культура первых Unix и современного open-source-движения.
В рамках этой статьи разбирать исходный код раздобревшей за десятилетия strace неразумно. Но и тайн для читателей оставаться не должно. Поэтому, чтобы показать принцип работы подобных strace программ, я приведу код миниатюрного трассировщика — Piglet Trace (ptr). Ничего особенного он делать не умеет, но главное — системные вызовы программы — выводит:
Piglet Trace распознает порядка сотни системных вызовов Linux (см. таблицу) и работает только на архитектуре x86-64. Для учебных целей этого достаточно.
Давайте разберём работу нашего клона. В случае с Linux для отладчиков и трассировщиков используется, как упоминалось выше, системный вызов ptrace. Он работает посредством передачи в первом аргументе идентификаторов команд, из которых нам нужны только PTRACE_TRACEME , PTRACE_SYSCALL и PTRACE_GETREGS .
Работа трассировщика начинается в обычном Unix-стиле: fork(2) запускает дочерний процесс, а тот в свою очередь с помощью exec(3) запускает исследуемую программу. Единственная тонкость здесь — вызов ptrace(PTRACE_TRACEME) перед exec : процесс-потомок ожидает, что процесс-родитель будет его отслеживать:
Процесс-родитель теперь должен вызвать wait(2) в дочернем процессе, то есть убедиться, что переключение в режим трассировки произошло:
На этом приготовления закончены и можно приступать непосредственно к отслеживанию системных вызовов в бесконечном цикле.
Вызов ptrace(PTRACE_SYSCALL) гарантирует, что последующий wait родителя завершится либо перед исполнением системного вызова, либо сразу после его завершения. Между двумя вызовами можно осуществить какие-либо действия: заменить вызов на альтернативный, изменить аргументы или возвращаемое значение.
Нам же достаточно дважды вызвать команду ptrace(PTRACE_GETREGS) , чтобы получить состояние регистра rax до вызова (номер системного вызова) и сразу после (возвращаемое значение).
Вот и весь трассировщик. Теперь вы знаете, с чего начинать очередное портирование DTrace на Linux.
Азы: запуск программы под управлением strace
В качестве первого примера использования strace , пожалуй, стоит привести самый простой способ — запуск приложения под управлением strace .
Чтобы не копаться в бесконечном списке вызовов типичной программы, напишем минимальную программу вокруг write :
Соберем программу и убедимся, что она работает:
И наконец запустим ее под управлением strace:
Очень «многословно» и не очень познавательно. Проблемы здесь две: вывод программы смешан с выводом strace и изобилие системных вызовов, которые нас не интересуют.
Разделить стандартный поток вывода программы и вывод ошибок strace можно при помощи ключа -o, перенаправляющего список системных вызовов в файл-аргумент.
Осталось разобраться с проблемой «лишних» вызовов. Предположим, что нас интересуют только вызовы write . Ключ -e позволяет указывать выражения, по которым будут фильтроваться системные вызовы. Самый популярный вариант условия — естественно, trace=* , при помощи которого можно оставить только интересующие нас вызовы.
При одновременном использовании -o и -e мы получим:
Так, согласитесь, намного проще читается.
А ещё можно убирать системные вызовы — например, связанные с выделением и освобождением памяти:
Обратите внимание на экранированный восклицательный знак в списке исключённых вызовов: этого требует командная оболочка (англ. shell).
В моей версии glibc завершает исполнение процесса системный вызов exit_group , а не традиционный _exit . В этом состоит сложность работы с системными вызовами: интерфейс, с которым работает программист, не имеет прямого отношения к системным вызовам. Более того, он регулярно меняется в зависимости от реализации и платформы.
Азы: присоединение к процессу на лету
Изначально системный вызов ptrace, на котором построена strace , можно было использовать только при запуске программы в специальном режиме. Такое ограничение, быть может, звучало разумно во времена Version 6 Unix. В наши же дни этого уже недостаточно: бывает, нужно исследовать проблемы работающей программы. Типичный пример — заблокированный на дескрипторе или спящий процесс. Поэтому современная strace умеет присоединяться к процессам на лету.
Соберём программу и убедимся в том, что она зависла:
А теперь попробуем присоединиться к ней:
Программа заблокирована вызовом pause . Посмотрим, как она отреагирует на сигналы:
Мы запустили зависнувшую программу и присоединились к ней при помощи strace . Выяснились две вещи: системный вызов pause игнорирует сигналы без обработчиков и, что интереснее, strace отслеживает не только системные вызовы, но и входящие сигналы.
Пример: отслеживание дочерних процессов
Работа с процессами через вызов fork — основа всех Unix. Давайте посмотрим, как strace работает с деревом процессов на примере несложной «плодящейся» программы:
Здесь исходный процесс создаёт дочерний процесс, оба пишут в стандартный поток вывода:
По умолчанию мы увидим только системные вызовы родительского процесса:
Отслеживать дерево процессов целиком помогает флаг -f , с которым strace отслеживает системные вызовы в процессах-потомках. К каждой строке вывода при этом добавляется pid процесса, делающего системный вывод:
В этом контексте может пригодиться фильтрация по группам системных вызовов:
Кстати, какой системный вызов используется для создания нового процесса?
Пример: пути к файлам вместо дескрипторов
Знать файловые дескрипторы, безусловно, полезно, но имена конкретных файлов, к которым обращается программа, тоже могут пригодиться.
Следующая программа пишет строку во временный файл:
При обычном вызове strace покажет значение числа-дескриптора, переданного в системный вызов:
С флагом -y утилита показывает путь к файлу, которому соответствует дескриптор:
Пример: отслеживание обращений к файлам
Ещё одна полезная возможность: отображать только системные вызовы, связанные с конкретным файлом. Следующая программа дописывает строку в произвольный файл, переданный в аргументе:
По умолчанию strace выводит много лишней информации. Флаг -P с аргументом заставляет strace выводить только обращения к указанному файлу:
Пример: многопоточные программы
Утилита strace может помочь и при работе с многопоточной программой. Следующая программа пишет в стандартный поток вывода из двух потоков:
Собирать её надо, естественно, со специальным приветом линковщику — флагом -pthread:
Флаг -f , как и в случае с обычными процессами, добавит в начало каждой строки pid процесса.
Естественно, речь идёт не об идентификаторе потока в смысле реализации стандарта POSIX Threads, а о номере, используемом планировщиком задач в Linux. С точки зрения последнего нет никаких процессов и потоков — есть задачи, которые надо распределить по доступным ядрам машины.
При работе в несколько потоков системных вызовов становится слишком много:
Имеет смысл ограничиться только управлением процессами и системным вызовом write :
Кстати, вопросы. Какой системный вызов используется для создания нового потока? Чем такой вызов для потоков отличается от вызова для процессов?
Мастер-класс: стек процесса в момент системного вызова
Одна из недавно появившихся в strace возможностей — отображение стека вызовов функций в момент системного вызова. Простой пример:
Естественно, вывод программы при этом становится очень объёмным, и, помимо флага -k (отображение стека вызовов), имеет смысл фильтровать системные вызовы по имени:
Мастер-класс: инъекция ошибок
И ещё одна новая и очень полезная возможность: инъекция ошибок. Вот программа, пишущая две строки в поток вывода:
Отслеживаем оба вызова write:
А теперь используем выражение inject , чтобы вставить ошибку EBADF во все вызовы write:
Интересно, что ошибки возвращают все вызовы write , включая вызов, скрытый за perror. Имеет смысл возвращать ошибку только для первого из вызовов:
Тип ошибки указывать не обязательно:
В сочетании с другими флагами можно «ломать» обращения к конкретному файлу. Пример:
Помимо инъекций ошибок, можно вводить задержки при выполнении вызовов или получении сигналов.
Послесловие
Утилита strace — простой и надёжный инструмент. Но помимо системных вызовов отлаживать случается и другие аспекты работы программ и операционной системы. Например, отслеживать вызовы динамически линкуемых библиотек умеет ltrace, заглянуть в работу операционной системы могут SystemTap и ftrace, а глубоко исследовать производительность программ позволяет perf. Тем не менее именно strace — первая линия обороны в случае проблем с собственными и чужими программами, и использую я её минимум пару раз в неделю.
Словом, любите Unix, читайте man 1 strace и не стесняйтесь подглядывать за вашими программами!
Источник