Процессы Linux: ps, pstree и состояния процессов

Рейтинг: 55.2% · 12 голосов
Подробный курс по диагностике и производительности Linux для админов и DevOps: с чего начать, методология USE, логи (journalctl, dmesg), процессы, CPU, память и OOM, диск и IO (iostat), сеть (ss, tcpdump), системные вызовы и strace, ltrace, perf, флеймграфы, ftrace, eBPF и bpftrace, lsof, мониторинг. Разбор каждого инструмента с чтением вывода.
Ответить
Аватара пользователя
Dmitry_SRE
Сообщения: 47
Зарегистрирован: 11 май 2026, 05:31

Процессы Linux: ps, pstree и состояния процессов

Сообщение Dmitry_SRE »

Оглавление курса (47)
  1. С чего начать диагностику Linux: методология вместо паники
  2. Первые 60 секунд: экспресс-диагностика нагруженного сервера
  3. Методологии диагностики: USE, RED и здравый смысл
  4. Логи systemd через journalctl: где искать причину
  5. Где лежат логи Linux: /var/log, dmesg и rsyslog
  6. Источники правды: load average, /proc и /sys
  7. Процессы Linux: ps, pstree и состояния процессов (вы здесь)
  8. Интерактивный мониторинг: top и htop
  9. Метрики процессов во времени: pidstat
  10. Приоритеты и ограничения: nice, ionice, cgroups
  11. Сигналы и зависшие процессы: kill, и что делать с D-state
  12. Загрузка CPU: user, system, iowait, steal и контекст-свитчи
  13. Диагностика CPU по ядрам: vmstat и mpstat
  14. Профилирование CPU: perf top и поиск пожирателя
  15. Частоты, троттлинг и NUMA: turbostat и numastat
  16. Память Linux: RSS, VSZ, page cache и миф о нехватке памяти
  17. Сколько памяти занято: free, /proc/meminfo и vmstat
  18. Поиск утечек и пожирателей памяти: smem, pmap, smaps
  19. Swap и подкачка: swapon, swappiness, когда своп - это боль
  20. OOM killer: кто и за что убил процесс
  21. Память ядра и slab: slabtop и куда уходит RAM
  22. Подсистема ввода-вывода: путь запроса от приложения до диска
  23. Диагностика диска: iostat и чтение await, %util
  24. Кто грузит диск: iotop и атрибуция io процессам
  25. Файловые системы: df, du, иноды и куда делось место
  26. Глубокая диагностика блочного слоя: blktrace и biolatency
  27. Кеш страниц и грязные данные: dirty pages, fsync, drop_caches
  28. Сетевой стек Linux: путь пакета и где возникают задержки
  29. Сокеты и соединения: ss и netstat
  30. Захват трафика: tcpdump для диагностики сети
  31. Задержки и потери в сети: ping, mtr, диагностика латентности
  32. Сеть как источник проблем: nftables, conntrack, дропы
  33. Что такое системный вызов и зачем его трассировать
  34. strace: трассировка системных вызовов на практике
  35. strace в бою: почему программа висит, падает или тормозит
  36. ltrace: трассировка вызовов библиотек
  37. Накладные расходы трассировки и безопасные альтернативы
  38. perf: универсальный профайлер Linux
  39. Флеймграфы: визуализация профиля производительности
  40. Трассировка ядра: ftrace и trace-cmd
  41. eBPF: революция в наблюдаемости Linux
  42. Инструменты eBPF на практике: BCC и bpftrace
  43. lsof: открытые файлы, дескрипторы, кто держит файл и порт
  44. Разбор кейса: приложение тормозит - пошаговая диагностика
  45. Непрерывный мониторинг: sar, node_exporter, Grafana, Zabbix
  46. Диагностика в контейнерах: cgroups, лимиты, Docker и Kubernetes
  47. Карта инструментов и сквозной разбор инцидента производительности
Представь: сервер "висит", сайт отвечает по 30 секунд, нагрузка по top вроде есть, а что именно происходит - непонятно. С чего начать? Почти всегда первый шаг диагностики в Linux - это посмотреть на процессы. Не на абстрактные графики в мониторинге, а руками, в консоли: какие процессы живут на машине, кто кого породил и в каком они состоянии. Состояние процесса часто сразу подсказывает диагноз - например, что куча процессов застряла в ожидании диска, а не в вычислениях. В этом уроке разберём базис: команды ps и pstree, иерархию родитель-потомок и ту самую колонку STAT, по которой опытный админ читает проблему за пару секунд. Материал актуален на 2026 год: современный Linux с systemd, cgroup v2 по умолчанию и ядро 6.x.

