lenec ru

← все посты

Redis eviction policies: какую стратегию вытеснения выбрать и почему

15K

Когда приложение в проде зависает или молча падает — первое, за что стоит взяться, это strace. Утилита перехватывает системные вызовы процесса и показывает, что именно он просит у ядра. Никакой перекомпиляции, никаких дебаг-символов — подключился к PID и смотришь.

Что такое strace и когда нужен

strace — трассировщик системных вызовов (syscalls) в Linux. Каждый раз, когда процесс обращается к ядру — открывает файл, читает сокет, выделяет память — strace это логирует. Незаменим когда:

  • Приложение падает без внятных логов
  • Сервис зависает и не отвечает на запросы
  • Непонятно, какие файлы/сокеты процесс открывает
  • Нужно понять, почему процесс тормозит на I/O

Главное преимущество — работает с любым бинарником без исходников.

Базовые флаги: -p, -e, -f, -t

Минимальный набор, который покрывает 90% задач:

# Подключиться к работающему процессу
strace -p 12345

# Трассировать только определённые syscalls
strace -e trace=open,read,write ./myapp

# Следить за дочерними процессами
strace -f -p 12345

# Временные метки + дочерние + сеть
strace -tf -e trace=network -p 12345

Дополнительные флаги:

  • -c — статистика по syscalls (summary)
  • -o file.log — вывод в файл
  • -s 1024 — увеличить длину строк
  • -T — время выполнения каждого вызова

Реальный кейс: приложение висит на I/O

Node.js-сервис в проде перестал отвечать. Логи пустые, CPU около нуля. Подключаемся:

PID=$(pgrep -f "node server.js")
strace -p $PID -e trace=read,write,futex -T 2>&1 | head -30

Видим в выводе:

futex(0x7f3a2c000900, FUTEX_WAIT_PRIVATE, 2, NULL) = 0 <4.999872>
read(23, "", 65536)                     = 0 <5.000034>

Процесс висит на read с дескриптором 23, таймаут ровно 5 секунд. Проверяем дескриптор:

ls -la /proc/$PID/fd/23
# socket:[1847523]

ss -tnp | grep $PID
# ESTAB 10.0.3.15:43210 10.0.5.80:5432

Это TCP-соединение к PostgreSQL. База не отвечает — оказалось, pg_locks заблокировал таблицу из-за незавершённой миграции. Убиваем транзакцию — сервис оживает. Диагностика заняла 3 минуты.

Фильтрация по syscall

Группы для -e trace=:

# Файловые операции
strace -e trace=file ./app

# Сетевые вызовы
strace -e trace=network ./app

# Исключить шумные вызовы
strace -e trace=!futex,clock_gettime,epoll_wait -p $PID

Совет: начните с strace -c — покажет топ syscalls по количеству и времени. Дальше фильтруйте по самым частым.

Альтернативы: ltrace, perf, bpftrace

  • ltrace — трассирует вызовы библиотечных функций (libc). Полезен, когда проблема не в syscalls, а в логике библиотеки.
  • perf trace — аналог strace с меньшим оверхедом. Подходит для нагруженных сервисов.
  • bpftrace — скриптуемый трассировщик на eBPF. Сложные условия: «покажи все read() дольше 100мс».
# perf trace: низкий оверхед
perf trace -p $PID --duration 100

# bpftrace: медленные read()
bpftrace -e 'tracepoint:syscalls:sys_exit_read { if (args->ret > 0) { printf("%d\n", nsecs); } }'

Подводные камни

  • Оверхед — strace замедляет процесс в 10-100 раз. На проде используйте кратковременно.
  • Многопоточность — без -f видите только главный тред.
  • Права — нужен root или CAP_SYS_PTRACE. В Docker: --cap-add=SYS_PTRACE.
  • Контейнеры — в Kubernetes используйте kubectl debug с ephemeral-контейнером.

strace — швейцарский нож для отладки в Linux. Не требует подготовки, работает с любым бинарником и даёт ответы за минуты. Освойте -p, -f, -e, -T — и большинство «необъяснимых» багов перестанут быть загадкой.

Комментарии 0

  • Будьте первым, кто оставит комментарий.

Войдите, чтобы оставить комментарий.