ОП.05Диагностика процессов и управление ресурсамизанятие 8Материалы

Часть 3 из 7

Поиск виновника: ps, pstree и /proc

В этой части разберём, как командой ps найти процесс, который занял процессор или память, и как узнать, кто его запустил и из какого каталога.

  1. 3.1 ps с сортировкой
  2. 3.2 Откуда взялся процесс
  3. 3.3 Если процессов много

3.1 ps с сортировкой

Вывод top меняется каждые три секунды, его неудобно сохранять и разбирать. Неподвижный список с нужными столбцами выводит ps: ключ -e выбирает все процессы системы, -o — нужные столбцы, --sort — порядок.

Знак минус перед именем столбца в --sort сортирует по убыванию. --sort=-%cpu ставит наверх самый загруженный процесс, --sort=-rss — процесс, занявший больше всего памяти. head оставляет заголовок и первые строки.

Столбец psЧто показывает
pid, ppidномер процесса и номер родителя
userвладелец
niпоправка приоритета nice
statсостояние
%cpuсредняя загрузка процессора за всю жизнь процесса
%mem, rssдоля памяти и занятая память в килобайтах
etimeсколько процесс работает
cmdкомандная строка с аргументами

Сортировка — как список должников в библиотеке, упорядоченный по сроку просрочки. Первая строка сразу показывает, с кого начинать разговор.

3.2 Откуда взялся процесс

Чтобы решить, что делать с найденным процессом, нужно понять, кто его запустил. Для этого есть три команды.

КомандаЧто отвечает
pstree -s -p PIDцепочка родителей от PID 1 до процесса: служба, терминал или другая программа
ls -l /proc/PID/cwdтекущий каталог процесса: где он работает
ps -o lstart,etime -p PIDкогда процесс запущен и сколько работает

Ключ -s у pstree показывает предков процесса. Если в цепочке есть gnome-terminal и bash, процесс запущен из терминала. Если над ним сразу systemd — это служба или сирота, у которой завершился родитель.

В опыте мы запустим процесс, который бесконечно крутит пустой цикл в каталоге /tmp, и найдём его по списку ps. Запись P=$( … ) сохраняет вывод команды в переменную P, а pgrep -f находит PID по фрагменту командной строки, который виден в списке.

В списке рядом с виновником может оказаться сама команда ps с большим %CPU. Она только что запустилась, а %CPU в ps — среднее за жизнь процесса, поэтому у новых процессов оно завышено. Такую строку пропускают.

В терминалеНайти и опознать
  1. bash -c 'cd /tmp; while true; do :; done' &# неизвестный процесс
    что делает

    Что делает команда. Запускает в фоне оболочку, которая переходит в /tmp и бесконечно крутит пустой цикл, занимая ядро.

    По частям:

    bash -c '…'
    запустить bash и выполнить команды из строки
    cd /tmp
    перейти в каталог /tmp: он станет текущим каталогом процесса
    while true; do :; done
    бесконечный цикл; двоеточие — пустая команда, процесс просто крутится
    &
    запустить в фоне
  2. ps -eo pid,ppid,user,stat,%cpu,etime,cmd --sort=-%cpu | head -4# самые загруженные
    что делает

    Что делает команда. Выводит все процессы системы, отсортированные по загрузке процессора, и оставляет заголовок и три первые строки.

    По частям:

    ps
    вывести сведения о процессах
    -eo pid,ppid,user,stat,%cpu,etime,cmd
    -e — все процессы системы; -o — выводить столбцы pid,ppid,user,stat,%cpu,etime,cmd
    --sort=-%cpu
    сортировать по загрузке процессора, минус — по убыванию
    |
    передать вывод левой команды на вход следующей
    head
    оставить только первые строки
    -4
    сколько первых строк оставить: 4
  3. P=$(pgrep -f 'while true')# PID найденного процесса
    что делает

    Что делает команда. Находит процесс, в командной строке которого есть while true, и сохраняет его PID в переменную P.

    По частям:

    P=$( … )
    сохранить в переменную P вывод команды в скобках
    pgrep
    найти процессы и вывести их PID
    -f
    искать образец во всей командной строке, а не только в имени
    'while true'
    образец
  4. pstree -s -p $P# кто его запустил
    что делает

    Что делает команда. Рисует цепочку предков процесса от PID 1 с номерами.

    По частям:

    pstree
    нарисовать дерево процессов
    -s
    показать предков процесса — цепочку от PID 1
    -p
    показывать PID рядом с именем
    $P
    с какого процесса начинать, значение переменной P: сохранённый PID
  5. ls -l /proc/$P/cwd# где он работает
    что делает

    Что делает команда. Показывает, на какой каталог указывает ссылка cwd — текущий каталог процесса.

    По частям:

    ls
    вывести содержимое каталога
    -l
    подробный список: права, владелец, размер, дата; для ссылки — куда она указывает
    /proc/$P/cwd
    что показать (абсолютный путь)
  6. ps -o lstart,etime -p $P# когда запущен
    что делает

    Что делает команда. Выводит дату и время запуска процесса и сколько он работает.

    По частям:

    ps
    вывести сведения о процессах
    -o lstart,etime
    выводить столбцы lstart,etime
    -p $P
    выбрать процесс: PID из переменной P
  7. kill $P# завершить
    что делает

    Что делает команда. Посылает процессу из переменной P сигнал TERM.

    По частям:

    kill
    послать процессу сигнал
    $P
    какому процессу, значение переменной P: сохранённый PID
Результат

наверху списка — bash -c с загрузкой около 100 %; цепочка ведёт к оболочке терминала, текущий каталог процесса — /tmp.

Снимок 3.1Ubuntu 24.04
  1. 1PID виновника
  2. 2%CPU почти 100
  3. 3цепочка: systemd → терминал → bash → процесс
  4. 4текущий каталог процесса — /tmp
  5. 5запущен в 06:56:55, работает 17 секунд
Самый загруженный процесс, его предки, каталог и время запуска.Весь снимок ↗

Самый загруженный процесс, его предки, каталог и время запуска.

Что показывает снимок. Первым по загрузке стоит bash -c с 99,8 %. Цепочка pstree ведёт от systemd через gnome-terminal и оболочку bash 3455 к процессу 23227. Текущий каталог процесса — /tmp, запущен он в 06:56:55.

Где это пригодится. По цепочке родителей видно, чей процесс: запущен из терминала — его владельца можно спросить; запущен службой — смотрят настройки службы.

3.3 Если процессов много

Программа часто состоит из родителя и нескольких потомков, которые и делают работу. Тогда в списке ps окажется несколько похожих строк с одним PPID. Их общий родитель виден в столбце ppid или в дереве pstree -p.

Всем потомкам сразу можно послать сигнал командой pkill -P PPID, а найти их — pgrep -P PPID. Если завершить только родителя, потомки продолжают работу: их усыновляет PID 1 или процесс-приёмник сеанса, и нагрузка остаётся прежней.

Итоги части 3

  • ps -eo поля --sort=-%cpu | head — самые загруженные процессы; --sort=-rss — самые большие по памяти.
  • pstree -s -p PID показывает, кто запустил процесс.
  • /proc/PID/cwd — где процесс работает, ps -o lstart,etime — когда запущен.
  • Завершение родителя не завершает потомков: их находят через pgrep -P.

В отчётСнимок поиска: подпишите PID виновника, цепочку его родителей и текущий каталог.

Открыть в отдельной вкладке ↗