Система продолжает работать: сайты отвечают, процессы крутятся, но любая попытка сохранить что-то заканчивается одинаково. В логах приложений строки Read-only file system, база данных отказывается фиксировать транзакции, systemctl жалуется на невозможность записи, а команда touch на файл в домашнем каталоге возвращает ошибку. Корневая файловая система переведена в состояние только чтение, и в девяти случаях из десяти это не сбой, а защита: ext4 остановила запись из-за ошибок ввода-вывода, чтобы не испортить то, что ещё цело. Дальше по шагам: подтверждение диагноза, чтение журнала journalctl, оценка накопителя через SMART и возврат записи утилитой e2fsck.
Симптомы перехода корневого раздела в ошибку записи EROFS
Приложения получают от системного вызова ошибку с кодом 30, EROFS. В терминале она выглядит так:
touch: cannot touch '/root/probe': Read-only file system
Проверяется состояние одной командой: findmnt -no OPTIONS / печатает список опций монтирования корня, и среди них оказывается ro. Тот же ответ словами даёт mount с фильтром по корню. Момент перехода важен не меньше факта: метки времени в журналах служб, получивших EROFS, очерчивают инцидент с точностью до минуты.
Вариантов причины три, и они различаются по времени. Если опция ro прописана в fstab или корень перемонтирован руками, это конфигурация, и лечится правкой. Если система при загрузке не смогла проверить корень, она уходит в аварийный режим и сообщает об этом явно. Третий, самый частый на практике сценарий: система работала нормально и среди дня переключилась в состояние только чтение. Это защита ext4.
Пока раздел в защите, службы чтения продолжают работать, и это окно используется для эвакуации данных: файлы читаются, копируются на другой носитель и не пропадают от того, что запись закрыта. Первыми страдают сервисы записи, и их журналы с EROFS служат точными метками инцидента.
Влияние на службы распределяется неровно, и это подсказка при диагностике. Если каталог var или var/log вынесен в отдельный раздел, логи продолжат писаться и покажут, что происходило уже после остановки записи в корень. Службы, которые держат состояние в etc, начнут жаловаться первыми; пакетный менеджер откажется ставить обновления, systemd не сможет сохранить состояние юнитов. Набор симптомов прямо указывает, где именно заморожена запись.
Полный порядок действий после обнаружения признаков выглядит так:
- подтвердить режим опцией ro в выводе findmnt и запомнить время перехода;
- собрать ошибки ядра текущей и предыдущей загрузки через journalctl;
- оценить состояние накопителя через SMART и журнал дефектов;
- скопировать критичные файлы пока раздел читается;
- исправить файловую систему утилитой e2fsck из внешней среды;
- вернуть корневой раздел к записи и проверить настройки fstab.
Механика защиты ext4 при аппаратных сбоях записи
У ext4 есть журнал, который фиксирует изменения метаданных. Когда запись метаданных возвращает ошибку, ядро помечает журнал аварийным и печатает строку Detected aborted journal, а следом решение EXT4-fs: Remounting filesystem read-only. С этого момента операции записи возвращают EROFS, а чтение продолжает работать.
Логика защиты проста: продолжать запись поверх сомнительного носителя значит с высокой вероятностью разрушить структуру, которую потом не соберёт ни одна утилита. Заморозив раздел в состоянии только чтение, ядро сохраняет последнее согласованное состояние, и данные остаются доступны для копирования.
В журнале ядра зрелый инцидент оставляет типичную пару строк:
EXT4-fs error (device sda2): ext4_journal_check_start:83: Detected aborted journal
EXT4-fs (sda2): Remounting filesystem read-only
Время второй строки это и есть момент перехода в защиту.
Поведение задаётся опцией errors= при монтировании. Значение remount-ro стоит по умолчанию и переводит раздел в защиту. Значение continue оставляет запись включённой и годится разве что для измерительных стендов. Значение panic уводит ядро в управляемую остановку, что уместно в кластерах, где сбойный узел исключает внешний механизм изоляции. Значение по умолчанию хранится в суперблоке и меняется утилитой tune2fs:
sudo tune2fs -e remount-ro /dev/sda2
Типичная строка в fstab закрепляет то же поведение на уровне конфигурации:
UUID=6f3c1b9e-4a2d-4e8f-9c1b-7d5e2a8f0413 / ext4 errors=remount-ro 0 1
Разбор журнала journalctl от ошибок файловой системы до сбоев устройства
Следы инцидента лежат в журнале ядра. Основная выборка собирается одной командой:
journalctl -k -b -p warning --no-pager | grep -iE "EXT4-fs|I/O error|aborted|medium"
Картина зрелого инцидента выглядит как цепочка. Сначала ошибки уровня устройства, затем признание файловой системой. Строка blk_update_request: I/O error, dev sda, sector 9765432 говорит, что запрос к устройству вернулся с ошибкой. Строки sd 0:0:0:0: [sda] tag#17 FAILED Result: hostbyte=DID_OK driverbyte=DRIVER_SENSE и Sense Key: Medium Error это ответ самого накопителя о проблеме носителя. Затем идут признание журнала, Detected aborted journal, и решение EXT4-fs (sda2): Remounting filesystem read-only.
Время строки с Remounting filesystem read-only это момент инцидента, от него отсчитывается влияние на сервисы. Ошибки за минуты и часы до перехода, особенно в предыдущей загрузке через journalctl -k -b -1, показывают, что накопитель деградировал давно и мягко намекал на замену. Если система не перезагружалась, та же картина видна в выводе dmesg, но journalctl удобнее фильтрами и метками времени.
Интерпретация зависит от характера ошибок. Десятки medium-ошибок по разным секторам означают деградацию поверхности. Ошибки CRC и растущий счётчик UDMA_CRC_Error_Count указывают на кабель, переходник или контроллер. Единичная ошибка после долгой стабильности может быть переходящим сбоем, но и её стоит зафиксировать в описании инцидента.
Окно инцидента вырезается фильтрами времени: journalctl принимает границы через --since и --until, и по ним собирается компактный отчёт для тикета. Строки с кодами ошибок накопителя обычно идут пачками по несколько штук за секунду, и первая из них указывает момент касания дефектной области.
Для чтения истории нужен постоянный журнал: Storage=persistent в /etc/systemd/journald.conf, иначе после перезагрузки от прошлых загрузок не останется ничего. На сервере с контроллером IPMI журнал читается и через аппаратную консоль, если сеть или сама система не пускают по обычному пути.
Оценка состояния накопителя через SMART до любых попыток записи
Проверка железа идёт раньше ремонта: e2fsck активно пишет, и на деградирующем накопителе это способно довести его до полного отказа. Базовая диагностика занимает минуты:
sudo smartctl -H /dev/sda
sudo smartctl -A /dev/sda
Итог PASSED сам по себе не успокаивает: он не отражает динамику. Читаются атрибуты: 5 Reallocated_Sector_Ct, 197 Current_Pending_Sector, 198 Offline_Uncorrectable. Ненулевые raw-значения у любого из трёх означают, что накопитель переназначает или откладывает дефектные секторы, и процесс идёт. Атрибут 199 UDMA_CRC_Error_Count отвечает за передачу данных по кабелю и контроллеру.
Функциональный тест запускается командой smartctl -t short: короткая самопроверка обычно занимает несколько минут, результаты читаются через smartctl -l selftest, а журнал внутренних ошибок через smartctl -l error. Растущие значения от теста к тесту закрывают вопрос: накопитель меняется.
Если атрибуты чистые, а ошибки продолжают сыпаться, подозрение переносится на обвязку: кабель проверяется и пересаживается, диск переводится на другой порт контроллера, после чего наблюдение продолжается по журналу ядра. Часть переходящих сбоев уходит после замены кабеля, и этим простым шагом закрывается заметная доля обращений.
Если атрибуты растут, план меняется с лечения на эвакуацию: данные копируются на другой носитель, раздел переносится, диск уходит в замену. Клонирование выполняется утилитой ddrescue, которая читает доступные блоки, ведёт карту нечитаемых областей и не застревает на каждой ошибке.
В виртуальных средах картина другая: внутри гостя диск называется vda, и smartctl на нём не покажет ничего о реальном носителе. Ошибки ввода-вывода в гостевой системе означают проблемы хранилища на стороне провайдера и решаются через поддержку, а журнал гостя помогает приложить к обращению конкретные строки с временем.
Проверка файловой системы e2fsck и возврат корневого раздела к записи
Первая мысль администратора, перемонтировать корень на живой системе командой mount -o remount,rw /, при прерванном журнале заканчивается отказом: ядро снова сообщит об аварийном журнале. Это не каприз, а защита: сначала исправление, потом запись.
Попытка запустить e2fsck на смонтированном корне тоже закончится отказом: утилита видит раздел под монтированием и прерывает работу, не трогая данные. Одновременная запись из системы и исправление структуры почти гарантированно разрушают том, и запрет здесь оправдан полностью.
Корректный путь это проверка из внешней среды: живой дистрибутив с флешки, rescue-режим панели хостинга или отдельный загрузочный образ. На незагруженном разделе запускается:
sudo e2fsck -f /dev/sda2
Флаг -f принуждает полную проверку даже при чистом флаге состояния, ответы на вопросы утилиты автоматизируются флагом -y. На больших томах проверка идёт десятки минут, и прерывать её нельзя: недоделанное исправление хуже, чем отсутствие исправления.
Для виртуальных серверов без доступа к живому образу есть параметры загрузки fsck.mode=force и fsck.repair=yes: проверка выполнится в загрузочном окружении до монтирования корня. Параметр добавляется к строке загрузки на один старт и убирается после успешного восстановления.
После чистого результата проверки система грузится в обычном режиме, и возврат записи подтверждается командами:
findmnt -no OPTIONS /
sudo touch /root/probe && sudo rm /root/probe
Если корень живёт на массиве mdadm, поведение отличается: ядро исключает сбойный диск из массива и пишет в журнал об ошибке и удалении устройства из активного набора. Починка массива это отдельная процедура, но сигнал к ней приходит из того же журнала ядра.
Настройка реакции на ошибки и мониторинг на будущее
Защиту errors=remount-ro оставляют как есть. Переключение в continue ради видимого благополучия обменивает целостность данных на время: раздел продолжит работать, пока структура не разрушится до нечитаемости. Сделка плохая при любом раскладе.
Мониторинг ставит сигнализацию на деградацию до того, как она дойдёт до защиты. Служба smartd читает атрибуты по расписанию и отправляет письма администратору; типовая строка в /etc/smartd.conf выглядит так:
DEVICESCAN -H -l error -l selftest -m root
Метрики SMART и температура отправляются в систему мониторинга наряду с остальными графиками, а порог на текущие дефектные секторы срабатывает задолго до срабатывания защиты ext4. В связке с постоянным журналом это даёт окно в дни и недели для плановой замены вместо ночной тревоги.
В облаке к мониторингу добавляется дисциплина образов: перед ремонтом снимается снапшот диска, и e2fsck выполняется на копии. Это одновременно страховка от неудачной починки и способ запустить проверку, не гася продакшен целиком.
Список накопителей с растущими атрибутами ведётся в системе учёта: диск, дата первого замечания, динамика значений. Когда приходит время плановой замены, решение принимается по записям, а не по памяти.
Отдельно проверяется конфигурация fstab: строки с опциями и точками монтирования переживут любые операции, и ошибка в UUID устройства это самый быстрый способ попасть в аварийный режим при следующей загрузке. Резервные копии критичных данных и тестовое восстановление закрывают сценарий, когда защита сработала, а выносить уже нечего.
Режим только чтение это не поломка, а сигнализация. Ядро честно сообщило, что носитель под подозрением, и дало время вынести данные. Задача инженера в том, чтобы прочитать журналы до возврата записи, а не гнать систему в работу вслепую.