Процессы и сигналы в Linux
Процесс — выполняющийся экземпляр программы. У него есть идентификатор PID, родительский процесс PPID, владелец, состояние, приоритет, открытые файлы и лимиты ресурсов. Ядро Linux планирует выполнение процессов и распределяет между ними ресурсы.
echo $$ # PID текущего shell
echo $! # PID последней фоновой команды
echo $? # код завершения последней командыPID, PPID и дерево процессов
PID (Process ID) — идентификатор процесса в работающей системе. После завершения процесса его PID позднее может быть использован повторно.
PPID (Parent Process ID) — PID процесса, создавшего текущий процесс.
ps -o pid,ppid,user,stat,comm -p 1234На большинстве современных систем процесс с PID 1 — менеджер инициализации, обычно systemd. Он запускает службы и принимает осиротевшие процессы.
Показать дерево процессов:
ps -ef --forest
ps axjf
pstree -p
pstree -ps 1234 # цепочка предков процессаpstree может устанавливаться отдельным пакетом, часто psmisc.
Состояния процессов
| Код | Состояние |
|---|---|
R |
выполняется или готов к выполнению |
S |
прерываемый сон, ожидание события |
D |
непрерываемое ожидание, часто ввод-вывод |
T |
остановлен сигналом или отладчиком |
Z |
zombie: завершён, но родитель ещё не получил статус |
I |
неактивный поток ядра |
В STAT встречаются дополнительные признаки: N — пониженный приоритет, < — высокий приоритет, s — лидер сеанса, l — многопоточный процесс, + — участник foreground-группы терминала.
Zombie-процесс уже не выполняет код. Посылать ему SIGKILL бессмысленно: родитель должен прочитать статус завершения дочернего процесса.
Просмотр процессов: ps
ps показывает снимок процессов на момент запуска.
ps # процессы текущего терминала
ps aux # все процессы, BSD-формат
ps -ef # все процессы, UNIX-форматНастраиваемый вывод:
ps -eo pid,ppid,user,%cpu,%mem,stat,etime,comm,args| Поле | Значение |
|---|---|
%CPU |
использование процессора |
%MEM |
доля оперативной памяти |
RSS |
резидентная память в KiB |
VSZ |
виртуальная память в KiB |
STAT |
состояние процесса |
ETIME |
время с момента запуска |
COMM |
краткое имя команды |
ARGS |
команда с аргументами |
Сортировка по CPU и памяти:
ps -eo pid,user,%cpu,%mem,comm --sort=-%cpu | head
ps -eo pid,user,%mem,rss,comm --sort=-%mem | headПоиск процессов:
ps aux | grep '[n]ginx'
pgrep nginx
pgrep -a nginx
pgrep -u username -a pythonДля сценариев pgrep обычно надёжнее, чем разбор ps | grep. Полная командная строка может содержать пароли или токены, поэтому её нельзя бездумно записывать в журналы.
Просмотр потоков:
ps -eLf
ps -L -p 1234 -o pid,tid,psr,stat,commИнтерактивный просмотр: top и htop
top
top
top -p 1234 # один процесс
top -d 2 # обновление каждые 2 секундыПолезные клавиши внутри top:
| Клавиша | Действие |
|---|---|
P |
сортировка по CPU |
M |
сортировка по памяти |
T |
сортировка по процессорному времени |
1 |
статистика отдельно по логическим CPU |
H |
показать потоки |
k |
отправить сигнал |
r |
изменить nice |
u |
фильтр по пользователю |
c |
полная командная строка |
q |
выход |
Load average — среднее число выполняющихся или ожидающих ресурсы задач за 1, 5 и 15 минут. Значения нужно сопоставлять с количеством CPU и характером нагрузки.
Поля CPU: us — пользовательский код, sy — ядро, ni — задачи с изменённым nice, id — простой, wa — ожидание ввода-вывода, st — время, отнятое гипервизором.
htop
htop — интерактивная альтернатива с удобной навигацией:
htopПолезные клавиши: F3 — поиск, F4 — фильтр, F5 — дерево, F6 — сортировка, F9 — сигнал, F10 — выход. Программа может устанавливаться отдельным пакетом.
jobs: задания текущего shell
Задание (job) — процесс или пайплайн, запущенный интерактивным shell. Номер задания %1 не равен PID.
jobs
jobs -l # вместе с PIDjobs показывает только задания текущего shell, а не все процессы системы.
Foreground и background
Foreground-процесс работает на переднем плане, получает ввод с терминала и занимает приглашение shell:
long_commandЗапуск в фоне:
long_command &Временно остановить foreground-задание можно через Ctrl+Z. Затем:
bg %1 # продолжить в фоне
fg %1 # вернуть на передний планОстановить и продолжить задание сигналами:
kill -STOP %1
kill -CONT %1Пайплайн обычно образует группу процессов. Сигналы терминала, например Ctrl+C, отправляются foreground-группе, поэтому могут затронуть весь пайплайн.
nohup и работа после закрытия терминала
nohup запускает команду с игнорированием SIGHUP:
nohup long_command >app.log 2>&1 &
echo $!Без явного перенаправления вывод обычно попадает в nohup.out.
В Bash уже запущенное задание можно удалить из таблицы заданий:
long_command &
disown %1nohup не перезапускает программу после сбоя и не делает её полноценной службой. Для постоянных сервисов лучше использовать systemd, а для длительной интерактивной работы — tmux или screen.
Сигналы
Сигнал — асинхронное уведомление процессу. Он может запросить завершение, остановку, продолжение или перечитывание конфигурации.
kill -l # список сигналов
kill -l TERM # номер сигнала| Сигнал | Типичный номер | Назначение |
|---|---|---|
SIGHUP |
1 |
разрыв терминала; часто перечитывание конфигурации |
SIGINT |
2 |
прерывание, обычно Ctrl+C |
SIGQUIT |
3 |
завершение, возможно с core dump |
SIGKILL |
9 |
безусловное завершение |
SIGTERM |
15 |
корректный запрос на завершение |
SIGCONT |
18 |
продолжить процесс |
SIGSTOP |
19 |
безусловно остановить процесс |
SIGTSTP |
20 |
интерактивная остановка, обычно Ctrl+Z |
Номера части сигналов зависят от архитектуры, поэтому в командах понятнее использовать имена.
SIGTERM
kill -TERM 1234
kill 1234 # TERM по умолчаниюПроцесс может обработать SIGTERM: завершить операции, закрыть файлы и сохранить состояние. Это основной способ запросить корректное завершение.
SIGKILL
kill -KILL 1234
kill -9 1234SIGKILL нельзя перехватить или игнорировать. Процесс не успевает очистить ресурсы, поэтому возможны потеря данных и незавершённые транзакции. Использовать только после неудачного SIGTERM.
Если процесс находится в состоянии D, даже SIGKILL обычно будет обработан только после завершения непрерываемой операции ввода-вывода.
SIGHUP
kill -HUP 1234Многие демоны используют SIGHUP для перечитывания конфигурации, но это не универсальное правило. Нужно проверить документацию программы.
Сигнал 0 ничего не отправляет, но проверяет существование процесса и права:
kill -0 1234kill, killall и pkill
kill работает с PID или номером задания:
kill -TERM 1234
kill -TERM 1234 5678
kill -TERM %1Обычный пользователь может сигнализировать своим процессам. Для чужих нужны дополнительные права.
killall выбирает процессы по имени:
killall -TERM nginx
killall -u username process_nameКоманда способна затронуть несколько процессов. Её поведение различается между ОС; здесь имеется в виду распространённая Linux-версия.
pkill использует правила поиска, аналогичные pgrep:
pkill -TERM nginx
pkill -HUP -u username process_nameПоиск по полной командной строке:
pgrep -af 'python.*worker.py'
pkill -TERM -f 'python.*worker.py'Перед killall или pkill -f нужно проверить совпадения через pgrep -a или pgrep -af, иначе можно завершить лишние процессы.
Безопасная последовательность:
pgrep -a process_name
kill -TERM PID
ps -p PID -o pid,stat,etime,cmd
# Только при необходимости:
kill -KILL PIDДля службы предпочтительнее её штатный менеджер:
sudo systemctl stop service-name
sudo systemctl reload service-nameПриоритеты: nice и renice
Nice-значение обычно находится в диапазоне от -20 до 19:
-20 — более высокий приоритет
0 — стандартное значение
19 — более низкий приоритетЧем больше значение, тем процесс «вежливее» к другим. Nice влияет на относительный приоритет CPU, но не задаёт жёсткую долю процессорного времени и не ограничивает память.
Запустить команду с nice 10:
nice -n 10 long_command
nice -n 15 long_command >app.log 2>&1 &Обычный пользователь может понижать приоритет своих процессов. Для повышения приоритета обычно нужны привилегии:
sudo nice -n -5 important_commandИзменить nice работающего процесса:
renice -n 10 -p 1234
sudo renice -n 10 -u usernameПроверить:
ps -o pid,ni,pri,stat,comm -p 1234Для настоящего ограничения CPU и памяти применяют cgroups и параметры systemd.
Файловая система /proc
/proc — виртуальная файловая система, создаваемая ядром в памяти. Каталог /proc/PID содержит сведения о процессе.
| Путь | Содержимое |
|---|---|
/proc/PID/status |
текстовая сводка |
/proc/PID/cmdline |
аргументы, разделённые нулевыми байтами |
/proc/PID/environ |
окружение, разделённое нулевыми байтами |
/proc/PID/exe |
ссылка на исполняемый файл |
/proc/PID/cwd |
рабочий каталог |
/proc/PID/fd/ |
открытые файловые дескрипторы |
/proc/PID/maps |
отображения виртуальной памяти |
/proc/PID/limits |
лимиты ресурсов |
/proc/PID/task/ |
потоки процесса |
cat /proc/1234/status
readlink -f /proc/1234/exe
readlink -f /proc/1234/cwd
ls -l /proc/1234/fd
cat /proc/1234/limits
tr '\0' ' ' </proc/1234/cmdline; echoОкружение можно вывести командой:
tr '\0' '\n' </proc/1234/environОно может содержать пароли, ключи и токены. Не следует без необходимости выводить его или сохранять в журнал.
Общесистемные файлы:
| Путь | Содержимое |
|---|---|
/proc/cpuinfo |
сведения о CPU |
/proc/meminfo |
статистика памяти |
/proc/loadavg |
нагрузка и число задач |
/proc/uptime |
время работы системы |
/proc/mounts |
точки монтирования |
/proc/sys/ |
параметры ядра |
Параметры /proc/sys удобнее читать через sysctl:
sysctl kernel.pid_maxДоступ к данным чужих процессов может ограничиваться правами, параметром hidepid, модулями безопасности и пространствами имён контейнеров.
Ограничение ресурсов: ulimit
ulimit — встроенная команда shell. Она изменяет лимиты текущего shell и процессов, которые он запустит позднее.
ulimit -a # все лимиты
ulimit -Sa # soft limits
ulimit -Ha # hard limitsSoft limit — текущий рабочий предел. Hard limit — верхняя граница для soft limit. Обычный пользователь может менять soft limit в пределах hard limit; повышение hard limit требует привилегий.
Частые опции Bash:
| Опция | Ресурс |
|---|---|
-n |
открытые файловые дескрипторы |
-u |
пользовательские процессы или задачи |
-c |
размер core dump |
-f |
размер создаваемого файла |
-s |
размер стека |
-t |
процессорное время |
-v |
виртуальная память |
-l |
блокируемая память |
ulimit -n # текущий лимит файлов
ulimit -Sn 4096 # новый soft limit
ulimit -c 0 # запрет core dumpЗапуск программы с лимитом без изменения родительского shell:
(
ulimit -n 1024
exec application
)Core dump может содержать секретные данные из памяти процесса, поэтому требует строгого контроля доступа.
Постоянные пользовательские лимиты в PAM-окружении часто задают в /etc/security/limits.conf и /etc/security/limits.d/*.conf:
username soft nofile 4096
username hard nofile 8192Для служб systemd применяют параметры unit-файла:
[Service]
LimitNOFILE=8192После изменения unit-файла:
sudo systemctl daemon-reload
sudo systemctl restart service-nameulimit не заменяет cgroups. Для служб лимиты CPU, памяти и задач обычно задают параметрами CPUQuota=, MemoryMax= и TasksMax=.
Практические сценарии
Найти процессы пользователя:
ps -u username -o pid,ppid,stat,%cpu,%mem,etime,comm
pgrep -u username -aПроцессы с наибольшим потреблением ресурсов:
ps -eo pid,user,%mem,rss,comm --sort=-rss | head -n 11
ps -eo pid,user,%cpu,etime,comm --sort=-%cpu | head -n 11Запустить длительную команду и наблюдать за журналом:
nohup command >command.log 2>&1 &
pid=$!
echo "PID: $pid"
tail -F command.logУзнать открытые файлы и рабочий каталог:
ls -l /proc/1234/fd
readlink -f /proc/1234/cwd
readlink -f /proc/1234/exeЕсли установлена lsof:
lsof -p 1234Диагностика процесса в состоянии D:
ps -o pid,ppid,stat,wchan:32,comm -p 1234
sudo cat /proc/1234/stackТакое состояние часто связано с диском, сетевой файловой системой, устройством или драйвером. Принудительное завершение обычно не устраняет причину ожидания.
Типичные ошибки
Сразу использовать kill -9
Сначала применяйте штатную остановку или SIGTERM. SIGKILL оставляйте на крайний случай.
Использовать слишком широкий pkill -f
Сначала проверяйте тот же шаблон через pgrep -af.
Искать все процессы через jobs
jobs видит только задания текущего shell. Для системы нужны ps, pgrep, top или htop.
Полагаться на простой command &
Фоновый процесс не обязательно переживёт закрытие сеанса. Используйте nohup, tmux, планировщик либо службу systemd.
Считать nice жёстким лимитом
Nice задаёт относительный приоритет CPU. Для реальных ограничений применяйте cgroups.
Менять ulimit не в том окружении
Лимиты наследуются дочерними процессами. Изменение в одном терминале не повлияет на уже запущенную службу или другой сеанс.
Краткая памятка
| Задача | Команда |
|---|---|
| Все процессы | ps aux или ps -ef |
| Выбранные поля | ps -eo pid,ppid,user,stat,%cpu,%mem,comm |
| Найти процесс | pgrep -a name |
| Дерево процессов | ps -ef --forest или pstree -p |
| Мониторинг | top или htop |
| Задания shell | jobs -l |
| Запустить в фоне | command & |
| Остановить временно | Ctrl+Z |
| Продолжить в фоне | bg %1 |
| Вернуть на передний план | fg %1 |
| Пережить закрытие терминала | nohup command >log 2>&1 & |
| Корректно завершить | kill -TERM PID |
| Принудительно завершить | kill -KILL PID |
| Перечитать конфигурацию | kill -HUP PID |
| Список сигналов | kill -l |
| Запустить с nice | nice -n 10 command |
| Изменить nice | renice -n 10 -p PID |
| Сведения о процессе | cat /proc/PID/status |
| Лимиты shell | ulimit -a |
| Лимиты процесса | cat /proc/PID/limits |
Рекомендации по безопасной работе
Перед отправкой сигнала проверяйте PID, владельца и полную команду процесса. Службами управляйте через systemctl, заданиями shell — через jobs, fg и bg.
Сначала используйте штатный механизм приложения или SIGTERM. Применяйте SIGKILL, только если корректное завершение не сработало и последствия понятны.
Не публикуйте содержимое /proc/PID/environ и полные командные строки: они могут содержать секреты. Для постоянных процессов используйте менеджер служб; nohup не заменяет мониторинг, автоматический перезапуск и управление журналами.