strace: трассировка системных вызовов для диагностики зависаний и утечек
При зависании сервиса стандартные инструменты — top, htop, ps — показывают состояние, но не причину. Если процесс в state D (uninterruptible sleep), значит он ждёт syscall. strace подключается к живому процессу и выводит каждый системный вызов в реальном времени. Это превращает загадочное зависание в конкретный syscall, его аргументы и код возврата.
strace работает через ptrace — механизм ядра для отладки. На продакшене трассировка замедляет процесс в 2–10 раз. Используйте точечно, на отдельном PID.
Базовые флаги и синтаксис
Установка:
Запуск:
Основные флаги для диагностики:
| Флаг | Назначение |
|---|---|
-f | Следить за дочерними процессами |
-c | Подсчёт вызовов и времени (summary) |
-tt | Микросекундные метки времени |
-T | Время выполнения каждого syscall |
-e trace=openat,read,write | Трассировать только указанные вызовы |
-e write=1,2 | Трассировать запись только в fd 1 и 2 |
-o output.log | Запись в файл |
-s 1024 | Обрезать строки длиннее N символов |
Диагностика блокирующих вызовов
Сценарий: процесс завис, в ps видите state D. Нужно понять, на чём именно он заблокирован.
Типичный вывод при блокировке на файле:
Если видите read(...) <время> = 0 с большим временем — процесс ждёт данных. Если <время> исчисляется секундами, нашли bottleneck.
Блокировка на epoll_wait, poll, select — нормально для idle-процесса. Ищите read, write, openat, sendto с временем больше 100ms.
Для сетевых сокетов полезно:
Зависание на connect() к недоступному хосту:
EINPROGRESS означает неблокирующий сокет, но долгое время указывает на проблему сети или таймаут.
Поиск утечек файловых дескрипторов
Сценарий: процесс не открывает файлы, ошибка “too many open files”. Нужно понять, кто держит дескрипторы.
Подключаем strace с фильтром на открытие файлов:
Анализируем вывод:
Альтернатива — summary mode:
Если close вызывается меньше openat — нашли утечку.
При высокой частоте вызовов (тысячи в секунду) strace генерирует огромный вывод. Ограничивайте время -tt и фильтруйте по syscall через -e trace=.
Анализ медленных запросов
Сценарий: API- endpoint отвечает 5 секунд вместо 200ms. Нужно найти, на каком syscall теряется время.
Ищем вызовы с большим временем выполнения:
openat с 523ms — ищем причину: файл на NFS, отсутствие прав, удалённый filesystem.
Для SQL-подобных запросов (PostgreSQL, MySQL) трассируем сокет:
Медленный запрос к БД выглядит как серия write/read с долгим временем между ними:
4.7 секунды между отправкой запроса и получением данных — проблема на стороне БД или сети до неё.
Коротко
strace превращает зависание без видимых причин в конкретный syscall. Подключайтесь к PID, фильтруйте вызовы через -e trace=, смотрите время выполнения через -T. Для утечек — сравнивайте open/close в summary mode. Для медленных запросов — ищите вызовы с временем больше 100ms.
На продакшене используйте -e trace=write,read,openat вместо трассировки всех вызовов — снизит overhead в 3–5 раз.