Заходишь на сервер, а он еле дышит. Первый рефлекс у новичка - "наверное, кончилась оперативка". Дальше паника: запускаешь top, видишь, что памяти занято почти всё, и думаешь, что нашёл виновного. В девяти случаях из десяти это ложная тревога. Linux специально съедает почти всю свободную память под кеш, и это нормально - так и должно быть. Незанятая память - это потраченные впустую деньги, ядро это понимает.
В этом уроке разберёмся, как в Linux посмотреть память по-человечески: сколько её всего, сколько занято процессами, а сколько - кешем, который отдадут по первому требованию. Это самая частая задача админа, поэтому пройдём её руками и медленно. Главное, чему научишься: не пугаться слова "used" и понимать, что такое available - единственная цифра, которой реально стоит верить, когда решаешь, хватает памяти или пора что-то делать. А в конце добавим то, чего обычно не хватает в старых гайдах: PSI - современный (и куда более честный, чем своп) индикатор нехватки памяти, ставший на 2026 стандартом де-факто.
Работать будем на любом современном Linux с systemd - команды одинаковы на Ubuntu, Debian, RHEL, Fedora. На Astra Linux и RED OS всё читается ровно так же: то же ядро Linux и те же утилиты из пакета procps-ng, никакой магии.

free -h: как в linux узнать объём памяти за одну команду
Команда free - первое, что стоит набрать, когда нужно быстро узнать память linux. Флаг -h (human readable) переводит байты в удобные гигабайты, -m показывает в мегабайтах, а -w (wide, есть в procps-ng) разносит buffers и cache в отдельные колонки. Запускай без sudo, права не нужны.
Код: Выделить всё
$ free -h
total used free shared buff/cache available
Mem: 15Gi 4,2Gi 512Mi 320Mi 11Gi 10Gi
Swap: 2,0Gi 0B 2,0Gi
- total - весь объём оперативной памяти, видимый ядру. Здесь 15Gi - значит в машине стоит 16 ГБ. Разница в том, что часть откусывает прошивка/видеоядро, плюс служебные структуры ядра, зарезервированные ещё до старта (kernel reserved). Поэтому total почти никогда не равен наклейке на планке.
- used - память, реально занятая процессами и неосвобождаемыми структурами ядра, без кеша. Формула в procps-ng: used = total - free - buffers - cache. Тут 4,2Gi. Это нагрузка, но не вся правда.
- free - совсем не тронутая, пустая память. Кажется, что её мало (512Mi) - и это пугает новичков. Но это НЕ повод для тревоги, читай дальше.
- shared - в основном tmpfs (например /dev/shm, /run) и память, общая для нескольких процессов. На сервере с большим /dev/shm (часто его держит PostgreSQL, Redis, контейнеры) эта цифра бывает заметной.
- buff/cache - буферы и страничный кеш файловой системы. Тут 11Gi - огромный кусок. Это копии файлов и метаданных в памяти, чтобы не читать их с диска. Память как бы занята, но в любой момент отдаётся приложениям.
- available - вот главная цифра. Оценка ядра: сколько памяти реально можно отдать новым программам без ухода в своп. Берётся не как "free + весь кеш", а умнее: free плюс та часть кеша и реклеймабельного slab, которую безопасно освободить, минусуются low watermarks. Поэтому available обычно меньше, чем free + buff/cache.
Строка Swap - файл, раздел или (на современных десктоп-сборках Fedora и Ubuntu по умолчанию) сжатый zram. Если used у свопа стабильно растёт и не падает, а available у Mem ползёт к нулю - вот это уже реальный сигнал. Но сам по себе ненулевой swap used паникой не является: ядро штатно выгружает давно не используемые страницы, чтобы освободить RAM под кеш. Об этом ниже.
/proc/meminfo: подробная карта памяти
free красиво, но это лишь выжимка. Источник правды - виртуальный файл /proc/meminfo. Ядро отдаёт его в реальном времени, читаем как обычный текст:
Код: Выделить всё
$ cat /proc/meminfo
MemTotal: 16310260 kB
MemFree: 524288 kB
MemAvailable: 10485760 kB
Buffers: 204800 kB
Cached: 10250240 kB
SwapTotal: 2097152 kB
SwapFree: 2097152 kB
Dirty: 12480 kB
Writeback: 0 kB
AnonPages: 4100200 kB
Slab: 612340 kB
SReclaimable: 430120 kB
SUnreclaim: 182220 kB
Committed_AS: 8123456 kB
- MemTotal / MemFree - то же, что total и free в free, только в kB.
- MemAvailable - тот самый available. Это поле и есть честный ответ "сколько свободно реально". Появилось в ядре 3.14 (2014), так что есть везде - не надо больше считать руками "free плюс кеш".
- Cached - страничный кеш, копии содержимого файлов в памяти. Большой Cached - это хорошо, диск меньше дёргается.
- Buffers - кеш блочных операций и метаданных. Обычно небольшой.
- AnonPages - анонимная память: куча и стеки процессов, то что выделено через malloc и не привязано к файлу. Именно её при нехватке некуда деть, кроме как в своп. Растущий AnonPages при стабильном Cached - признак, что память едят приложения, а не кеш.
- Dirty - "грязные" страницы: данные изменены в памяти, но ещё не записаны на диск. В норме десятки-сотни мегабайт. Если Dirty пухнет до гигабайтов - диск не успевает за записью, жди фризов на fsync. Связано с sysctl vm.dirty_ratio.
- Slab - память под внутренние структуры ядра (inode-кеш, dentry-кеш и прочее). Делится на SReclaimable (можно освободить под давлением, входит в available) и SUnreclaim (нельзя). Если SUnreclaim разрос до нескольких гигабайт - это уже похоже на утечку в ядре или драйвере, копай через slabtop.
- Committed_AS - сколько памяти процессы суммарно "забронировали" (через malloc и mmap), даже если ещё не трогали ни байта. Если Committed_AS заметно больше MemTotal - система раздала обещаний больше, чем имеет физически (overcommit). При невезении, когда все придут забирать обещанное, сработает OOM killer.
Код: Выделить всё
$ grep -E 'MemTotal|MemAvailable|Dirty' /proc/meminfo
MemTotal: 16310260 kB
MemAvailable: 10485760 kB
Dirty: 12480 kB
free и meminfo - снимок "здесь и сейчас". А если хочется видеть, как память живёт во времени, и поймать момент, когда система начинает свопить? Для этого vmstat. Запускай с интервалом в секунду; флаг -w (wide) раздвинет колонки, чтобы цифры не слипались:
Код: Выделить всё
$ vmstat -w 1 5
--procs-- -----------------------memory---------------------- ---swap-- -----io---- -system-- --------cpu--------
r b swpd free buff cache si so bi bo in cs us sy id wa st
1 0 0 524288 204800 10250240 0 0 12 35 220 410 3 1 95 1 0
0 0 0 521340 204800 10252100 0 0 0 8 198 380 2 1 97 0 0
0 0 0 519200 204812 10253400 0 0 0 16 205 395 2 1 97 0 0
- free / buff / cache - те же килобайты памяти, но обновляются каждую секунду. Видно, как кеш дышит.
- si / so (swap in / swap out) - главные герои. Сколько КБ в секунду читается из свопа (si) и выгружается в своп (so). Важно: единицы тут именно КБ/с, флаг -S единицы для si/so не меняет (известная особенность vmstat). В здоровой системе тут стабильные нули. Постоянно ненулевые si и so - система активно гоняет страницы туда-сюда, это и есть нехватка памяти и частая причина тормозов.
- wa в блоке cpu - процент времени, когда процессор простаивает в ожидании диска (I/O wait). Высокий wa вместе с ненулевыми si/so - классический memory pressure: память кончилась, всё уперлось в диск подкачки.
- r / b - очередь процессов, готовых бежать (r), и заблокированных в непрерывном ожидании (b). Растущий b при свопе подтверждает, что упёрлись в I/O.
Память конкретного процесса
Общая картина ясна - теперь найдём, кто именно ест память. Сортируем процессы по RSS (Resident Set Size - реально занятая физическая память) через ps:
Код: Выделить всё
$ ps -eo pid,comm,rss,vsz --sort=-rss | head -5
PID COMMAND RSS VSZ
1842 mysqld 1820432 3920100
2310 java 1204880 5621000
980 dockerd 210640 1820300
- RSS - сколько физической оперативной памяти процесс занимает прямо сейчас (в КБ). Честная цифра, но с оговоркой: если процесс линкуется с общими библиотеками, их память считается ему целиком, хотя делится с другими. Поэтому простая сумма RSS по всем процессам обычно больше реально занятой RAM - двойной учёт shared-страниц.
- VSZ - виртуальный размер: всё, что процесс себе зарезервировал, включая ещё не загруженное в RAM и просто замапленное. VSZ часто огромный и пугающий - не верь ему, смотри RSS.
Код: Выделить всё
$ grep -E '^Pss:' /proc/1842/smaps_rollup
Pss: 1623840 kB
Код: Выделить всё
$ grep -E 'VmRSS|RssAnon|RssFile|VmSwap' /proc/1842/status
VmRSS: 1820432 kB
RssAnon: 1500200 kB
RssFile: 320232 kB
VmSwap: 51200 kB
PSI: честный индикатор нехватки памяти (актуально на 2026)
Главное обновление по сравнению со старыми гайдами. Раньше единственным сигналом считали своп, но с zram и быстрыми NVMe своп перестал быть надёжным маркером боли. Современный ответ - PSI (Pressure Stall Information), доступный на cgroup v2 (а это дефолт во всех актуальных дистрибутивах: Ubuntu 22.04+, Debian 12+, RHEL 9+, свежие Astra/RED OS). PSI показывает не "сколько занято", а "сколько времени задачи реально простаивали из-за нехватки памяти" - то есть прямую меру тормозов.
Код: Выделить всё
$ cat /proc/pressure/memory
some avg10=0.00 avg60=0.12 avg300=0.05 total=1820400
full avg10=0.00 avg60=0.04 avg300=0.01 total=910200
- some - доля времени, когда хотя бы одна задача стояла в ожидании памяти.
- full - доля времени, когда ВСЕ незадействованные задачи стояли одновременно (полный стопор, чистая потеря тактов).
- avg10 / avg60 / avg300 - проценты за последние 10, 60 и 300 секунд.
Код: Выделить всё
$ cat /sys/fs/cgroup/system.slice/mysql.service/memory.current
1864441856
$ cat /sys/fs/cgroup/system.slice/mysql.service/memory.pressure
some avg10=0.00 avg60=0.20 avg300=0.08 total=2210400
Типичные грабли и заблуждения
- "used почти 100 процентов - сервер умирает". Нет. Linux ВСЕГДА старается занять память под кеш. Смотри на available, а ещё лучше на PSI, а не на used и free.
- Чистка кеша через drop_caches "для оптимизации". Команда sync; echo 3 > /proc/sys/vm/drop_caches существует, но в проде её трогать не надо: ты просто выкинешь полезный кеш, и система начнёт медленнее читать диск, пока не прогреется заново. Это диагностический инструмент, а не оптимизация.
- Считать VSZ занятой памятью. Виртуальный размер - бронь и мапинги, а не факт. Реальное потребление - RSS, а для честного учёта shared - PSS.
- Суммировать RSS всех процессов и пугаться. Из-за двойного учёта общих библиотек сумма завышена. Доверяй MemAvailable от ядра.
- Игнорировать своп vs паниковать от свопа. Немного в свопе - норма. Тревога - когда своп активно читается/пишется прямо сейчас (si/so), при этом высокий wa и растёт PSI. На zram активность свопа сама по себе почти безболезненна.
- Выполни free -h и найди свои total, used и available. Ответь себе: сколько памяти реально свободно? Сравни used и available.
- Сравни: grep -E 'MemTotal|MemFree|MemAvailable|Committed_AS' /proc/meminfo - сходятся ли цифры с free? Committed_AS уже больше MemTotal?
- Запусти vmstat -w 1 5 и посмотри колонки si, so и wa. У тебя там нули? Отлично, своп спит.
- Найди топ-3 пожирателя: ps -eo pid,comm,rss --sort=-rss | head -4, потом загляни в /proc/<PID>/status на VmRSS и VmSwap.
- Прочитай cat /proc/pressure/memory. Какие у тебя avg10 у some и full? Если оба около нуля - давления на память нет.
- Почему низкое значение free в выводе free -h - это нормально, и на какую колонку надо смотреть вместо него?
- Чем RSS отличается от VSZ, и почему сумма RSS по всем процессам обычно завышена по сравнению с реально занятой RAM?
- Какие две колонки vmstat сигналят о свопинге, и почему в 2026 на машине с zram одних si/so уже мало для вывода о нехватке памяти?
- Что показывает PSI (строки some и full в /proc/pressure/memory) и какой примерно порог some avg10 считается тревожным?
free -h - быстрый снимок, /proc/meminfo - полная карта, vmstat - динамика и своп, PSI - честный индикатор боли. Главная цифра при оценке памяти - available (она же MemAvailable), а не free. used высокий - не страшно; страшно, когда available у нуля, в vmstat побежали si/so при высоком wa, а PSI some/full пополз вверх. Память процесса - это RSS (и PSS для честности), а не VSZ. В мире systemd и контейнеров смотри memory.current и memory.pressure по cgroup v2. На Astra Linux и RED OS всё ровно то же самое.