Tracing processes in linux

Debugging Tip: Trace the Process and See What It is Doing with strace

strace is a useful diagnostic, instructional, and debugging tool. It can save lots of headache. 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. This is also useful to submit bug reports to open source developers.

Each line in the trace contains the system call name, followed by its arguments in parentheses and its return value.

Run strace against /bin/foo and capture its output to a text file in output.txt:
$ strace -o output.txt /bin/foo
You can strace the webserver process and see what it’s doing. For example, strace php5 fastcgi process, enter:
$ strace -p 22254 -s 80 -o /tmp/debug.lighttpd.txt
To see only a trace of the open, read system calls, enter :
$ strace -e trace=open,read -p 22254 -s 80 -o debug.webserver.txt
Where,

  • No ads and tracking
  • In-depth guides for developers and sysadmins at Opensourceflare✨
  • Join my Patreon to support independent content creators and start reading latest guides:
    • How to set up Redis sentinel cluster on Ubuntu or Debian Linux
    • How To Set Up SSH Keys With YubiKey as two-factor authentication (U2F/FIDO2)
    • How to set up Mariadb Galera cluster on Ubuntu or Debian Linux
    • A podman tutorial for beginners – part I (run Linux containers without Docker and in daemonless mode)
    • How to protect Linux against rogue USB devices using USBGuard

Join Patreon

  • -o filename : Write the trace output to the file filename rather than to screen (stderr).
  • -p PID : Attach to the process with the process ID pid and begin tracing. The trace may be terminated at any time by a keyboard interrupt signal (hit CTRL-C). strace will respond by detaching itself from the traced process(es) leaving it (them) to continue running. Multiple -p options can be used to attach to up to 32 processes in addition to command (which is optional if at least one -p option is given).
  • -s SIZE : Specify the maximum string size to print (the default is 32).

Refer to strace man page for more information:
$ man strace

Источник

10 Strace Commands for Troubleshooting and Debugging Linux Processes

strace is a powerful command line tool for debugging and trouble shooting programs in Unix-like operating systems such as Linux. It captures and records all system calls made by a process and the signals received by the process.

It displays the name of each system call together with its arguments enclosed in a parenthesis and its return value to standard error; you can optionally redirect it to a file as well.

In this article, we will explain 10 strace command examples for troubleshooting and debugging programs and processes in a Linux system.

How to Install Strace Process Monitoring Tool in Linux

If strace is not pre-installed on your Linux system, run the appropriate command below for your distribution, to install it.

In case a program crashes or behaves in a way not expected, you can go through its systems calls to get a clue of what exactly happened during its execution. As we will see later on, system calls can be categorized under different events: those relating to process management, those that take a file as an argument, those that involve networking, memory mapping, signals, IPC and also file descriptor related system calls.

You can either run a program/command with strace or pass a PID to it using the -p option as in the following examples.

Читайте также:  Линукс для съемных носителей

1. Trace Linux Command System Calls

You can simply run a command with strace like this, here we are tracing of all system calls made by the df command.

>P\t». 832) = 832 fstat(3, ) = 0 mmap(NULL, 3971488, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7f82f7310000 .

From the output above, you can see various types of system calls made by df command, for example.

  • open – is the type of system call
  • (“/etc/ld.so.cache”, O_RDONLY|O_CLOEXEC) – system call argument
  • 3 – system call return value

Below is an sample output showing the write system calls, that displays df command output on the screen.

2. Trace Linux Process PID

If a process is already running, you can trace it by simply passing its PID as follows; this will fill your screen with continues output that shows system calls being made by the process, to end it, press [Ctrl + C] .

%», 4096>], msg_controllen=0, msg_flags=0>, 0) = 32 recvmsg(4, 0x7ffee4dbf870, 0) = -1 EAGAIN (Resource temporarily unavailable) recvmsg(4, 0x7ffee4dbf850, 0) = -1 EAGAIN (Resource temporarily unavailable) poll([, , , , , ], 6, -1) = 1 ([]) read(31, «2», 1) = 1 recvmsg(4, 0x7ffee4dbf850, 0) = -1 EAGAIN (Resource temporarily unavailable) poll([, , , , , ], 6, 0) = 1 ([]) read(31, «2», 1) = 1 recvmsg(4, 0x7ffee4dbf850, 0) = -1 EAGAIN (Resource temporarily unavailable) poll([, , , , , ], 6, 0) = 0 (Timeout) mprotect(0x207faa20000, 8192, PROT_READ|PROT_WRITE) = 0 mprotect(0x207faa20000, 8192, PROT_READ|PROT_EXEC) = 0 mprotect(0x207faa21000, 4096, PROT_READ|PROT_WRITE) = 0 mprotect(0x207faa21000, 4096, PROT_READ|PROT_EXEC) = 0 .

