Ситуация знакомая: система отвечает с задержкой, индикатор диска горит постоянно, а top показывает низкую загрузку процессора. Виноват ввод-вывод, и найти процесс поможет iotop — консольный монитор, который показывает чтение и запись в разбивке по процессам и потокам.
Как работает iotop
Программа не опрашивает /proc вслепую, а получает статистику ядра через netlink-интерфейс taskstats. Для этого в ядре должны быть включены CONFIG_TASK_IO_ACCOUNTING и CONFIG_TASK_DELAY_ACCT. В дистрибутивных ядрах они обычно есть, но проверить стоит.
zgrep -E "TASK_IO_ACCOUNTING|TASK_DELAY_ACCT" /proc/config.gz
grep -E "TASK_IO_ACCOUNTING|TASK_DELAY_ACCT" /boot/config-$(uname -r)
sudo apt install iotop
iotop --version
Запуск требует прав root или возможности CAP_NET_ADMIN: без них список будет пустым, хотя диск загружен. Это не ошибка установки, а сознательное ограничение — статистика ввода-вывода раскрывает поведение других пользователей.
Разбираем колонки
- TID — идентификатор потока, а не процесса; в скобках может быть имя.
- PRIO — приоритет ввода-вывода.
- USER — владелец процесса.
- DISK READ и DISK WRITE — реальный трафик к блочным устройствам.
- SWAPIN — доля времени, потраченного на подкачку.
- IO> — доля времени ожидания ввода-вывода.
- COMMAND — имя программы.
Ключевая тонкость: учитывается фактический обмен с диском, а не запись в страничный кэш. Программа может «писать» гигабайты, которые ещё не дошли до устройства, и в iotop её не будет видно. Обратная ситуация — сброс кэша — покажет активность процесса, который на самом деле давно спит. Поэтому iotop смотрят вместе с iostat и /proc/PID/io.
Быстрый старт
Без аргументов iotop показывает все потоки и обновляется раз в секунду. На практике нужны фильтры: иначе полезные строки тонут в служебных.
sudo iotop -o
sudo iotop -oPa
sudo iotop -bo -n 10 -d 2
sudo iotop -p 1234
-o оставляет только активные процессы, -P показывает процессы вместо потоков, -a — накопленные значения с момента запуска, -b включает пакетный режим для записи в файл, -n задаёт число итераций, -d — задержку, -p — конкретный PID. Ещё есть -k для килобайт вместо человекочитаемых единиц, -u для фильтра по пользователю и -t для отметок времени.
Колонки SWAPIN и IO> показывают не объём, а долю времени ожидания. Если у процесса IO> держится выше 20–30%, он проводит в очереди к диску заметную часть времени; высокий SWAPIN при этом прямо указывает на нехватку памяти. Для домашней машины это повод проверить свободную память и активность подкачки, а не только диск.
Сценарий: диск занят, виновника не видно
Сначала снимите картину на несколько минут в пакетном режиме. Интерактивный экран удобен для наблюдения, но не даёт истории, а проблема часто плавающая.
sudo iotop -botk -n 30 -d 2 | tee /tmp/iotop.log
grep -v "^Total" /tmp/iotop.log | tail -40
sudo iotop -boak -n 5
Флаг -a показывает накопленный итог: так видно процесс, который медленно, но постоянно пишет, даже если в моменте его значения невелики. Если в логе мелькает то один, то другой процесс, ищите общий источник — например, службу резервного копирования, которая запускает дочерние задачи.
Подтверждение другими инструментами
Один инструмент легко вводит в заблуждение. Если iotop указал на процесс, проверьте нагрузку на устройство и характер операций.
iostat -xz 1 5
pidstat -d 2 5
cat /proc/1234/io
sudo lsof -p 1234 | head -30
iostat -xz показывает утилизацию устройства, очередь и среднее время операции. pidstat -d даёт разбивку по процессам, /proc/PID/io — счётчики read_bytes и write_bytes, то есть реальный диск, в отличие от rchar и wchar, куда входит и кэш. lsof отвечает на вопрос «какие файлы открыты», а fatrace из одноимённого пакета — «кто прямо сейчас трогает файлы».
Кто обычно нагружает диск
- Резервное копирование: restic, borg, rsync по расписанию.
- Индексация файлов: tracker, baloo, обновление базы locate.
- Контейнеры: распаковка слоёв и запись логов Docker или Podman.
- Журнал systemd при неаккуратных настройках хранения.
- Браузер с большим кэшем и профилем.
- Нехватка памяти: активная подкачка выглядит как постоянная запись.
Для каждого случая есть свой рычаг. Тяжёлую задачу можно опустить по приоритету ввода-вывода, бэкап — перенести на ночь, индексацию — ограничить по каталогам, журнал — подрезать.
sudo ionice -c2 -n7 -p 1234
journalctl --disk-usage
sudo journalctl --vacuum-size=500M
sudo nice -n 19 ionice -c3 rsync -a /data/ /backup/
ionice -c3 включает режим ожидания: процесс получает диск только когда он свободен. Это не спасёт от нехватки памяти, но уберёт конкуренцию за очередь. Если всплески повторяются в одно и то же время, ищите таймер systemd или задание cron — systemctl list-timers и crontab -l показывают источник быстрее, чем наблюдение за экраном.
Ограничения iotop
Сетевые файловые системы и FUSE-монтирования могут не попадать в статистику taskstats: там смотрите на сетевой трафик и процессы-клиенты. В контейнерах iotop на хосте показывает процессы, но не их принадлежность к контейнеру — сверяйтесь с crictl или docker top. Ядерные потоки вида [kworker] не имеют привычного имени, и их активность часто означает отложенную запись, а не конкретную программу.
На NVMe показатель %util в iostat может быть близок к 100% без реального насыщения: устройство обрабатывает команды параллельно. Смотрите на задержки и очередь, а не только на утилизацию.
Чек-лист
- iotop запущен с правами root, ядро поддерживает учёт ввода-вывода.
- Снят лог в пакетном режиме, а не только взгляд на живой экран.
- Проверены накопленные значения, а не один момент.
- Нагрузка подтверждена iostat и /proc/PID/io.
- Найденный процесс сопоставлен с расписанием и службой.
- Принята мера: ionice, перенос задачи или ограничение журнала.
Итог
iotop отвечает на конкретный вопрос: кто прямо сейчас читает и пишет на диск. Он не заменяет iostat и не показывает нагрузку на сеть, зато мгновенно сужает круг подозреваемых. Снимайте историю в пакетном режиме, сверяйте с накопленными счётчиками и подтверждайте вывод вторым инструментом — тогда «диск занят на 100%» превращается из загадки в конкретную задачу с понятным исполнителем.