惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
aimingoo的专栏
aimingoo的专栏
IT之家
IT之家
N
Netflix TechBlog - Medium
MyScale Blog
MyScale Blog
雷峰网
雷峰网
T
Tailwind CSS Blog
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
T
The Blog of Author Tim Ferriss
S
Schneier on Security
C
CERT Recently Published Vulnerability Notes
Help Net Security
Help Net Security
云风的 BLOG
云风的 BLOG
GbyAI
GbyAI
I
InfoQ
H
Help Net Security
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
酷 壳 – CoolShell
酷 壳 – CoolShell
G
GRAHAM CLULEY
Blog — PlanetScale
Blog — PlanetScale
G
Google Developers Blog
I
Intezer
大猫的无限游戏
大猫的无限游戏
AWS News Blog
AWS News Blog
Recent Announcements
Recent Announcements
Google DeepMind News
Google DeepMind News
Spread Privacy
Spread Privacy
博客园_首页
宝玉的分享
宝玉的分享
量子位
T
Threatpost
D
Darknet – Hacking Tools, Hacker News & Cyber Security
Security Latest
Security Latest
C
Cybersecurity and Infrastructure Security Agency CISA
SecWiki News
SecWiki News
H
Hackread – Cybersecurity News, Data Breaches, AI and More
博客园 - Franky
C
CXSECURITY Database RSS Feed - CXSecurity.com
T
The Exploit Database - CXSecurity.com
T
Tenable Blog
Know Your Adversary
Know Your Adversary
P
Proofpoint News Feed
The Register - Security
The Register - Security
V2EX - 技术
V2EX - 技术
Recent Commits to openclaw:main
Recent Commits to openclaw:main
Last Week in AI
Last Week in AI
L
LangChain Blog
T
Tor Project blog
Stack Overflow Blog
Stack Overflow Blog
月光博客
月光博客

Все публикации подряд на Хабре

