Как откатить обновление dnf в Rocky или AlmaLinux 9
Если обновление системы вызвало ошибки, используйте команду dnf history для отмены транзакции. В статье описан процесс поиска ID операции, отката изменений и фиксации пакетов.
Откат неудачного обновления dnf за минимальное количество шагов
Чтобы откатить неудачное обновление dnf, найдите ID транзакции, которая изменила пакет, изучите действия этой транзакции, а затем отмените их. Каждое действие dnf записывается с присвоением номера, поэтому восстановление сводится к поиску, а не к догадкам. Приведенные здесь команды написаны для Rocky Linux 9 и AlmaLinux 9, в которых поставляется dnf 4.
sudo dnf history list
sudo dnf history info 42
sudo dnf history undo 42Замените 42 на ID, который вы увидите в первой команде. Это краткий путь, и он работает только в том случае, если старые версии пакетов всё ещё доступны для загрузки. Большая часть этого руководства посвящена ситуации, когда они недоступны, поскольку именно этот случай упускают быстрые ответы.
Каждое действие dnf получает идентификатор транзакции
dnf записывает каждую установку, обновление, откат версии и удаление в собственную базу данных истории. dnf 4 хранит эту базу данных в /var/lib/dnf/history.sqlite. Она отделена от базы данных RPM в /var/lib/rpm, которая содержит информацию только о текущем состоянии установленных пакетов. История хранит хронологию изменений, и именно этот порядок необходим для любого отката.
sudo dnf history list
sudo dnf history list --reverse
sudo dnf history list httpd
sudo dnf history info last
sudo dnf history info 42dnf history list httpd позволяет сузить список до транзакций, затронувших конкретный пакет. Это помогает найти операцию, нарушившую работу сервиса, не просматривая весь журнал. dnf history info описывает отдельную транзакцию: какие пакеты были изменены и в каком направлении, а также командную строку, которая инициировала действие. Изучите эту информацию перед выполнением отмены, так как undo отменяет всю транзакцию целиком, а не только тот пакет, который вы считаете проблемным.
Детали низкого уровня хранятся в двух файлах журналов. /var/log/dnf.log фиксирует действия dnf, а /var/log/dnf.rpm.log записывает изменения пакетов в том виде, в котором их применял rpm. Оба файла важны, если транзакция была выполнена в ваше отсутствие.
Отмена одной транзакции с помощью dnf history undo
dnf history undo выполняет действия, обратные каждому шагу в указанной транзакции. Обновленные пакеты возвращаются к предыдущим версиям. Пониженные версии пакетов обновляются снова. Установленные пакеты удаляются. Удаленные пакеты устанавливаются заново. Используйте эту команду, если вы точно знаете, какая операция привела к сбою системы, и последующие изменения не имеют значения.
sudo dnf history undo 42
sudo dnf history undo last
sudo dnf history undo --assumeno 42В dnf 4 нет --dry-run, поэтому безопаснее запускать команду без -y и изучать предложенный план перед подтверждением. --assumeno автоматически отвечает «нет», что позволяет увидеть план без внесения изменений.
Операция отмены сама по себе является транзакцией. Она получает собственный ID и отображается в dnf history list, поэтому неудачную отмену можно отменить в свою очередь. Именно по этой причине номера ID продолжают расти, даже когда система откатывается назад.
Откат к определенному моменту времени с помощью dnf history rollback
dnf history rollback отменяет все транзакции, выполненные после указанной вами, возвращая набор пакетов в состояние, в котором он находился сразу после завершения этой транзакции. Используйте эту команду, если между моментом, когда сервис работал исправно, и текущим моментом было выполнено несколько операций, и вы не можете определить, какая из них вызвала сбой.
sudo dnf history list --reverse
sudo dnf history rollback 40Прежде всего, необходимо учитывать два момента. ID, который вы передаете, — это номер последней транзакции, которую вы хотите сохранить, а не первой, которую нужно удалить. Кроме того, откат может не выполниться, если текущий набор установленных пакетов не соответствует тому, что ожидает история; это происходит, если что-то было установлено или удалено напрямую через rpm, в обход dnf. В такой ситуации dnf не пытается угадать состояние системы, поэтому изучите выведенное сообщение и выполните отмену отдельных транзакций или понижение версии конкретного пакета.
Откат, затрагивающий смену версии дистрибутива, может привести к изменению сотен пакетов одновременно. Ознакомьтесь с объемом изменений в плане перед тем, как подтвердить его выполнение.
Понижение версии отдельного пакета
Иногда не требуется отменять всю транзакцию целиком. Вам нужно вернуть один пакет к рабочей версии, сохранив при этом остальные обновления.
sudo dnf list --showduplicates httpd
sudo dnf downgrade httpd
sudo dnf downgrade httpd-2.4.62-4.el9Выполните первую команду перед всеми остальными. --showduplicates выводит список всех версий этого пакета, доступных в подключенных репозиториях. Если в списке указана только та версия, которая у вас уже установлена, понижение версии через репозитории невозможно — в этом случае вам помогут следующие разделы.
dnf downgrade httpd выполняет переход к самой старшей из доступных версий, которая ниже текущей. Лучше указывать точную версию, так как в этом случае вы сами выбираете целевой вариант, а не полагаетесь на то, что система предложит следующей. После этого проверьте, что сервис возобновил работу с помощью rpm -q httpd и systemctl status httpd, а также убедитесь, что порт снова прослушивается извне сервера.
Почему отмена операции часто не срабатывает
Отмена операции (undo) — это не восстановление из снимка системы. dnf не хранит копии замененных пакетов. Программа считывает историю, определяет, какие версии нужно вернуть, а затем пытается загрузить именно эти файлы RPM из репозитория, где они все еще доступны. Если их там нет, транзакция завершается ошибкой на этапе разрешения зависимостей, еще до внесения изменений на диск.
Выпуск промежуточной версии (point release) изменил структуру дерева. Репозитории Rocky и Alma 9 содержат текущую минорную версию. Когда выходит следующая минорная версия, предыдущие сборки удаляются из активного репозитория и перемещаются в архив. История по-прежнему ссылается на старую версию, но ни одно из подключенных зеркал её не предлагает.
Сторонний репозиторий выполнил пересборку. Репозитории сообщества обычно хранят только одну актуальную сборку каждого пакета, поэтому вчерашняя версия уже удалена. Чаще всего это затрагивает пакеты из EPEL или CRB, а не из базовых репозиториев.
Репозиторий отключен или удален. Пакет, установленный из репозитория, который вы впоследствии удалили, восстановить невозможно. То же самое касается пакетов, установленных из локальных файлов.
Минорная версия достигла конца жизненного цикла. Для неё больше ничего не публикуется, поэтому загрузить какую-либо версию невозможно.
sudo dnf list --showduplicates отвечает на вопрос для одного пакета одной строкой. Не существует команды, которая выполняла бы предварительную проверку всей транзакции аналогичным образом, поэтому отмена операции может завершиться ошибкой в процессе разрешения зависимостей уже после того, как вы утвердили план действий.
Получение старого пакета из архива
Оба дистрибутива хранят архивы предыдущих минорных версий. Добавьте один из них в качестве отключенного репозитория, загрузите нужный пакет и выполните откат до этого файла. Важно оставлять репозиторий отключенным, так как включенный архивный репозиторий может удержать всю систему на старой минорной версии и незаметно прекратить получение обновлений безопасности.
Для Rocky Linux используйте /etc/yum.repos.d/rocky-vault.repo:
[rocky-9-5-baseos-vault]
name=Rocky Linux 9.5 BaseOS vault
baseurl=https://dl.rockylinux.org/vault/rocky/9.5/BaseOS/x86_64/os/
gpgcheck=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-Rocky-9
enabled=0AlmaLinux публикует свой архив на другом хосте, в /etc/yum.repos.d/alma-vault.repo:
[alma-9-5-baseos-vault]
name=AlmaLinux 9.5 BaseOS vault
baseurl=https://vault.almalinux.org/9.5/BaseOS/x86_64/os/
gpgcheck=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-AlmaLinux-9
enabled=0Измените 9.5 на минорную версию, которую вы использовали, и замените BaseOS на AppStream, если пакет находится там. Уточните имя файла ключа, который фактически находится в вашей системе, с помощью ls /etc/pki/rpm-gpg/, так как этот файл размещается там пакетом релиза, а не вами. Эти базовые URL соответствовали опубликованной структуре в сентябре 2026 года. Если загрузка не удалась, откройте базовый URL в браузере: ошибку 404 в адресной строке проще прочитать, чем ошибку разрешения зависимостей dnf. Дистрибутивы имеют небольшие различия, и практические различия между Rocky Linux и AlmaLinux стоит изучить перед тем, как вставлять содержимое любого из файлов.
Затем загрузите пакет и установите файл:
sudo dnf install -y dnf-plugins-core
sudo dnf --enablerepo=rocky-9-5-baseos-vault download --destdir=/root/rpm-rollback httpd
sudo dnf downgrade /root/rpm-rollback/httpd-2.4.62-4.el9.x86_64.rpmdnf download входит в состав пакета dnf-plugins-core и не является частью базового набора команд, поэтому установите его первым. Передавайте файл в dnf downgrade, а не в rpm -U, так как это позволяет сохранить разрешение зависимостей внутри dnf, что важно, если старому пакету также требуется старая библиотека.
Храните собственные копии старых RPM-пакетов
Самый дешевый способ обезопасить себя — перестать удалять пакеты. Установите keepcache в файле /etc/dnf/dnf.conf:
[main]
keepcache=1После этого загруженные RPM-пакеты будут сохраняться в /var/cache/dnf/, в каталоге, названном в честь репозитория. Найдите нужный файл и установите его напрямую:
sudo find /var/cache/dnf -name 'httpd-*.rpm'
sudo dnf downgrade /var/cache/dnf/appstream-1ec8a0bfaa5e5ff9/packages/httpd-2.4.62-4.el9.x86_64.rpmЦена этого решения — дисковое пространство. Кэш растет с каждым обновлением, и никто не очищает его автоматически, поэтому /var на небольшом VPS со временем переполнится. Команда sudo du -sh /var/cache/dnf показывает объем занятого места, а sudo dnf clean packages очищает кэш. Вторая команда также уничтожает ваши материалы для отката, поэтому не запускайте её в ту же неделю, когда занимаетесь отладкой обновления. Проверку кэша следует включить в план регулярного технического обслуживания.
Еще одна полезная привычка — загружать пакеты перед обновлением. Это занимает несколько секунд и гарантирует наличие точных версий файлов для нужных вам пакетов:
sudo dnf download --destdir=/root/rpm-rollback httpd
sudo dnf upgradeКогда загружать больше нечего
Ядра являются исключением, причем полезным. Enterprise Linux 9 устанавливает ядра параллельно, а не заменяет их, а параметр installonly_limit в /etc/dnf/dnf.conf определяет, сколько из них сохранять. Таким образом, неудачное обновление ядра оставляет на диске рабочую версию.
rpm -q kernel
grep installonly /etc/dnf/dnf.conf
sudo grubby --default-kernel
sudo grubby --info=ALL
sudo grubby --set-default=/boot/vmlinuz-5.14.0-503.14.1.el9_5.x86_64
sudo rebootИспользуйте точное имя файла, которое выводит grubby --info=ALL на вашей машине, а не то, что указано выше. Установка значения по умолчанию до перезагрузки важна на VPS, так как меню загрузки недоступно по SSH, и доступ к нему возможен только через консоль провайдера. После перезагрузки uname -r покажет, какое ядро было загружено фактически, а чтение лога ядра на VPS покажет, на что жаловалось неисправное ядро. Сначала выполните rpm -q kernel, так как предыдущая очистка может оставить вас только с поврежденным ядром, и тогда единственным вариантом останется установка старой версии из репозитория vault, упомянутого выше.
Для всего, что не является ядром, резервным вариантом служит снапшот, сделанный до обновления. В Rocky и Alma по умолчанию используется XFS, у которой нет встроенной функции снапшотов, а большинство облачных образов размещают одну файловую систему XFS на одном разделе без LVM под ней. Проверьте свою конфигурацию с помощью lsblk и sudo vgs. На практике точкой отката является снапшот всего диска на стороне провайдера, сделанный перед началом обновления и удаляемый после того, как машина проработала сутки. Если вы хотите, чтобы откат был встроенным свойством операционной системы, а не привычкой, о которой нужно помнить, это требует иного подхода: дистрибутивы на основе образов версионируют всю систему как единое целое.
Предотвращение повторной установки поврежденного пакета
Команда undo не вносит изменений в репозиторий, поэтому удаленная вами версия остается в нем самой актуальной. Следующая команда dnf upgrade установит ее снова. Зафиксируйте версию пакета перед тем, как завершить работу.
sudo dnf install -y python3-dnf-plugin-versionlock
sudo dnf versionlock add httpd
sudo dnf versionlock list
sudo dnf versionlock delete httpdКоманда versionlock add httpd фиксирует версию, установленную в данный момент, и записывает правило в /etc/dnf/plugins/versionlock.list. После этого dnf игнорирует данный пакет до тех пор, пока вы не удалите правило. Альтернативный вариант — excludepkgs=httpd в файле dnf.conf или --exclude=httpd в одной команде — полностью скрывает пакет от dnf, что может сделать невозможным выполнение несвязанных транзакций, если от этого пакета зависит что-то другое. Для уже установленного пакета предпочтительнее использовать versionlock.
Блокировка также означает отказ от получения обновлений безопасности для этого пакета. Файл блокировки поддерживает комментарии #, поэтому записывайте в него дату и причину, а также установите напоминание там, где вы его гарантированно увидите. Забытая блокировка — это причина, по которой сервер может год работать с уязвимым веб-сервером.
dnf 4 и dnf 5 — это разные инструменты
В Rocky Linux 9 и AlmaLinux 9 поставляется dnf 4, и все команды в этой статье написаны для dnf 4. В Fedora и более новых релизах используется dnf 5, который является полной переработкой. Он поддерживает те же подкоманды для работы с историей, но обрабатывает некоторые опции иначе. Прежде чем использовать флаг, проверьте, какая версия установлена в вашей системе и какие параметры она принимает:
dnf --version
dnf history --helpdnf history --help — это самый точный способ узнать версию для текущей машины. Если вы также администрируете системы Debian или Ubuntu, таблица соответствия команд apt и dnf поможет сориентироваться в аналогичных задачах. Там эквивалентным действием является apt install <package>=<version>, за которым следует apt-mark hold, поскольку apt записывает свои операции в /var/log/apt/history.log, но не имеет встроенной команды для их отмены.
Почему это важно, если машина обновляется сама
Причина изучать команды истории заключается в том, что вы позволяете серверу обновляться самостоятельно. Автоматические обновления — правильный выбор по умолчанию для машины, на которую никто не заходит ежедневно, и платой за это является то, что изменения происходят, пока вы не наблюдаете. Знание модели транзакций превращает ситуацию «что-то сломалось, непонятно когда» в нумерованный список с отметками времени.
systemctl list-timers 'dnf-*'
sudo dnf history list
sudo dnf history info lastПервая команда показывает, включены ли автоматические запуски и когда ожидается следующий. Проверьте это заранее, так как нет смысла тратить час на откат, который ночной таймер отменит. Настраивайте эти таймеры осознанно, как описано в настройке dnf-automatic в Rocky и Alma, и блокируйте всё, что вы откатили.
Ещё одна проверка, прежде чем винить пакет. Обновление может установиться корректно и всё равно выглядеть сломанным, потому что процесс всё ещё использует старый код, а его никто не перезапустил. Изучите какие службы требуют перезапуска после обновления, прежде чем что-либо отменять. На новой машине политика обновлений должна быть частью того же первого этапа, что и всё остальное в обеспечении безопасности нового сервера Rocky Linux.
Полезное упражнение
Выполните это на некритичном сервере сегодня, пока всё работает исправно.
sudo dnf install -y tree
sudo dnf history list tree
sudo dnf history info last
sudo dnf history undo last
rpm -q treeПоследняя команда покажет, действительно ли откат удалил пакет. Затем найдите пакет, для которого доступно несколько версий, используя sudo dnf list --showduplicates chrony или ту же команду для другого пакета, выполните его понижение версии (downgrade), а затем отмените это действие. Десять минут такой практики на запасном VPS полезнее любого чек-листа, так как в следующий раз, когда вам придётся это делать, сервис будет недоступен, а время будет ограничено.
FAQ
Как узнать, что изменилось после последнего обновления dnf?
sudo dnf history info last описывает самую последнюю транзакцию, а sudo dnf history list выводит нумерованный список, чтобы вы могли выбрать более раннюю. Чтобы отследить изменения конкретного пакета, выполните sudo dnf history list httpd. Журналы низкого уровня находятся в /var/log/dnf.log и /var/log/dnf.rpm.log; там следует искать информацию, если обновление произошло ночью и вам нужно уточнить время.
В чем разница между dnf history undo и dnf history rollback?
undo отменяет одну транзакцию, оставляя все последующие без изменений. rollback отменяет все транзакции, выполненные после указанного ID, возвращая состояние пакетов к моменту завершения этой транзакции. Используйте undo, если знаете, какая именно операция привела к сбою. Используйте rollback, если с момента последнего стабильного состояния прошло несколько операций и вы не можете выделить одну конкретную.
Почему dnf history undo завершается ошибкой после минорного обновления дистрибутива?
Потому что для отмены необходимо повторно загрузить старые версии пакетов, а dnf не хранит их локальные копии. Основные репозитории содержат только текущую минорную версию, поэтому, как только 9.5 сменяется на 9.6, предыдущие сборки перемещаются в архив. Проверьте наличие версии с помощью sudo dnf list --showduplicates и имени пакета. Если старая версия не найдена, добавьте архивный репозиторий как отключенный, загрузите пакет из него с помощью dnf download и передайте полученный файл в sudo dnf downgrade.
Можно ли откатить обновление ядра в Rocky или AlmaLinux?
Да, это самый простой случай, так как Enterprise Linux 9 сохраняет несколько установленных ядер, а не заменяет их. rpm -q kernel показывает список ядер на диске, sudo grubby --info=ALL выводит записи загрузчика, а sudo grubby --set-default=/boot/vmlinuz-<version> позволяет выбрать ядро для следующей загрузки. Установите значение по умолчанию до перезагрузки, так как для выбора записи из меню загрузчика потребуется консоль провайдера, а не SSH.
Как предотвратить повторную установку проблемного обновления сегодня ночью?
Зафиксируйте версию пакета. Установите python3-dnf-plugin-versionlock, затем выполните sudo dnf versionlock add с именем пакета; это запишет установленную версию в /etc/dnf/plugins/versionlock.list. Без этой фиксации удаленная версия останется самой новой в репозитории, и следующее обновление установит её снова. Запишите дату и причину в файл блокировки, так как фиксация также блокирует обновления безопасности для этого пакета.