С чего начать Первые шаги трек · 15 ступеней
Linux Labs

strace — какие системные вызовы делает процесс

7 мин strace 6.8 · Ubuntu 24.04

strace показывает системные вызовы программы и их результат: какой файл не открылся, куда не подключилась, на чём висит.

Шпаргалка

8 команд Версия для печати
  • strace cat /etc/hostname все вызовы команды
  • strace -f sh -c '…' и дочерних процессов
  • strace -e trace=openat cmd только openat
  • strace -f -e trace=file cmd всё, что с путями файлов
  • strace -e trace=network cmd сокеты и подключения
  • strace -o /tmp/t.log -f cmd в файл, отдельно от вывода
  • strace -c ls /etc > /dev/null сводка: сколько каких вызовов
  • sudo timeout 10 strace -p 1234 подключиться к процессу

Обзор

Программа сама ничего не открывает и не отправляет: она просит ядро. Каждая такая просьба — системный вызов: openat открывает файл, read и write читают и пишут, connect подключается, exit_group завершает процесс. strace запускает программу и печатает каждый вызов с аргументами и результатом — в поток ошибок, чтобы не мешать выводу программы.

text
student@ubuntu:~$ strace -e trace=openat,read,write cat /etc/hostname
…
openat(AT_FDCWD, "/etc/hostname", O_RDONLY) = 3
read(3, "ubuntu\n", 131072)             = 7
write(1, "ubuntu\n", 7ubuntu
)                 = 7
read(3, "", 131072)                     = 0
+++ exited with 0 +++

Как читать строку

имя(аргументы) = результат. openat(…, "/etc/hostname", O_RDONLY) = 3 — файл открыт и получил дескриптор 3; дальше read(3, …) читает именно его. write(1, …) пишет в стандартный вывод — поэтому ubuntu вклинился в строку strace. Последняя строка — +++ exited with 0 +++, код завершения.

Отказ — результат -1 и имя ошибки:

text
openat(AT_FDCWD, "/nope", O_RDONLY)     = -1 ENOENT (No such file or …
openat(AT_FDCWD, "/etc/shadow", O_RDONLY) = -1 EACCES (Permission …
Ошибка Что значит
ENOENT нет такого файла или каталога
EACCES нет прав
ECONNREFUSED на этом порту никто не слушает
EMFILE кончился лимит открытых файлов (см. ulimit)
EAGAIN ресурс занят, попробуй позже

Не каждый ENOENT — беда. Программа ищет файлы в нескольких местах по очереди: sh перебрал /usr/local/sbin/ls, /usr/local/bin/ls, /usr/sbin/ls, прежде чем нашёл /usr/bin/ls. Важен отказ, после которого программа сдалась — обычно он ближе к концу.

Дочерние процессы: -f

Без -f strace видит только сам запущенный процесс. Оболочка, служба, скрипт делают работу в потомках — с -f их вызовы видны, у каждой строки — PID:

text
student@ubuntu:~$ strace -f -e trace=file sh -c 'cat /etc/shadow'
…
[pid  1060] openat(AT_FDCWD, "/etc/shadow", O_RDONLY) = -1 EACCES (…
cat: /etc/shadow: Permission denied

Отбор вызовов: -e trace=

Полный вывод — сотни строк. -e trace= оставляет нужные:

Отбор Что останется
-e trace=openat только openat
-e trace=openat,read,write перечисленные
-e trace=file всё, где есть путь к файлу: openat, statx, execve, access
-e trace=network socket, connect, sendto, recvfrom
-e trace=process запуск и завершение процессов

Подключиться к процессу: -p

strace -p <PID> подключается к работающему процессу и печатает его вызовы с этого момента. В Ubuntu kernel.yama.ptrace_scope = 1: без root можно трассировать только своих потомков. К уже работающему процессу — даже своему — нужен sudo:

text
student@ubuntu:~$ strace -p 1081
strace: attach: ptrace(PTRACE_SEIZE, 1081): Operation not permitted

Процесс, который ждёт, показывает незаконченный вызов — без = и результата. Здесь flock ждёт блокировку, которую держит другой процесс:

text
student@ubuntu:~$ sudo timeout 3 strace -p 1112
strace: Process 1112 attached
flock(3, LOCK_EXstrace: Process 1112 detached
 <detached ...>

timeout 3 отцепляет strace через 3 секунды (код 124); процесс продолжает работу как ни в чём не бывало. Ctrl+C делает то же.

Ключи

9

Основные ключи — в таблице ниже. Полный список — man strace.

Ключ Что делает Пример
-f Следовать за дочерними процессами и потоками. strace -f cmd
-p PID Подключиться к уже работающему процессу по PID. sudo strace -p 1234
-e trace=... Фильтр по группе вызовов — file, network, openat,read и другие. strace -e trace=network cmd
-c Сводка-профиль — какие вызовы и сколько времени они заняли. strace -c cmd
-T Показать время, потраченное на каждый вызов. strace -T -e trace=openat cmd
-y Показывать пути и адреса вместо номеров файловых дескрипторов. strace -y -p 1234
-s N Длина показываемых строк в выводе (по умолчанию 32 — часто мало). strace -s 200 -e trace=write -p 1234
-o FILE Записать вывод в файл вместо терминала. strace -o trace.log -f cmd
-tt Таймстамп с микросекундами перед каждой строкой. strace -tt -o trace.log cmd

Ничего не найдено. Попробуй запрос короче.

Рецепты

6

Программа молча завершается с кодом 1

bash
strace -f -o /tmp/t.log ./app; echo $?
grep -E '= -1 E' /tmp/t.log | tail

-o пишет трассу в файл, вывод программы остаётся на экране. Последние отказы перед exited with 1 и есть причина: файл не найден, нет прав, порт не открылся.

Запускай от пользователя службы

root читает любой файл, и под sudo strace отказа в правах не видно. Служба работает от своего пользователя — от него и трассируй:

bash
sudo strace -e trace=openat cat /etc/app.conf
sudo -u appsvc strace -e trace=openat cat /etc/app.conf
text
openat(AT_FDCWD, "/etc/app.conf", O_RDONLY) = 3
…
openat(AT_FDCWD, "/etc/app.conf", O_RDONLY) = -1 EACCES (Permission …
cat: /etc/app.conf: Permission denied

Пользователя службы покажет systemctl show -p User <служба>.

Какие файлы читает программа

bash
strace -f -e trace=openat -o /tmp/t.log cmd
grep -v ENOENT /tmp/t.log | grep -o '"[^"]*"' | sort -u

Куда подключается

text
student@ubuntu:~$ strace -e trace=network curl -s -m 2 127.0.0.1:9
…
socket(AF_INET, SOCK_STREAM, IPPROTO_TCP) = 5
connect(5, {sa_family=AF_INET, sin_port=htons(9), sin_addr=inet_addr(…

Адрес и порт — в аргументах connect.

На чём висит процесс

bash
sudo timeout 5 strace -p 1112

Одна незаконченная строка — процесс ждёт в этом вызове: flock — блокировку файла (кто её держит — lsof и /proc/locks, см. proc-filesystem), read — данных, connect — ответа сети. Процесс в состоянии D ждёт ядро внутри вызова, и strace может ничего не напечатать, пока ожидание не кончится (см. load-average).

Сводка: какие вызовы и сколько

text
student@ubuntu:~$ strace -c ls /etc > /dev/null
% time     seconds  usecs/call     calls    errors syscall
------ ----------- ----------- --------- --------- ----------------
 22.41    0.000221         221         1           execve
 18.86    0.000186           5        34        12 openat
…
100.00    0.000986           6       150        18 total

calls — сколько раз, errors — сколько с отказом, % time — доля времени в ядре.

Неполадки

4

attach: ptrace(PTRACE_SEIZE, …): Operation not permitted

ptrace_scope = 1 не даёт подключиться к процессу, который не твой потомок. Запусти sudo strace -p <PID>. К PID 1 и чужим процессам без sudo тоже нельзя.

Вывод программы перемешан со strace

Оба пишут в терминал. -o файл уводит трассу в файл.

Строки обрезаны: "hello-wo"...

strace показывает 32 символа строки, остальное — .... -s 200 показывает 200.

Вызовов потомков нет

Работу делает дочерний процесс, а strace без -f его не видит.

Термины

1
системный вызов (system call)
Просьба программы к ядру: открыть файл (openat), прочитать (read), записать (write), подключиться (connect), завершиться (exit_group). strace печатает каждый вызов с результатом; отказ — -1 и имя ошибки. Ещё встречается в: Load average: сколько задач ждёт процессор и диск

См. также

  • proc-filesystem — fd, status, limits процесса в /proc.
  • lsof — открытые файлы и блокировки.
  • exit-codes — код в строке exited with.
  • ulimit — EMFILE и лимит открытых файлов.
  • processes — PID, потомки, состояния.
  • load-average — процесс в D.
Загрузка…