Ловим музу за клавиатуру: как айтишнику стать автором Что умеет Midjourney в 2026? Мой немного грустный разбор этого шикарного инструмента Никто не любит писать тесты, но ИИ может исправить это IPv8 выглядит как мечта. Поэтому почти наверняка не взлетит Производители вернули в продажу материнки с DDR3. Что происходит? Управление агентом с телефона через Telegram теперь в KodaCode От координации к лидерству: как меняется роль руководителя разработки Я сделала родителям бизнес вместо пенсии: зарабатываем 70 тысяч, мама не даёт продать В три раза быстрее приемка товара и оптимизация трудозатрат на 73%: как «РСТ-Инвент» помог Gulliver Group ИИ-шечный мир победил? О влиянии искусственного интеллекта на игропром Кремль снижает давление на Телеграмм пока Европа строит интернет по паспорту Как CEO, CTO и CIO за 8 часов собрали ИИ-директора, который умеет держать позицию под давлением Как (не) потерять домен за выходные Вместо 8 разных VPS: как я организовал практику студентам на одном сервере Почему твой Open Source проект не замечают? R&D: искусство управления неопределенностью в разработке AI-дефляция: вакансий для разработчиков больше, а рост зарплат — худший за 15 лет Мы отдали управление роботами OpenClaw. Что из этого вышло Галактический ID: система идентификации для всех форм разумной жизни Шесть основ бизнес-анализа: начинаем с вопроса «Кто в игре?» Код-ревью, в котором дело не в коде Данные переехали. Команда — нет Системной подход к сдаче OSWE в 2025 Почему комната управления реактором покрашена в цвет морской пены 4 YAML-файла вместо PySpark: как аналитикам строить пайплайны без разработчиков LLM-агент для поиска свободных доменов: автоматизируем подбор Когда, зачем и как правильно начинать новую сессию в Claude Code? Как я заставил нейросеть писать макросы для FreeCAD Анатомия ИИ‑агента для подбора персонала. От тысячи резюме к топ‑10 за минуты Опыт разработчика как экономика внимания Автономность как точка невозврата: кто будет субъектом в цифровом будущем Обучение ИИ в «диких» условиях: как рутинные действия превращаются в датасеты Как измерить LLM для задач кибербеза: обзор открытых бенчмарков Где хранить код? Сравнение GitHub, GitLab и Bitbucket Математика объясняет, почему нормальное распределение встречается повсюду Почему ваш FinOps не работает: 12 тезисов от практиков Как подписать проектную документацию УКЭП с использованием бесплатных лицензий Pilot Адаптивное администрирование Sigla Vision Я грузил уран в бочки, а потом 20 лет строил ИТ в атомной отрасли Чем позвонить с Эвереста? История и обзор спутниковой связи. Часть 2 Как языковая модель помогает контролировать качество инструктажей по охране труда в металлургии Как не передать на desktop свой IP в РКН Анатомия SAP Privileges: как устроено управление правами в macOS MoneyDev: Сказка про три главных слова Обновлённый токенизатор видео K-VAE 2.0 от Сбера Как сделать диспетчеризацию дома на 1284 квартиры почти бесплатно Как мы разогнали железную дорогу Мы дали агентам рутину. Теперь надо решить — что делать с освободившимся временем Токсичный контент, промпт-хакинг и защита ИИ — всё о Guardrails для LLM Умный город начинается с точного взгляда: как «Фалькон Тех» меняет пространство к лучшему Навайбкодил приложение для анализа графов Почему Дюну так интересно читать? Упрощаем работу с рутиной или как стать Гендальфом Белым Деконструкция Go: CPU, RAM и что там происходит. Go Assembler база. Часть 1.1 Какие профессии исчезнут из-за ИИ, а какие появятся? И что с этим делать Как мы построили IT-отдел, где хочется расти: архитектурные встречи, прозрачные метрики и книжные подарки Rufler: Делаем из Claude Code автономный рой через один YAML-конфиг Sing-box и белый список приложений Как построить надёжный обмен сообщениями в микросервисах: лучшие практики для enterprise OpenAI строит MLM-пирамиду, а McKinsey и Accenture помогают ей в этом Дом, который не построил Фишер (Часть 2) «Сверхзвуковой математик» против «Вдумчивого логиста»: битва алгоритмов 3D-упаковки Мультимодальные модели – грубый и дорогой инструмент Разговоры ничего не стоят. Код тоже Проверки физических лиц: с кого начнет ФНС Топ-10 бесплатных нейросетей для создания видео в 2026 году Первые слои кода: как наши решения сегодня определяют архитектуру ИИ на десятилетия Разработка нового статического анализатора: PVS-Studio JavaScript Поиск уязвимостей ПО: базовый минимум или роскошный максимум Почему оценка персонала не работает как инструмент управления Как мы разработали ИИ-ассистента и сократили рутину продуктовой команды на 50% Как я ушел из найма, нажарил косточек и продал на маркетплейсах на 168 млн в год Когда 1С:ERP уже внедрена, а нормального производственного плана всё ещё нет Как я сделал Claude мультимодальным, подключив к нему Qwen Omni Как приглашение на вакансию мечты превращается в атаку Infrastructure as Code: философия и лучшие практики IaC Тестируем Yandex Code Assistant на задаче, в которой нужно хранить секреты nxs-universal-chart v3.0: новое поколение универсального Helm-чарта Callback Injection: Техника, которая отправила Microsoft Defender в глухой нокаут «Все идеи на стол»: митап как способ вывести проект из тупика Сегодня я узнал нечто новое о GPU благодаря багу в своей игре Как заставить LLM ̶ ̶г̶а̶л̶л̶ю̶ ̶ эволюционировать Карта событий как фундамент аналитики: практический кейс для E-commerce Что выбрать для AI: x86, ARM или RISC-V? Дайджест железа за март Роль соматических мутаций в развитии аутоиммунных заболеваний: путь к избирательной терапии Mythos от Anthropic — тревожный сигнал для всех, а не только для банков Guardrails для LLM на Java: как приручить промпт‑инъекции и токсичные ответы Green-VLA: как мы собрали VLA-модель для реального антропоморфного робота и не потеряли обобщение Финансовая гонка вооружений: почему умные люди добровольно в ней участвуют Эра ИИ-агентов наступила: выбираем лучшего цифрового сотрудника # Практический опыт внедрения WinCC Redundancy на производственном предприятии Сделал MVP за 3 дня, а потом неделю прикручивал оплату. Оно того стоило? Физика против Маска: почему Starship V3 может оказаться ещё одной катастрофой Нефть Венесуэлы: крупнейшие запасы в мире, но не крупнейшая нефтяная держава JPA 4. Переосмысление Hibernate Почему зеркальная фотокамера Nikon D5 десятилетней давности идеально подошла для миссии «Артемида-2» Проект «Уровень-Спутник» или как мы сделали платформу для гидрологов «Замедлиться, чтобы ускориться»: почему ИИ повышает цену ошибок в требованиях и архитектуре Как с нуля поднять трафик IT-компании на 1657% при бюджете 55 тыс. и выжить Pixel-perfect Downsampling — идеальная отрисовка 50 миллионов точек без потерь
Linux: Процессы
opensophy · 2026-06-02 · via Все публикации подряд на Хабре