3. Get Summary of Linux Process

Using the -c flag, you can generate a report of total time, calls, and errors for each system call, as follows.

4. Print Instruction Pointer During System Call

The -i option displays the instruction pointer at the time of each system call made by the program.

>P\t». 832) = 832 [00007faf9cafb2b4] fstat(3, ) = 0 [00007faf9cafb47a] mmap(NULL, 3971488, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7faf9c716000 [00007faf9cafb517] mprotect(0x7faf9c8d6000, 2097152, PROT_NONE) = 0 .

5. Show Time of Day For Each Trace Output Line

You can also print the time of day for each line in the trace output, by passing the -t flag.

>P\t». 832) = 832 15:19:25 fstat(3, ) = 0 15:19:25 mmap(NULL, 3971488, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7f8c7ebec000 15:19:25 mprotect(0x7f8c7edac000, 2097152, PROT_NONE) = 0 .

6. Print Command Time Spent in System Calls

To shows the time difference between the starting and the end of each system call made by a program, use the -T option.

7. Trace Only Specific System Calls

In the command below, trace=write is known as a qualifying expression, where trace is a qualifier (others include signal, abbrev, verbose, raw, read, or write). Here, write is the value of the qualifier.

The following command actually shows the system calls to print df output on standard output.

Here are some additional commands about trace qualifier.

8. Trace System Calls Based on a Certain Condition

Let’s look at how to trace system calls relating to a given class of events. This command can be used to trace all system calls involving process management.

Next, to trace all system calls that take a filename as an argument, run this command.

To trace all system calls involving memory mapping, type.

You can trace all network and signals related system calls.

9. Redirect Trace Output to File

To write the trace messages sent to standard error to a file, use the -o option. This means that only the command output is printed on the screen as shown below.

To look through the file, use cat command.

10. Show Some Debugging Output of Strace

To show debugging information for strace tool, use the -d flag.

For additional information, see the strace man page.

Also read these useful related articles:

In conclusion, strace is a remarkable tool for diagnosing cause(s) of program failure: it is a powerful debugging and trouble shooting. It is practically useful to experienced system administrators, programmers and hackers. To share any thoughts concerning this article, use the feedback form below.

If You Appreciate What We Do Here On TecMint, You Should Consider:

TecMint is the fastest growing and most trusted community site for any kind of Linux Articles, Guides and Books on the web. Millions of people visit TecMint! to search or browse the thousands of published articles available FREELY to all.

If you like what you are reading, please consider buying us a coffee ( or 2 ) as a token of appreciation.

We are thankful for your never ending support.

Источник

Strace в Linux: история, устройство и использование

В Unix-подобных операционных системах общение программы с внешним миром и операционной системой происходит через небольшой набор функций — системных вызовов. А значит, в отладочных целях полезно бывает подсмотреть за выполняемыми процессами системными вызовами.

Читайте также:  Почему не обновляется mac os high sierra

Следить за «интимной жизнью» программ на 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 мы получим:

Так, согласитесь, намного проще читается.

А ещё можно убирать системные вызовы — например, связанные с выделением и освобождением памяти:

Читайте также:  Linux путь до приложения

Обратите внимание на экранированный восклицательный знак в списке исключённых вызовов: этого требует командная оболочка (англ. 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 и не стесняйтесь подглядывать за вашими программами!

Источник

Оцените статью