Что такое процесс и зачем тут ps

Процесс - это запущенная программа: код плюс выделенная ей память, открытые файлы, переменные окружения и так далее. У каждого процесса в Linux есть номер - PID (process ID). И есть PID родителя - PPID (parent PID), потому что в Linux процессы не возникают из воздуха: один процесс порождает другой системным вызовом fork (или clone). В самом верху этой пирамиды стоит init-процесс с PID 1 (на современных системах это systemd) - предок всех остальных. Важная деталь 2026: systemd как PID 1 является "субреапером", то есть автоматически усыновляет осиротевшие процессы и подбирает за ними - дальше это пригодится в разговоре про зомби.

Главный инструмент, чтобы увидеть linux процессы прямо сейчас, - это ps (process status). Он делает моментальный снимок: показывает, что происходит в момент запуска команды, и завершается. Этим он отличается от top/htop, которые обновляют картинку в реальном времени. Для разовой диагностики снимок ps часто удобнее: его можно скопировать, отгрепать, сохранить в файл, приложить к тикету. На современных дистрибутивах ps идёт из пакета procps-ng (версии 4.x), та же кодовая база у pgrep, pkill, pstree, pidof - это важно помнить, потому что флаги у них согласованы.

У ps исторически два набора флагов, и новичков это путает. Есть BSD-стиль (флаги без дефиса) и UNIX/POSIX-стиль (флаги с дефисом). Это не просто косметика - они дают разные колонки по умолчанию:
  • ps aux - BSD-стиль. Показывает USER, PID, %CPU, %MEM, VSZ, RSS, TTY, STAT, START, TIME, COMMAND. Удобен, когда интересны CPU и память.
  • ps -ef - UNIX-стиль. Показывает UID, PID, PPID, C, STIME, TTY, TIME, CMD. Удобен, когда нужен PPID (кто родитель).
Важная ловушка: пиши именно ps aux, без дефиса. Если написать ps -aux, procps-ng воспримет это как UNIX-стиль с опцией -a и -u БЕЗ аргумента и выдаст предупреждение или не то, что ты ждёшь. Привыкай различать стили сразу.

Изображение

Читаем вывод ps aux по колонкам

Теория без интерпретации бесполезна, поэтому смотрим на реальный вывод и разбираем каждое поле.

Код: Выделить всё

$ ps aux | head -4
USER      PID %CPU %MEM    VSZ    RSS TTY STAT START  TIME COMMAND
root        1  0.0  0.1 167840  11200 ?   Ss   09:01  0:03 /sbin/init
www       912 12.5  4.3 982340 351200 ?   Sl   09:14  2:41 php-fpm: pool www
postgres  770  0.7  8.1 1450220 660400 ?  Ss   09:12  0:55 postgres: main
Что значат поля:
  • USER - от чьего имени работает процесс. Если веб-сервис крутится от root - это повод задуматься о безопасности.
  • PID - номер процесса. Его подставляют в kill, strace, ну и вообще он главный идентификатор.
  • %CPU - доля процессора. Может быть больше 100, если процесс многопоточный и грузит несколько ядер (100 = одно полное ядро). Учти: ps считает %CPU как среднее за всё время жизни процесса, а не "вот сейчас", поэтому для мгновенной картины CPU лучше top/htop, а ps - для снимка и сортировки.
  • %MEM - доля физической памяти (RSS) от общей RAM.
  • VSZ - виртуальный размер (сколько адресного пространства зарезервировано) в килобайтах. Часто пугающе большой, но это НЕ реально занятая RAM.
  • RSS - resident set size, вот это уже реально занятая физическая память в килобайтах. Для оценки "кто съел память" смотри на RSS, а не на VSZ. Тонкость: RSS включает разделяемые библиотеки, поэтому сумма RSS всех процессов может быть больше реальной RAM. Для честной оценки уникальной памяти процесса есть поле PSS из /proc/PID/smaps_rollup (но это уже за пределами ps).
  • TTY - терминал. Знак ? означает, что процесс не привязан к терминалу (демон).
  • STAT - состояние. О нём ниже отдельно, это самое интересное.
  • TIME - сколько процессорного времени процесс суммарно сжёг (не время с момента старта, а именно CPU-время).