Средний

11 мин

19K

1. Введение

Продолжаем серию о Linux. В прошлой части разбирали права доступа, а теперь переходим к одной из самых важных тем в Linux — процессам. Любая программа в системе в конечном итоге существует как процесс: nginx, postgres, docker, sshd, systemd, ваш shell и даже потоки ядра. Понимание того, как процессы создаются, живут, взаимодействуют с ядром и завершаются, — это база для понимания и диагностики Linux-систем. Цель этой статьи — рассказать кратко и простым языком всю нужную информацию как для начинающих, так и для опытных пользователей и админов, чтобы освежить знания. Важно: для практики, если обучаетесь, лучше всего использовать виртуалку с Linux.

Серия в основном под Ubuntu/Debian.

2. Что такое процесс и поток

Процесс — это запущенная программа. Когда вы запускаете контейнер nginx, или python app.py, или браузер, ядро Linux создаёт процесс: выделяет ему память, даёт номер (PID) и начинает его выполнять. Пока программа не запущена, это программный файл. Отличается он только наличием доступа x (т. е. возможности исполнения), но, как только вы его запускаете, он становится процессом под управлением ядра Linux.

Про поток (thread) достаточно запомнить, что это задача внутри процесса, разделяющая с ним адресное пространство и файловые дескрипторы. В ядре он представлен той же структурой task_struct, что и процесс, но с флагами CLONE_VM, CLONE_FILES, CLONE_SIGHAND. В утилитах (ps, htop) потоки отображаются как LWP (Light Weight Process) с общим PID и уникальным TID. Сбой в одном потоке затрагивает весь процесс.

У каждого процесса есть своё окружение — набор ресурсов и атрибутов, которые ядро выделяет при создании:

  1. Виртуальная память, где у процесса своё адресное пространство. Он не видит и не может напрямую изменить память другого процесса.

  2. Таблица открытых файлов, через неё процесс работает с файлами, сокетами, пайпами и др. По умолчанию открыты дескрипторы: 0 (stdin), 1 (stdout), 2 (stderr). Остальные процесс открывает сам по мере необходимости.

  3. Каталог (cwd) — директория, в которой процесс сейчас находится. От неё отсчитываются все относительные пути.

  4. Переменные окружения — набор пар ключей (или, по-другому, KEY=VALUE), которые процесс получил от родителя. Через них передают конфиги: PATH, HOME, LANG и другие (к примеру, иногда чувствительные данные: токены, пароли). Меняются до запуска процесса, внутри — только если процесс сам их перезапишет.

  5. UID / GID — идентификаторы пользователя и группы, от имени которых запущен процесс. По ним идёт проверка прав: может ли процесс прочитать файл, открыть порт, выполнить какую-то операцию и т. д.

  6. Код возврата — целое число от 0 до 255, которое процесс возвращает при завершении: 0 = успех, 1–255 = ошибка. Сохраняется в ядре до тех пор, пока родитель не считает его через команду wait() / waitpid(). Если родитель не забирает код, процесс остаётся зомби до очистки.

3. Жизненный цикл: рождение и смерть

Как рождается процесс: в Linux новый процесс создаётся клонированием существующего через команды fork() и exec(). fork() создаёт точную копию родителя с новым PID, а exec() заменяет её память кодом новой программы, сохраняя PID и наследуя ресурсы.

Что наследует дочерний процесс: открытые файловые дескрипторы, переменные окружения, текущий каталог, UID/GID, обработчики сигналов. Не наследует: PID, очередь сигналов и статистику выполнения.

Как умирает процесс: процесс вызывает exit() (т. е. мы сообщаем ядру информацию о том, что программа внутри процесса завершила все свои действия), и, соответственно, освобождаются ресурсы (файлы, память, сокеты), процесс переходит в состояние зомби (Z), ядро отправляет родителю сигнал (SIGCHLD), родитель вызывает wait() и забирает код возврата — зомби удаляется. Если родитель завершается раньше, то дочерний процесс усыновляется systemd (PID 1), который сам выполнит wait() при его завершении.

