Это один из самых частых запросов у админов: strace linux, strace примеры, как присоединиться к процессу. Запрос strace 1319 (это просто пример PID процесса) - классика жанра, когда человек гуглит, как прицепиться к работающему демону. Разберём strace с нуля и доведём до боевого набора опций, чтобы ты после урока мог открыть терминал и сам прочитать вывод. Сразу пометка: на 2026 год strace - всё ещё базовый инструмент, но для горячего прода у него появилась серьёзная замена в лице eBPF, и про это мы тоже поговорим.
Что такое системный вызов и зачем тут strace
Любая программа сама по себе мало что может. Открыть файл, прочитать байты, отправить пакет в сеть, выделить память, запустить другой процесс - всё это делает не программа, а ядро Linux по её просьбе. Эти "просьбы" и называются системными вызовами (syscalls). Программа как посетитель в банке: сама в сейф не лезет, а пишет заявки в окошко, и кассир (ядро) их выполняет.
strace - это камера, которая снимает все заявки в это окошко. Технически он делает это через системный вызов ptrace(2): ядро останавливает отслеживаемый процесс на каждом syscall и отдаёт strace его аргументы и результат. Команда strace показывает поток системных вызовов: имя вызова, его аргументы и результат. Ты буквально видишь, какие файлы программа пытается открыть, по каким путям лезет, к какому сокету подключается и где спотыкается. Поэтому говорят, что strace - это шпаргалка к тому, что софт делает на самом деле, без догадок.
Важно сразу понимать границу: strace отлично ловит обращения к файлам, сети, процессам и сигналам. Но из-за ptrace он замедляет программу в разы (каждый syscall - это два переключения контекста туда-обратно) и не показывает, что творится ВНУТРИ процесса между вызовами - там уже нужен perf или gdb. Для прода это значит: не вешай обычный strace надолго на нагруженный демон, иначе уронишь ему latency.

