Зачем нужен pgrep, если есть ps и grep
Связка ps aux | grep имя решает ту же задачу, но требует фильтровать собственную строку grep и разбирать столбцы. Утилита pgrep (process grep) сокращает это до одной команды: она сама ищет среди процессов и печатает только их номера, по одному на строку. Это удобно и при ручной проверке, и в скриптах, где вывод идёт дальше в другую команду.
Минимальный пример: pgrep sshd выведет номера процессов, имя которых содержит sshd. Совпадение по умолчанию ищется как регулярное выражение в имени процесса, поэтому подстрока тоже подходит. Утилита не включает в результат саму себя, и это одна из причин, по которым с ней проще, чем с grep.
pgrep есть в современных Linux-системах в пакете procps и в macOS. Набор ключей в основном совпадает, но отдельные варианты различаются: например, -c есть в Linux, а ключ -a в macOS означает совсем другое (включать в список предков процесса), поэтому перед использованием проверьте man pgrep своей системы.
Ключи, которые чаще всего нужны
Базовый набор помогает почти во всех бытовых задачах.
| Ключ | Что делает | Замечание |
|---|---|---|
| -l | печатает рядом с PID имя процесса | есть в Linux и macOS |
| -a | в Linux печатает PID и полную командную строку | в macOS ключ -a значит другое, смотрите man pgrep |
| -f | ищет по всей командной строке, а не по имени | полезно для интерпретаторов |
| -x | требует точного совпадения имени | исключает случайные подстроки |
| -u user | только процессы указанного пользователя | имя подставьте своё |
| -n | оставляет только новейший по времени запуска подходящий процесс | выбор одного из нескольких |
| -o | оставляет только старейший подходящий процесс | выбор одного из нескольких |
| -c | выводит количество совпадений | в Linux |
Ключ -f нужен, когда программа запущена через интерпретатор. Например, скрипт на Python в списке процессов называется python, и по имени отличить его от других нельзя. С -f шаблон применяется к строке запуска, где есть имя скрипта. Но чем шире поиск, тем выше риск захватить лишнее, поэтому формулируйте шаблон как можно точнее и проверяйте вывод через -l или -a.
pgrep в скриптах: код возврата и пустой результат
Если найден хотя бы один процесс, pgrep завершается с кодом 0, а если ничего не найдено, с кодом 1. Благодаря этому его удобно ставить в условие.
Пример проверки в сценарии оболочки: if pgrep -x nginx > /dev/null; then echo "работает"; fi. Вывод перенаправляется в /dev/null, потому что нам важен только код возврата.
Две типичные ошибки. Первая: использовать pgrep без -x и получить совпадение по подстроке, например имя nginx совпадёт и с процессом, в имени которого есть nginx-helper. Вторая: подставлять результат в команду без проверки. Если pgrep ничего не нашёл, подстановка $(pgrep ...) даст пустую строку, и последующая команда выполнится без аргументов, что бывает опасно. Проверяйте результат или используйте условие.
В Linux имя процесса, по которому ищет pgrep без -f, ограничено 15 символами. Длинные имена обрезаются, поэтому точное имя из 20 символов не найдётся через -x. В таких случаях помогает -f. Для macOS этот нюанс проверяйте на своей версии.
pkill: та же выборка, но с сигналом
Утилита pkill использует те же правила отбора, что pgrep, но вместо печати номеров отправляет процессам сигнал. По умолчанию это TERM, то есть вежливая просьба завершиться. Конкретный сигнал задаётся ключом: pkill -HUP имя, pkill -KILL имя.
Прежде чем запускать pkill, выполните ту же команду с pgrep -l. Так вы увидите, кого заденет шаблон. Особенно осторожно относитесь к -f и к коротким шаблонам вроде «py» или «ssh»: под них подходят процессы, которые вы не имели в виду.
Для тренировки запустите безобидный фоновый процесс с уникальным аргументом: sleep 301 &. Затем выполните pgrep -fl 'sleep 301' и убедитесь, что в списке только он, и лишь после этого pkill -f 'sleep 301'. Так вы отработаете порядок «проверить, затем завершить» без риска для рабочих программ.
Три практических правила:
- Сначала pgrep -l с тем же шаблоном, потом pkill.
- Сужайте выбор ключами -x и -u, если это возможно.
- Начинайте с обычного TERM, принудительный KILL оставляйте на случай, когда процесс не реагирует. Подробнее о порядке завершения на странице kill и top.
На общих серверах с несколькими пользователями pkill от имени обычного пользователя затрагивает только его собственные процессы, а от администратора любые. Поэтому команда pkill от sudo с широким шаблоном заслуживает отдельной внимательности.
Когда pgrep не подходит
Если процесс запущен как служба, для её управления лучше пользоваться менеджером служб, а не pgrep. Он знает, как корректно остановить и перезапустить, и что делать с дочерними процессами. pgrep полезен для проверки наличия и для разовых действий.
Другое ограничение: pgrep ищет по именам и командным строкам, а не по ресурсам. Чтобы выбрать процессы с высокой нагрузкой, используйте ps aux с сортировкой по CPU или памяти. А если нужно найти процесс по порту или по открытому файлу, воспользуйтесь lsof или ss.
На macOS с включёнными ограничениями доступа к некоторым системным процессам информация может быть неполной для обычного пользователя. В контейнерах pgrep видит только процессы своего пространства имён, и это нормальное поведение изоляции.
Если результат вас удивляет, сопоставьте его с ps -eo pid,ppid,etime,comm: так вы увидите родителя и время работы и поймёте, что именно нашёл шаблон.
Проверка перед действием
Прежде чем завершать что-либо по шаблону, пройдите короткую проверку.
- Запустите pgrep -l с тем же шаблоном и посмотрите, кого он выбирает.
- Если список шире ожидаемого, добавьте ключ -x или -u.
- Для интерпретаторов используйте -f, но проверяйте результат через -a в Linux.
- Определите, не управляется ли процесс менеджером служб, и тогда работайте через него.
- Начните с TERM и подождите, прежде чем применять KILL.
Эта дисциплина кажется лишней в одной команде, но на общем сервере она спасает от случайного завершения чужой работы.