Когда зомби становится проблемным: по ситуации. Несколько зомби, к примеру, — это норма, если они живут миллисекунды, пока родитель не вызовет wait(). Основная проблема возникает, когда он не вызывает его никогда, из-за чего происходит накопление зомби, исчерпание PID-пространства и т. д. В итоге система перестаёт создавать новые процессы.

В качестве примеров команды:

# Найти зомби
ps aux | awk '$8 == "Z"'

# Найти родителя зомби и «напомнить» ему убраться
kill -CHLD <PPID зомби>

# Если родитель мёртво завис – убить его (дети усыновятся systemd)
kill -TERM <PPID>

4. Состояния процесса

Каждый процесс находится в одном из состояний, отображаемых в колонке STAT (ps aux).

Основные состояния:

Символ

Название

Описание

R

Running

Выполняется или в очереди на CPU.

S

Sleeping

Прерываемое ожидание (ввод, сеть, таймер). Реагирует на сигналы.

D

Uninterruptible sleep

Ожидание I/O, который не прерывается сигналами.

T

Stopped

Процесс приостановлен сигналом SIGSTOP или SIGTSTP (Ctrl+Z). Не выполняется и не потребляет CPU. Можно возобновить через SIGCONT.

Z

Zombie

Завершён, но родитель не забрал код возврата через wait()

I

Idle

Неактивный поток ядра

Модификаторы состояния:

  1. < — высокий приоритет

  2. N — низкий приоритет

  3. s — лидер сессии

  4. l — многопоточный

  5. + — на переднем плане

Пример: Ssl — спит, лидер сессии, многопоточный.

5. Идентификаторы: PID, PPID, UID и другие

PID (Process ID) — уникальный номер процесса, который назначает ядро. Не повторяется, пока не исчерпается диапазон.

PPID (Parent PID) — PID процесса, который создал данный. Каждый процесс (кроме systemd) имеет ровно 1 родителя. При завершении родителя его дочерние процессы переходят под управление systemd (PID 1).

# Посмотреть PID/PPID/Имя процесса
ps -ef | head -10

# Дерево процессов (наглядная иерархия. Рекомедую посмотреть данный пример)
pstree -p

# Максимальный PID в системе 
cat /proc/sys/kernel/pid_max

Особые процессы: PID 1 и PID 2. Эти процессы создаются ядром сразу после загрузки. Они не запускаются пользователем и не появляются через команды как обычные программы. Про PID 1 уже несколько раз упомянули, но всё же стоит отдельно вынести его в терминологию.

PID 1 (systemd) — первый процесс в пользовательском пространстве. От него ведут начало все остальные процессы: от сессий до демонов. Если процесс теряет родителя, PID 1 его усыновляет, забирая коды возврата завершившихся процессов и предотвращая накопление зомби. Убить его нельзя, в основном завершить его можно только через перезагрузку системы.

PID 2 (kthreadd) — прародитель всех потоков ядра. От него создаются системные воркеры (к примеру, kworker). В ps и htop их видно по квадратным скобкам: [kworker/0:0]. Эти процессы работают в пространстве ядра и отвечают за фоновые задачи, такие как обработка прерываний, работа с диском и т. д.

# Увидеть иерархию от systemd
pstree -p | head -20

# Посмотреть потоки ядра (в квадратных скобках)
ps -eo pid,comm | grep '\['

# Проверить родителя у любого процесса
ps -o pid,ppid,comm -p <PID>

6. Сигналы

Сигнал — это асинхронное уведомление процессу от ядра или другого процесса. Процесс может поймать сигнал, проигнорировать его или выполнить действие по умолчанию.

Главные сигналы

Сигнал

Номер

По умолчанию

Когда использовать

SIGTERM

15

Завершить

Первый выбор для остановки, процесс может перехватить и завершиться корректно: сохранить данные, закрыть соединения.

SIGKILL

9

Убить

Крайняя мера. Процесс не успевает сохранить состояние

SIGHUP

1

Завершить

Для демонов (перечитывать к примеру конфиг nginx без перезапуска)

SIGINT

2

Завершить

