Наблюдение: ps, lsof, strace
Наблюдение за процессами: ps, lsof, strace, /proc.
Три угла зрения на один процесс
Когда сервис ведёт себя странно, полезно посмотреть на него с трёх сторон: что за процессы вообще запущены, какие файлы и соединения они держат, какие системные вызовы делают прямо сейчас. Под каждый вопрос есть свой инструмент.
ps даёт снимок. lsof показывает открытые файлы и сокеты. strace
подслушивает системные вызовы. Ниже по одному примеру на каждый, а в конце
тот же результат напрямую из ядра через /proc.
ps: снимок процессов
ps aux печатает разом все процессы в системе. Вывод — таблица с
фиксированными колонками:
$ ps aux
USER PID %CPU %MEM VSZ RSS STAT START TIME COMMAND
root 1 0.0 0.1 168240 11500 Ss 09:00 0:02 /sbin/init
www 812 1.3 2.4 720160 98400 Sl 09:01 0:21 nginx: worker
Что означают колонки:
| Колонка | Значение |
|---|---|
USER | владелец процесса |
PID | номер процесса |
%CPU | доля процессора |
%MEM | доля физической памяти |
RSS | реально занятая память в КБ (Resident Set Size) |
STAT | состояние (R, S, D, Z, T) |
COMMAND | что запущено |
Одна ловушка: обычный ps aux показывает процессы, а не потоки внутри них.
Многопоточный сервис выглядит одной строкой, хотя внутри крутится десяток
threads. Потоки вытаскивает флаг -L:
ps -L -p 812 # каждый поток процесса 812 отдельной строкой (колонка LWP)
lsof: какие файлы открыл процесс
lsof (list open files) отвечает на вопрос «что этот процесс держит
открытым». В Linux открытым файлом считается и обычный файл, и сокет, и
устройство, и pipe.
По PID:
$ lsof -p 812
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
nginx 812 www cwd DIR 8,1 4096 2 /
nginx 812 www 6u IPv4 18432 0t0 TCP *:http (LISTEN)
nginx 812 www 9u REG 8,1 14210 262145 /var/log/nginx/access.log
Обратный вопрос — «кто занял порт 80»:
lsof -i :80 # процессы, слушающие или использующие порт 80
Это первый ход, когда сервис не стартует с ошибкой «address already in use»:
lsof -i :<порт> сразу назовёт PID того, кто порт уже держит.
Тот же вопрос бывает шире: кто держит не отдельный файл, а целую точку
монтирования. Это классика ошибки umount: target is busy, когда раздел не
отмонтировать, потому что внутри него кто-то работает. lsof +f -- /mnt/data
перечислит процессы с открытыми файлами на этой точке, fuser -m /mnt/data
выдаст короткий список PID.
$ lsof +f -- /mnt/data
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
python 5120 app 3w REG 8,17 20480 132 /mnt/data/import.csv
$ fuser -m /mnt/data
/mnt/data: 5120
Дальше по ситуации: остановить сервис, дождаться конца записи или снять процесс сигналом. Точка отмонтируется, когда её отпустит последний держатель.
strace: какие системные вызовы делает процесс
Системный вызов (syscall) — это обращение процесса к ядру: открыть файл,
прочитать сокет, выделить память. strace перехватывает эти вызовы и печатает
их в реальном времени.
Подключиться к уже работающему процессу по PID:
$ strace -p 812
read(6, "GET / HTTP/1.1\r\n"..., 8192) = 79
openat(AT_FDCWD, "/var/www/index.html", O_RDONLY) = 11
write(9, "192.168.1.10 - - [11/Jul...]", 64) = 64
Чаще всего strace нужен в двух ситуациях. Процесс завис: видно, на каком
вызове он остановился (например, read из сокета, который никто не пишет).
Или процесс не находит файл, тогда в выводе всплывает строка вида:
openat(AT_FDCWD, "/etc/app/config.yml", O_RDONLY) = -1 ENOENT (No such file or directory)
ENOENT прямо говорит: искомого пути нет. Дальше остаётся понять, почему
процесс ждёт его именно там.
Здесь вторая ловушка. strace не бесплатен: он перехватывает каждый syscall,
и нагруженный процесс под ним заметно тормозит, иногда в разы. На боевом
сервисе с трафиком его вешают ненадолго и осознанно, а не оставляют висеть.
/proc: те же данные напрямую от ядра
Каталог /proc/<PID>/ — это интерфейс ядра к состоянию процесса, отдаётся
как обычные файлы. ps и lsof во многом читают именно его.
cat /proc/812/status # PID, PPID, состояние, память, потоки (Threads:)
cat /proc/812/cmdline # командная строка, аргументы разделены \0
ls -l /proc/812/fd # открытые дескрипторы: симлинки на файлы и сокеты
ls -l /proc/812/fd показывает то же, что lsof -p 812, только без обёртки:
lrwx------ 1 www www 64 Jul 11 09:01 6 -> socket:[18432]
l-wx------ 1 www www 64 Jul 11 09:01 9 -> /var/log/nginx/access.log
Сигналы: что стоит помнить рядом
Наблюдая за процессом, часто им же и управляют сигналами. Пара фактов, о которые легко споткнуться.
Перехватить, заблокировать или проигнорировать нельзя ровно два сигнала:
SIGKILL и SIGSTOP. Остальные процесс волен обработать по-своему.
У сигнала есть действие по умолчанию, если обработчик не задан. Их пять:
Term (завершить), Ign (проигнорировать), Core (завершить с дампом),
Stop (остановить), Cont (продолжить). Например, SIGCHLD по умолчанию
относится к Ign: процесс не обязан реагировать на завершение потомка.
Про зомби из прошлого урока: запись зомби в таблице процессов держит только
номер PID, память процесса уже освобождена. Когда родитель умирает раньше
потомка, осиротевшего усыновляет init (PID 1) и вызывает для него wait(),
так что вечных зомби под нормальным init не бывает. С ядра 3.4 роль такого
сборщика можно передать заранее назначенному процессу через subreaper, а не
только PID 1.
Что важно запомнить
ps aux — снимок процессов и их ресурсов; потоки только с флагом -L.
lsof -p <PID> — открытые файлы процесса, lsof -i :<порт> — кто занял порт,
lsof +f -- /mnt и fuser -m /mnt — кто держит точку монтирования.
strace -p <PID> — системные вызовы в реальном времени; ENOENT = файл не
найден. На нагруженном проде вешать осторожно, он тормозит процесс.
/proc/<PID>/ (status, fd, cmdline) — те же данные напрямую от ядра.
SIGKILL и SIGSTOP не перехватить; действий по умолчанию пять
(Term/Ign/Core/Stop/Cont); осиротевший процесс усыновляет PID 1.
Дальше — короткий квиз по треку процессов.
Дрилл · вопросы как на собесе
Проверь себя без подсказок
Сформулируй ответ вслух или письменно, потом раскрой и честно отметь: знал или нет.
Где хранится информация о процессах в Linux?
LIN-027Как понять, какими процессами используется раздел?
LIN-093Прошли материал до конца? Отметьте урок пройденным.
Прогресс сохранён в этом браузере
Почистишь историю или откроешь с телефона, и отметки пропадут. Оставь почту, они переедут в аккаунт. Пароль придумывать не нужно.
Готово. теперь в аккаунте: прогресс виден с любого устройства. Мой прогресс