Представьте: вы автоматизировали обновление серверов через Ansible, всё работает как часы, но после ребута скрипт внезапно падает с загадочной ошибкой про отсутствующий файл в /proc
. Знакомо? Давайте разберёмся, почему это происходит и как заставить ваш playbook вести себя предсказуемо даже в таких ситуациях.
Почему возникает ошибка «No such file or directory»
Команда dnf needs-restarting
проверяет, какие службы требуют перезапуска после обновления пакетов. Когда вы добавляете флаг -r
, она также определяет, нужна ли полная перезагрузка системы. Проблема возникает из-за конкурентного доступа к данным процессов в момент их завершения.
Вот как это работает под капотом:
1. dnf
получает список PID (идентификаторов процессов), которые используют обновлённые библиотеки.
2. Для каждого PID проверяет наличие файлов в /proc/[PID]/
:
– status
(общая информация о процессе)
– stat
(детали выполнения)
3. Если процесс завершается между проверкой существования PID и чтением /proc/[PID]/stat
, файл успевает исчезнуть – отсюда ошибка «No such file or directory».
Пример из вашего playbook: после перезагрузки Ansible сразу запускает проверку, но процесс с PID 771 (например, временный демон) уже завершился, а dnf всё ещё пытается прочитать его статистику.
Как исправить проблему в Ansible Playbook
Есть три подхода, которые можно комбинировать для надёжности:
1. Обновление dnf до версии 4.16.2+
В более новых версиях dnf [обрабатывает исключения](https://github.com/rpm-software-management/dnf/commit/41da7f09bc73b4f34bc90c0b7dca058780bee8e9) при отсутствии файлов в /proc
. Установите актуальный пакет:
- name: Обновление dnf
command: dnf update -y dnf
2. Добавление задержки перед проверкой
Дайте системе время завершить процессы после перезагрузки. Используйте модуль wait_for_connection
с таймаутом:
- name: Ждём стабилизации системы после ребута
wait_for_connection:
delay: 30 # Пауза 30 секунд перед проверкой
timeout: 180
3. Игнорирование ошибок для не-critical задач
Если проверка needs-restarting
не критична для работы, добавьте ignore_errors
(но это временное решение!):
- name: Проверка необходимости перезапуска служб
command: dnf needs-restarting
args:
warn: false
register: result
ignore_errors: yes # Пропускаем ошибки, но логируем их
changed_when: false
Бонус: Альтернатива для dnf needs-restarting
Если ошибка persist (упорно повторяется), попробуйте использовать needrestart
– отдельную утилиту с более гибкими настройками:
dnf install needrestart
needrestart -r a # -r a = автоматический режим
В Ansible task это будет выглядеть так:
- name: Проверка через needrestart
command: needrestart -r a
args:
warn: false
Что проверить дополнительно:
– Логи systemd: journalctl -u dnf-upgrade.service
– ищите записи о завершении процессов.
– Версия ядра: На Oracle Linux 9 иногда возникают конфликты с SELinux (попробуйте временно отключить setenforce 0
для теста).
– Шаблон обработки ошибок: Создайте отдельный handler для перезапуска failed задач с экспоненциальной задержкой (этот приём называется “retry with backoff”).