pgrep и pkill
Найти процессы по имени или командной строке и отправить им сигнал без ps | grep
pgrep ищет процессы по шаблону и печатает их PID. pkill принимает те же условия, но вместо печати отправляет найденным процессам сигнал (по умолчанию TERM). Обе команды заменяют связку ps aux | grep … | awk … | xargs kill и не находят сами себя.
Синтаксис
pgrep [опции] шаблон
pkill [-сигнал] [опции] шаблон
Шаблон — расширенное регулярное выражение (ERE), и по умолчанию он ищется как подстрока в имени процесса (comm, до 15 символов). С -f — во всей командной строке.
Код возврата: 0 — что-то найдено, 1 — ничего, 2 — ошибка в опциях.
Как сопоставлять
| Опция | Что делает |
|---|---|
| (без опций) | шаблон ищется в имени процесса: pgrep ssh найдёт и sshd, и ssh-agent |
-x | имя должно совпасть целиком: pgrep -x sshd |
-f | искать в полной командной строке (с аргументами и путями) |
-i | без учёта регистра |
-v | инвертировать: все процессы, которые не подходят |
Фильтры
| Опция | Что выбирает |
|---|---|
-u пользователь | по эффективному пользователю (имя или UID, через запятую) |
-U пользователь | по реальному пользователю |
-G группа | по реальной группе |
-P PPID | только дети указанного процесса |
-g PGID / -s SID | по группе процессов / сессии |
-t pts/0 | по терминалу |
-r S,D | по состоянию (R, S, D, Z, T — как в ps) |
-n / -o | только самый новый / самый старый из найденных |
-O сек | только процессы старше указанного числа секунд |
-F файл | взять PID из PID-файла |
-A | исключить своих предков (оболочку, из которой запущен pgrep) |
Вывод pgrep
| Опция | Что печатает |
|---|---|
| (без опций) | PID по одному на строку |
-l | PID и имя |
-a | PID и полную командную строку |
-c | только количество |
-d , | разделитель вместо перевода строки: 12,34,56 |
-w | идентификаторы потоков (TID) вместо PID |
Опции pkill
| Опция | Что делает |
|---|---|
-HUP, -9, --signal TERM | какой сигнал отправить |
-e | печатать каждый процесс, которому отправлен сигнал: … killed (pid 42) |
-c | напечатать, скольким процессам отправлен сигнал |
все фильтры pgrep | -f, -x, -u, -P, -n, -o… |
Примеры
# PID процессов с именем ровно nginx
pgrep -x nginx
# с полными командными строками
pgrep -a python3
# по аргументам: процесс, запущенный с конкретным конфигом
pgrep -af 'worker --queue=mail'
# сколько процессов у пользователя
pgrep -c -u www-data
# самый новый процесс ssh
pgrep -n -x sshd
# PID через запятую — для ps -p
ps -o pid,etime,cmd -p "$(pgrep -d, -x cron)"
# запущен ли процесс — в условии
if pgrep -x cron >/dev/null; then echo "cron работает"; fi
# остановленные (T) процессы
pgrep -a -r T
# перечитать конфиг всем процессам по имени
pkill -HUP -x nginx
# завершить процессы пользователя и показать, кого
pkill -e -u alice
# убить по командной строке
pkill -f 'sleep 1000'
Самосовпадение -f и трюк со скобками
pgrep -f смотрит на командные строки всех процессов. Если pgrep запущен из bash -c '…' (или из скрипта), строка этой оболочки тоже содержит шаблон — и pgrep найдёт её. Сам себя pgrep исключает, свою родительскую оболочку — нет:
bash -c "pgrep -af 'sleep 777'; true"
# 9 bash -c pgrep -af 'sleep 777'; true ← процесса sleep 777 нет, а «нашёлся»
Так проверка «процесс запущен» всегда успешна, а «процесс остановлен» — всегда проваливается. Лечится квадратными скобками в шаблоне:
pgrep -f '[s]leep 777'
Регулярка [s]leep совпадает со строкой sleep, но в командной строке оболочки записано [s]leep — сама с собой она уже не совпадает. Тот же приём работает с ps aux | grep '[n]ginx'. Другой вариант — pgrep -A, который пропускает всех предков pgrep.
Подводные камни
- Имя процесса — не больше 15 символов.
pgrep averyverylongname_sleeperничего не найдёт (и предупредит об этом). Используй-fили первые 15 символов. - Без
-xшаблон — подстрока.pkill sshубьёт иsshd, и твою собственную ssh-сессию. Дляpkillпочти всегда добавляй-xили точный-f. - Шаблон — регулярка. Точка значит «любой символ»,
+и(— спецсимволы.pgrep -f 'app.py'найдёт иappXpy. -fсовпадает и с чужими строками: редактор, открывший файлworker.conf, найдётся по шаблонуworker. Делай шаблон конкретнее.- Самосовпадение с оболочкой — см. выше: в скриптах и
bash -cс несколькими командами используй[x]yzили-A. pkillбез сигнала шлётTERM, а неKILL. Процесс может его перехватить и не завершиться.