Базовый запуск: strace команда и strace -p PID
Есть два способа. Первый - запустить программу под наблюдением:
Код: Выделить всё
strace ls /tmpКод: Выделить всё
sudo strace -p 1319Теперь учимся читать вывод. Каждая строка - один системный вызов. Возьмём реальный пример:
Код: Выделить всё
openat(AT_FDCWD, "/etc/hosts", O_RDONLY|O_CLOEXEC) = 3
read(3, "127.0.0.1 localhost\n", 4096) = 20
close(3) = 0Главные опции strace и чтение ошибок
Несколько флагов делают strace по-настоящему рабочим. Запомни их как набор по умолчанию:
- -f - следить за дочерними процессами и потоками (форками). Нужен почти всегда: без него ты увидишь только главный процесс, а вся работа часто уходит в потомков и воркеры.
- -e trace=... - фильтр вызовов. Группы на 2026 пишутся с префиксом %: -e trace=%file (всё про пути к файлам), -e trace=%network или %net (сеть), -e trace=%process (форки и exec), -e trace=%desc (работа с дескрипторами), -e trace=%memory. Старая запись без % (trace=file) пока работает как синоним, но рекомендуемая форма - с процентом. Или поимённо: -e trace=openat,read,write.
- -o файл - писать вывод в файл, а не в терминал. Незаменимо, когда вызовов тысячи: strace -o /tmp/trace.log -p 1319.
- -s 200 - длина показываемых строк-аргументов. По умолчанию strace обрезает строки до 32 символов, и ты не видишь полный путь или тело запроса. Ставь -s 200, чтобы видеть больше. На свежих версиях (strace 6.10+, 2024) можно вообще снять лимит: -s inf.
- -y (он же --decode-fds) - показывать рядом с дескриптором его настоящий путь. Вместо голого read(3, ...) увидишь read(3</etc/hosts>, ...). Двойной -yy раскрывает ещё и сокеты с протоколом и адресом - очень помогает не держать в голове, какой fd что значит.
- -p PID - прицепиться к процессу (разбирали выше). Можно указать несколько: -p PID1 -p PID2.
- -t / -tt - добавить отметку времени в начало строки (-tt с микросекундами), -T - показать, сколько длился каждый вызов. Незаменимо, когда ищешь, на чём именно процесс залип.
Код: Выделить всё
sudo strace -f -yy -s 200 -T -e trace=%file -o /tmp/trace.log -p 1319Код: Выделить всё
sudo strace -f -Z -e trace=%file -p 1319Код: Выделить всё
openat(AT_FDCWD, "/etc/app/config.yml", O_RDONLY) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/var/log/app.log", O_WRONLY) = -1 EACCES (Permission denied)
read(7, 0x7ffd..., 4096) = -1 EAGAIN (Resource temporarily unavailable)- ENOENT - файла или каталога нет по этому пути. Самая частая причина "программа не стартует": лезет за конфигом не туда. Решение видно прямо в строке - вот точный путь, который она ждёт. Лайфхак: strace -f -e trace=%file ./app 2>&1 | grep ENOENT моментально выдаёт список всего, что программа искала и не нашла.
- EACCES - путь есть, но нет прав. Смотри владельца и режим файла (ls -l), от какого пользователя запущен процесс. Типичная история с правами на лог, сокет или каталог. Не путай с EPERM (часто это уже про привилегии/capabilities или ограничение seccomp/SELinux).
- EAGAIN (то же, что EWOULDBLOCK) - "пока нечего, попробуй позже". На неблокирующих сокетах это норма, а не ошибка: программа спрашивает данные, их ещё нет, она повторит. Рядом часто видно EINPROGRESS на connect - это тоже рабочий фон асинхронной сети. Пугаться одиночных EAGAIN не надо.
Код: Выделить всё
sudo strace -f -c -p 1319
% time seconds usecs/call calls errors syscall
------ ----------- ----------- --------- --------- ----------------
61.2 0.184523 18 10240 512 read
22.4 0.067610 33 2048 write
9.1 0.027400 534 51 51 connect2026: где strace уступил место eBPF
Это главное обновление урока. strace построен на ptrace и тормозит цель в разы - на горячем демоне с десятками тысяч syscall в секунду это опасно. Поэтому в 2026 для прода стандарт сместился к eBPF: ядро инструментирует точки вызова напрямую, без остановки процесса, и накладные расходы near-zero.
- opensnoop / opensnoop-bpfcc (из пакета bpfcc-tools) или opensnoop.bt (bpftrace) - то же самое, что strace -e trace=%file для отлова открытий файлов, но почти бесплатно по нагрузке. Идеально, когда надо понять, какой конфиг ищет сервис, не трогая его latency.
- execsnoop - ловит запуск новых процессов (execve) по всей системе. Незаменимо, когда сервис спавнит дочерние команды и они мгновенно умирают - обычным strace такое поймать сложно.
- bpftrace - однострочники под любую задачу. Например, посчитать syscall конкретного процесса: bpftrace -e 'tracepoint:raw_syscalls:sys_enter /pid == 1319/ { @[args.id] = count(); }'.
Код: Выделить всё
sudo strace -f --seccomp-bpf -e trace=%network -p 1319Типичные грабли и заблуждения
- Забыл -f. Снимаешь nginx или Apache, видишь почти пустоту и думаешь "ничего не делает". А вся работа в воркерах-потомках. Без -f их не видно.
- Строки обрезаны. Видишь "..." в аргументах и не понимаешь полный путь. Добавь -s 200 (или -s inf на свежих версиях).
- Путаешь EAGAIN с поломкой. На сетевых демонах EAGAIN, EWOULDBLOCK и EINPROGRESS - рабочий фон, а не авария. Авария - это когда ошибок 100% и процесс не движется.
- Вешаешь обычный strace на горячий прод надолго. ptrace тормозит процесс заметно. На нагруженной базе это может уронить latency. Бери -c для сводки, --seccomp-bpf для точечного фильтра или вообще eBPF.
- Ждёшь от strace внутренностей. Он показывает границу "программа - ядро", но не логику внутри функций. Чтобы увидеть, в каком коде застрял вызов, собери стек: strace -k (нужен strace, собранный с libunwind, и бинарь с отладочными символами).
Мини-лаба: попробуй прямо сейчас
- Запусти strace ls /etc и найди в выводе вызовы openat - посмотри, какие библиотеки (.so) и файлы открывает даже простая ls перед стартом.
- Сделай strace -e trace=openat cat /nonexistent и найди строку с -1 ENOENT. Это эталон "файла нет".
- Поймай только ошибки: strace -Z ls /root /nope /etc 2>&1 - сравни, что strace отфильтровал.
- Возьми реальный сервис: pidof sshd (или nginx), затем sudo strace -f -yy -s 200 -p ВЫБРАННЫЙ_PID. Поработай с сервисом и смотри, какие файлы и сокеты он дёргает. Отцепись по Ctrl+C.
- Сними сводку: sudo strace -f -c -p PID на 10-15 секунд и найди самый частый syscall и строку с максимумом errors.
- Если есть bpfcc-tools: запусти sudo opensnoop-bpfcc в одном окне, поработай системой в другом - сравни ощущение с strace по нагрузке.
- Чем отличается запуск strace команда от strace -p PID и когда нужен второй вариант?
- Что значит результат = -1 ENOENT и куда смотреть дальше при такой ошибке? Чем она отличается от EACCES?
- Зачем почти всегда добавляют флаг -f и что будет без него при трассировке nginx?
- Почему обычный strace опасно вешать на горячий прод и какие есть три обходных пути на 2026 год?