Прерывание (Ctrl+C)

SIGCONT

18

Приостановить/Продолжить

Возобновить приостановленный процесс

SIGCHLD

17

Игнорировать

Уведомление родителю о завершении дочернего процесса

SIGSTOP

19

Остановить

Приостановить процесс

Наверное, появится вопрос: «Почему SIGKILL — это крайняя мера?» Потому что процесс не успеет завершить свои дела (сохранить данные, записать файлы и т. д.). Поэтому сначала пробуйте SIGTERM.

Что процесс может сделать с сигналом? Поймать, игнорировать, принять действие по умолчанию. Это означает следующие:

  1. Поймать, значит выполнить свой обработчик (например, nginx перечитывает конфиг на SIGHUP).

  2. Игнорировать (ну тут и так понятно).

  3. Принять действие по умолчанию, обычное завершение.

Стоит ещё отметить, что поймать или проигнорировать SIGKILL и SIGSTOP нельзя, т. к. они всегда обрабатываются ядром.

Примеры, как отправить сигнал и завершить процесс.

# По PID
kill -TERM 1234
kill -9 1234           # то же что kill -KILL

# По имени процесса
pkill -TERM nginx
pkill -HUP sshd        # перечитать конфиг

# По полной командной строке
pkill -f "python app.py"

# Всей группе процессов (минус перед номером)
kill -TERM -<PGID>

# Проверить, жив ли процесс (без отправки сигнала)
kill -0 1234 && echo "жив" || echo "мёртв"
PID=1234
TIMEOUT=30

# Шаг 1: попросить завершиться
kill -TERM "$PID"

# Шаг 2: подождать
for i in $(seq 1 $TIMEOUT); do
    kill -0 "$PID" 2>/dev/null || { echo "завершился за ${i}с"; exit 0; }
    sleep 1
done

# Шаг 3: если не вышел – убиваем
echo "не завершился за ${TIMEOUT}с, применяем SIGKILL"
kill -KILL "$PID"

7. /proc — заглянуть внутрь любого процесса

Виртуальная файловая система (/proc) — это интерфейс, через который ядро отдаёт информацию о процессах и системе. Файлы здесь не занимают место на диске: когда, к примеру, мы делаем cat /proc/1234/status, ядро прямо в этот момент формирует текстовый ответ и отдаёт его вам. Здесь лежат данные обо всём: какие процессы запущены, сколько памяти используется и т. д.

Главные файлы /proc/<PID> и другие примеры

# cmdline: командная строка запуска
cat /proc/1/cmdline | tr '\0' ' '

# exe: показывает, какой файл запущен. Если обновили пакет, а процесс не перезагрузили – будет (deleted, означает что этот процесс был запущен, которого больше нет на диске.) 
ls -la /proc/1/exe

# cwd: текущий рабочий каталог процесса.
ls -la /proc/1/cwd

# environ: переменные окружения
tr '\0' '\n' </proc/1/environ

# status: состояние/память/UID/сигналы.
cat /proc/1/status 
# или с выбором нужных строк
cat /proc/1/status | grep -E "Name|State|Uid|VmRSS|Threads"

# wchan: на каком системном вызове процесс ждёт / завис
cat /proc/1/wchan

# stack: стек ядра(требует рут)
sudo cat /proc/1/stack

Файловые дескрипторы

# Cписок открытых дескрипторов
ls -la /proc/1/fd/

# Cколько открыто
ls /proc/1/fd | wc -l

# Cравнить с лимитом
cat /proc/1/limits | grep "open files"

Если число в fd близко к лимиту, возможна утечка. Частая причина ошибки: too many open files.

Память и I/O

# Потребление памяти
cat /proc/1/status | grep -E "VmRSS|VmSize|VmSwap"

# Статистика ввода-вывода
cat /proc/1/io

VmRSS (Resident Set Size) — показатель реального потребления памяти. Разница между rchar и read_bytes показывает, насколько эффективен page cache для этого процесса.

8. Планировщик и приоритеты

Linux делит время CPU между процессами через планировщик CFS (Completely Fair Scheduler). Планировщик решает, кто получает ресурсы и на сколько.

Nice: что это и как работает?

Nice — это атрибут процесса и утилита для его изменения.

Как атрибут: число от -20 до +19, которое хранится в ядре для каждого процесса. По умолчанию стоит 0, но чем меньше значение — тем выше приоритет. Как утилита: nice запускает команду с заданным приоритетом, renice меняет приоритет уже работающего процесса.