Чтобы найти пожирателей ресурсов, не нужно глазами листать - сортируй встроенными средствами. Колонки для вывода задаёт флаг -o (своя выборка полей), порядок - флаг --sort:

Код: Выделить всё

# Топ-10 по потреблению CPU (знак минус = по убыванию)
ps -eo pid,ppid,user,%cpu,%mem,stat,comm --sort=-%cpu | head -n 11

# Топ-10 по памяти (по RSS)
ps -eo pid,user,rss,%mem,stat,comm --sort=-rss | head -n 11
Здесь -e значит "все процессы". В наборе полей comm - короткое имя процесса, а args (синоним command) - полная командная строка с аргументами. Набор полей ты выбираешь сам, это и есть сила -o. Полезный приём: поле можно расширить по ширине через двоеточие, например wchan:32, чтобы длинное значение не обрезалось.

Колонка STAT и состояние процесса в linux

Вот ради чего всё затевалось. Состояние процесса в linux - это первое, на что смотрит инженер при зависании. Первая буква в STAT - это и есть основное состояние:
  • R - running или runnable. Процесс прямо сейчас выполняется на CPU или готов выполняться и стоит в очереди (runqueue). Много R при высокой нагрузке - это нагрузка на процессор.
  • S - interruptible sleep, прерываемый сон. Процесс спит и ждёт события (сетевого пакета, ввода, таймера). Его можно разбудить сигналом. Подавляющее большинство процессов в системе именно в S - это норма, они просто ждут работу.
  • D - uninterruptible sleep. Процесс спит так, что обычными сигналами его не трогают, потому что он ждёт завершения операции ядра, почти всегда дискового ввода-вывода. Один-два D на миг - нормально (так выглядит любое активное чтение/запись). Но если процессы надолго залипают в D - это красный флаг. Это тот самый d state linux, из-за которого load average улетает в небеса, хотя CPU при этом простаивает: машина не считает, а ждёт диск (или зависший NFS, или сбойный накопитель). Про убийство D-процессов есть важный нюанс 2026 - сразу ниже.
  • Z - zombie, зомби. Процесс уже завершился, но его родитель ещё не забрал код возврата (не сделал wait). Зомби не потребляет CPU и память - от него остаётся только запись в таблице процессов. Опасен он не сам по себе, а как симптом: если зомби копятся пачками, значит родитель написан криво и не подбирает за детьми. Когда упрёшься в лимит PID (kernel.pid_max), система не сможет создавать новые процессы. Убить зомби нельзя (он и так мёртв) - лечится либо тем, что родитель наконец сделает wait, либо смертью самого родителя.
  • T - stopped, остановлен сигналом job control (например, Ctrl+Z или kill -STOP). Процесс заморожен и ждёт SIGCONT.
  • t - tracing stop, остановлен под отладчиком (strace, gdb). Полезно отличать от T: это не job control, а трассировка.
  • I - idle, простаивающий поток ядра (увидишь у kworker и подобных). Состояние появилось в ядре 4.14, чтобы такие потоки не накручивали load average. На любом современном ядре 6.x это норма.
Большой миф, который надо убить: "процесс в D нельзя завершить даже kill -9". На современном Linux это уже не всегда так. В ядре давно появилось состояние TASK_KILLABLE - разновидность непрерываемого сна, которая всё-таки реагирует на фатальный сигнал (SIGKILL). Многие места ядра, особенно сетевые ФС вроде NFS, переписаны на killable-сон, поэтому в современных системах часть D-процессов убивается через kill -9. Но не все: если код ядра ушёл в классический непрерываемый сон (старый драйвер, сбойный локальный диск), то да - никакой сигнал не подействует, пока операция не завершится или не отвалится по таймауту. Так что правильная формулировка на 2026: D-процесс может не убиваться сигналом, и это зависит от того, killable там сон или нет.

После основной буквы идут дополнительные флаги-модификаторы, их полезно понимать:
  • s - процесс является лидером сессии.
  • l - многопоточный (использует CLONE_THREAD).
  • + - находится в foreground-группе процессов (на переднем плане в терминале).
  • < - повышенный приоритет (отрицательный nice).
  • N - пониженный приоритет (положительный nice).
  • L - имеет страницы, залоченные в памяти (mlock).
То есть Ssl - это спящий лидер сессии с потоками (типичный демон), а R+ - выполняется на переднем плане в твоём терминале. Зомби обычно выглядит как Z и подписан defunct:

Код: Выделить всё

$ ps aux | grep defunct
user 4123 0.0 0.0 0 0 ? Z 10:22 0:00 [worker] <defunct>
Обрати внимание: у зомби VSZ и RSS равны нулю - памяти нет, осталась только запись.

Куда смотреть дальше: wchan и диагностика D-state

Самый частый прикладной вопрос - "процессы залипли в D, что они ждут?". Не угадывай - спроси у ядра, в какой функции процесс заснул. Это показывает поле wchan (wait channel):

Код: Выделить всё

$ ps -eo pid,user,stat,wchan:24,comm --sort=-stat | head
  PID USER  STAT WCHAN                    COMMAND
 5012 www   D    folio_wait_bit_common    php-fpm
 5013 www   D    nfs_wait_on_request      php-fpm
Имя функции в WCHAN сразу намекает на причину: folio_wait_bit / io_schedule - ждём страничный ввод-вывод (локальный диск), nfs_... - сетевая ФС. Если нужен полный стек ядра для конкретного PID, на современном ядре доступен псевдофайл:

Код: Выделить всё

sudo cat /proc/5012/stack
И главный инструмент 2026 для подтверждения "это правда диск, а не CPU" - PSI (Pressure Stall Information), включён по умолчанию на cgroup v2:

Код: Выделить всё

$ cat /proc/pressure/io
some avg10=42.13 avg60=38.40 avg300=20.05 total=...
full avg10=31.02 avg60=27.66 avg300=15.10 total=...
Цифры some/avg10 в десятках процентов означают: задачи реально простаивают в ожидании ввода-вывода. Это куда честнее, чем гадать по load average. Аналогично есть /proc/pressure/cpu и /proc/pressure/memory.

Дерево процессов: pstree, родитель и потомок

ps показывает плоский список, а связи родитель-потомок по нему читать неудобно. Для иерархии есть pstree - он рисует дерево, наглядно показывая, кто кого породил:

Код: Выделить всё

$ pstree -p
systemd(1)-+-sshd(820)---sshd(1502)---bash(1503)
           |-nginx(900)-+-nginx(901)
           |            `-nginx(902)
           `-php-fpm(912)-+-php-fpm(940)
                          `-php-fpm(941)
Флаг -p добавляет PID в скобках. Сразу видно: systemd породил nginx и php-fpm, а nginx породил рабочие воркеры. Если у тебя зомби или процесс ведёт себя странно - дерево моментально показывает виновного родителя, к которому идти разбираться. Удобные флаги: pstree -s PID показывает цепочку предков конкретного процесса (от него вверх до systemd), а pstree -T скрывает потоки, чтобы дерево не зашумлялось. Если pstree не установлен, его ставят из пакета psmisc (актуально и для Astra Linux, и для RED OS).

Чтобы увидеть потоки внутри процесса (а не только сами процессы), у ps есть флаг -L. Он добавляет колонки LWP (light weight process, идентификатор потока) и NLWP (число потоков):

Код: Выделить всё

ps -L -p 912 -o pid,lwp,nlwp,stat,%cpu,comm
Эквивалентный BSD-способ - ps -T или ps H. Это пригодится, когда один многопоточный процесс грузит CPU и надо понять, какой именно его поток виноват: находишь LWP с высоким %CPU, а дальше можно копать его стек.

И последнее из базиса - быстрый поиск процесса по имени без grep. Для этого есть pgrep (и его брат pkill для сигналов):

Код: Выделить всё

pgrep -a nginx        # PID-ы и полные командные строки всех nginx
pgrep -u www php-fpm  # только процессы пользователя www
pgrep -c php-fpm      # просто посчитать количество
Связка на каждый день: ps -o ... -p $(pgrep -d, php-fpm) - и ты сразу смотришь нужные колонки только по интересующим процессам.

Типичные грабли и заблуждения
  • VSZ - это не съеденная память. Новички пугаются гигантских чисел в VSZ. Реально занятую RAM показывает RSS, а честную уникальную - PSS.
  • Высокий load average при простое CPU. Классика: load average 30, а %CPU почти нулевой. Значит, процессы стоят в D-state и ждут диск или сеть. Лечится не докидыванием ядер, а разбором, куда упирается ввод-вывод - подтверди через /proc/pressure/io, wchan, дальше iostat/iotop (или eBPF-инструмент biolatency).
  • Попытка убить зомби. kill по зомби не сработает - он уже мёртв. Смотри на его родителя (PPID) в ps -ef, проблема в нём.
  • "kill -9 никогда не берёт D-процесс". Устаревшее правило. На современном ядре часть D-сна - killable и реагирует на SIGKILL (например NFS). Не убивается только классический непрерываемый сон.
  • ps -aux против ps aux. Разные стили разбора флагов. Привыкай к ps aux без дефиса.
  • Idle-потоки больше не пугают. Состояние I у kworker - это нормально и не накручивает load. Не путай с D.
Мини-лаба: повтори руками прямо сейчас
  • Выполни ps aux | head и найди свои процессы по столбцу USER. Посмотри на STAT - большинство ли в S?
  • Выведи топ по памяти: ps -eo pid,user,rss,stat,comm --sort=-rss | head. Кто занял больше всего RSS? Сравни с VSZ того же процесса.
  • Запусти sleep 600 на переднем плане, нажми Ctrl+Z и найди его в ps - увидишь состояние T. Верни в работу через fg или bg.
  • Посмотри, что ждут процессы: ps -eo pid,stat,wchan:24,comm | grep -E " D | S " | head.
  • Подсмотри давление ввода-вывода: cat /proc/pressure/io (нужен cgroup v2, по умолчанию на современных дистрибутивах).
  • Нарисуй дерево: pstree -p и найди в нём свой bash и его родителя. Затем pstree -s $$ - цепочка предков твоей оболочки.
  • Найди процесс по имени: pgrep -a sshd.
Контрольные вопросы
  • Чем отличается вывод ps aux от ps -ef и когда какой удобнее?
  • Что означает состояние D в колонке STAT, и правда ли, что такой процесс невозможно убить даже kill -9? Поясни, от чего это зависит на современном ядре.
  • Что такое зомби-процесс, чем он опасен и как от него избавиться?
  • Какую колонку смотреть, чтобы оценить реально занятую процессом память - VSZ или RSS, и почему?
  • Куда смотреть, чтобы понять, что именно ждёт залипший в D процесс?
Что запомнить

ps - твой первый инструмент при разборе зависаний: ps aux для CPU и памяти, ps -ef для родителей, ps -eo для своих колонок с сортировкой. Связи процессов смотри через pstree, потоки - через ps -L, ищи по имени через pgrep. Главное - научись читать колонку STAT: R значит работает или готов, S - нормальный сон, D - залип на вводе-выводе (тревога, если надолго), Z - зомби (симптом кривого родителя), T - остановлен. Если упёрся в D - не гадай, смотри wchan, /proc/PID/stack и /proc/pressure/io. Состояние процесса - это самый быстрый способ понять, машина считает, ждёт диск или просто простаивает.
👍2 ❤️1 🔥 😄 🤔2
Аватара пользователя
sheibley
Сообщения: 1
Зарегистрирован: 11 май 2026, 14:59

Re: Процессы Linux: ps, pstree и состояния процессов

Сообщение sheibley »

Спасибо, наконец дошло про D-state. У нас как раз load был под 40, а top показывал CPU почти в нуле, я думал мониторинг врет. Оказалось диск сыпался и процессы висели в D. Часть удалось прибить kill -9, а часть - нет, пока NFS не отвалился по таймауту.
👍 ❤️ 🔥1 😄 🤔
Аватара пользователя
nicnoc
Сообщения: 1
Зарегистрирован: 14 май 2026, 16:29

Re: Процессы Linux: ps, pstree и состояния процессов

Сообщение nicnoc »

Про wchan и /proc/pressure/io прям полезно, раньше я только load average смотрел и гадал. Вопрос новичка: если зомби висит, а родитель это systemd с PID 1, он сам его подберет? Или так и будет defunct в списке?
👍 ❤️1 🔥 😄 🤔1
Ответить
← Предыдущая глава
Источники правды: load average, /proc и /sys
Следующая глава →
Интерактивный мониторинг: top и htop

Все главы курса «Диагностика и производительность Linux: логи, strace, perf и eBPF»

Поделиться темой: ✈ Telegram VK
Похожие запросы: как посмотреть сколько памяти занято в linuxlsof кто держит файл и порт в linuxperf top как найти что грузит процессорчто такое системный вызов и зачем трассироватьЛоги и диагностика macOSкак посмотреть процессы в linux и убить зависший

Вернуться в «Диагностика и производительность Linux: логи, strace, perf и eBPF»

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и 1 гость