Правила Nice и Политика Планировщика

Правила nice довольно простые: уменьшать nice (что означает повышать приоритет) может только root. Обычный пользователь может только увеличивать его (т. е. снижать приоритет): с 0 до 10 — можно, с 0 до -5 — нельзя. Отмечу, что nice влияет только на распределение процессорного времени. Он не даёт гарантий, не резервирует CPU и не работает для real-time задач.

Примеры использования nice

# Запуск команды с низким приоритетом(не будет мешать другим)
nice -n 15 rsync -av /data /backup

# Запустить с высоким приоритетом (root)
sudo nice -n -10 ./service

# Просмотр nice всех процессов (колонка NI)
ps -eo pid,ni,comm | sort -k2 -n | head -20

Теперь про политику планировщика. Если сравнивать, то nice — это мягкое влияние, для более жёсткого контроля есть политики планировщика. Они определяют, как именно процесс конкурирует за CPU.

chrt — утилита для управления политиками планировщика.

Политика

Описание

Когда использовать

SCHED_OTHER

Стандартная, на основе nice. Процессы вытесняют друг друга.

Обычные приложения, демоны, пользовательские задачи.

SCHED_BATCH

Как OTHER, но оптимизирована для пакетной обработки: не мешает интерактивным задачам.

Фоновые расчёты, бэкапы, конвертация видео.

SCHED_IDLE

Самый низкий приоритет. Процесс получает CPU только когда система полностью свободна.

Очень фоновые задачи, которые не должны влиять ни на что.

SCHED_FIFO

Real-time. Процесс выполняется, пока сам не уступит или не завершится. Не вытесняется другими.

Аудио/видео обработка, промышленная автоматизация.

SCHED_RR

Real-time с квантами времени. Процесс выполняется фиксированными отрезками, затем уступает очередь.

Задачи с жёсткими временными рамками, но без риска «зависнуть навсегда».

Приоритет: для real-time политик (FIFO, RR) — число от 1 до 99. Для остальных политик приоритет игнорируется. Будьте осторожны: real-time политики могут повесить систему, если процесс войдёт в бесконечный цикл и не будет уступать CPU (тестировать и практиковаться рекомендуется через виртуальную машину!).

Примеры использования chrt

# Посмотреть политику и приоритет процесса
chrt -p 1234

# Изменить политику работающего процесса
sudo chrt -f -p 50 1234

# 1234 это пример pid

ionice — утилита для управления приоритетом доступа процесса к диску.

Классы.

  • 1 (real-time): первый в очереди диска. Опасно: может заблокировать систему.

  • 2 (best-effort): по умолчанию. Приоритет 0-7 внутри класса(0 = высший)

  • 3 (idle): работает только когда никто другой не запрашивает диск.

Примеры использования ionice

# Запуск с минимальным i/o-приоритетом.
ionice -c 3 rsync -av /data /backup

# посмотреть i/o-приоритет процесса
ionice -p 1234

taskset — утилита для просмотра и установки привязки процесса к конкретным ядрам процессора. Зачем она нужна? К примеру, чтобы изолировать критичный сервис от других процессов, которые потребляют много ресурсов.

Примеры использования taskset

# Запуск процесс только на ядрах 0 и 1
taskset -c 0,1 ./myapp

# Запустить на ядрах 2-4 (диапазон)
taskset -c 2-4 ./worker

# Привязка рабочего процесса к ядрам 0,2,4
taskset -cp 0,2,4 1234

# Посмотреть текущую привязку.
taskset -cp 1234

Ещё пример: на 8-ядерном сервере привяжите базу данных к ядрам 0-3, а веб-сервер — к 4-7. Это снизит конкуренцию за кэш и память, уменьшит миграцию и повысит стабильность.

9. OOM Killer — кто умрёт первым

Когда памяти не хватает, ядро убивает кого-то. Жертву выбирает OOM Killer по очкам (oom_score): чем больше процесс жрёт памяти, тем ближе он к смерти. Примеры и частые практики, для которых нужно знать OOM Killer.

# Кто сейчас под угрозой
for pid in /proc/[0-9]*/oom_score; do
    score=$(cat $pid 2>/dev/null)
    [ "${score:-0}" -gt 100 ] 2>/dev/null || continue
    comm=$(cat ${pid%/oom_score}/comm 2>/dev/null)
    echo "$score $comm"
done | sort -rn | head -10

# Проверить, был ли кто убит
dmesg | grep -i oom
journalctl -k | grep "killed process"

# Защитить какой-то процесс от убийства
echo -500 | sudo tee /proc/$(pgrep postgres | head -1)/oom_score_adj

# Проверить, был ли кто убит
sudo dmesg | grep -i oom

# Защитить процесс от убийства
echo -500 | sudo tee /proc/$(pgrep postgres | head -1)/oom_score_adj

# Сделать процесс главной мишенью
echo 1000 | sudo tee /proc/1234/oom_score_adj

Кратко еще стоит добавить про ulimit и cgroups ограничение ресурсов

ulimit задаёт ограничения для процессов в текущей сессии шелла и их потомков: сколько файлов можно открыть, сколько памяти занять, сколько процессов создать и т. д. Но, закрыв терминал, всё сбросится, если не прописать это постоянно в limits.conf (путь: /etc/security/limits.conf). Пропишите в конфиге все нужные вам ограничения, чтобы изменения пережили перезапуск. Проверить текущие ограничения можно примерно так: systemctl show myapp.service | grep -E "Memory|CPU|Tasks|IO".

cgroups — более низкоуровневый механизм ядра, который ограничивает ресурсы для произвольной группы процессов независимо от сессий. systemd автоматически создаёт cgroups для каждого сервиса, поэтому это рекомендуемый (моя рекомендация) способ ограничения ресурсов: прописал условный MemoryMax в unit-файлах — и всё, ядро следит за лимитами, даже если сервис форкает сотню процессов или дочерних процессов.

Но вот вопрос: когда что использовать?

Давайте как пример пару ситуаций:

  1. Лимит для пользователя или сессии: достаточно ulimit и настройка конфига.

  2. Лимит для systemd-сервиса: systemd + cgroups

  3. Лимит для контейнера, к примеру в Docker это можно сделать через yaml (docker compose) у них под капотом cgroups.

Примеры команд

# посмотреть все лимиты
ulimit -a

# макс. открытых файлов
ulimit -n

# макс. процессов
ulimit -u

# макс. виртуальной памяти
ulimit -v

# макс. cpu 
ulimit -t

# поднять лимит файлов прямо сейчас
ulimit -n 65536

# лимиты конкретного процесса
cat /proc/1/limits

# иерархия cgroups
systemd-cgls

# посмотреть потребление ресурсов по сервисам в реальном времени
systemd-cgtop

# найти в какой cgroup сидит процесс
cat /proc/1/cgroup

10. Мониторинг: top, htop и другие.

top — инструмент, показывающий процессы, нагрузку на процессор, память и среднюю загрузку системы. Можно запустить top сразу, а можно и написать флаги, к примеру обновление каждую секунду top -d 1 или следить за конкретным процессом top -p 1234 (несколь процессов через запятую писать).

Возможно есть ещё флаги, но полезные флаги я выделю вот такие:

Для запуска и отображения:

  • -d <секунды> — интервал обновления. По умолчанию 3 секунды.

  • -n <число> — завершить после N обновлений. Полезно в скриптах.

  • -b — пакетный режим, выводит результат в stdout без интерактива. Используется вместе с -n,

  • -1 — показать каждое ядро процессора отдельно.

Для фильтрации:

  • -p <PID> — следить только за указанным процессами, до 20 через запятую.

  • -u <пользователь> — показывать только процессы конкретного пользователя.

  • -U <пользователь> — то же, но включает процессы где пользователь указан в любом из полей.

Прочее:

  • -H — показывать потоки вместо процессов. Каждый поток отображается отдельной строкой.

  • -c — показывать полную командую строку вместо короткого имени процесса.

  • -i — скрыть простаивающие процессы, показывать только активные.

  • -s — безопасный режим, отключает опасные команды(к примеру r и k).

Заключение

Мы разобрали базу процессов (за рамками остались межпроцессное взаимодействие, strace и т. д.), они войдут в следующие части серии. Самая лучшая практика для вас (если вы, к примеру, обучаетесь) — запустить виртуалку и попробовать создать сценарии, используя команды и знания из статьи. Удачи вам!

© 2026 ООО «МТ ФИНАНС»