Я использую Ansible для проверки хостов на необходимость их перезагрузки, если /vmlinuz
ядро не разрешается в uname -r
.
Условие if
всегда определяет перезагрузку, даже если тестовая машина была перезагружена и ядро разрешается в то же ядро:
если [ $(readlink -f /vmlinuz) != /boot/vmlinuz-$(uname -r) ]; тогда echo 'reboot'; иначе echo 'no'; fi
- name: Check for reboot hint.
shell: if [ $(readlink -f /vmlinuz) != /boot/vmlinuz-$(uname -r) ]; then echo 'reboot'; else echo 'no'; fi
ignore_errors: true
register: reboot_hint
- name: Rebooting ...
command: shutdown -r now "Ansible kernel update applied"
async: 0
poll: 0
ignore_errors: true
when: kernelup|changed or reboot_hint.stdout.find("reboot") != -1
register: rebooting
- name: Wait for thing to reboot...
pause: seconds=45
when: rebooting|changed
решение1
Вы можете надежно определить последнюю установленную версию ядра с помощью следующего запроса rpm:
rpm -q kernel --queryformat '%{installtime} %{version}-%{release}.%{arch}\n' | sort -n -k1 | tail -1 | cut -d ' ' -f 2
Пример вывода на RHEL 7:
3.10.0-229.11.1.el7.x86_64
Теперь просто проверьте, совпадают ли выходные данные uname -r
:
3.10.0-229.1.2.el7.x86_64
В данном примере это не соответствует и требуется перезагрузка.
Вы можете использовать test для сравнения строк:
if [ "`rpm -q kernel --queryformat '%{installtime} %{version}-%{release}.%{arch}\n' | sort -n -k1 | tail -1 | cut -d ' ' -f 2`" = "`uname -r`" ]; then echo "latest kernel already booted."; else echo "new kernel. reboot required."; fi
решение2
Ответ на 2021 год
Как упомянул @kawing-chiu вих ответ, dnf
теперь имеет needs-restarting
модуль, который делает именно то, что требуется в вопросе. Он определяет, были ли обновлены системные пакеты с момента последней загрузки, хотя это не ограничивается только изменениями ядра. Такое поведение, возможно, лучше, чем простое сравнение версии ядра с установленными пакетами.
Модуль needs-restarting
dnf недоступен через ansible.builtin.dnf
модуль Ansible, но его можно вызвать через ansible.builtin.shell
или ansible.builtin.command
по его псевдониму needs-restarting -r
, более напрямую с помощью dnf needs-restarting -r
или даже более явно с помощью /usr/bin/dnf needs-restarting -r
.
Флаг -r
, похоже, не требует привилегий root и просто сообщает, нужна ли перезагрузка. Код возврата — 0
если перезагрузка не нужна, а 1
если нужна. Поэтому мы должны иметь возможность использовать такую задачу, как эта, которая адаптирована из предложеннойДжоэль Каттин:
- name: Check if a reboot is required
ansible.builtin.command: needs-restarting -r
register: reg_reboot_required
ignore_errors: yes
failed_when: false
changed_when: reg_reboot_required.rc != 0
notify:
- Reboot server
Вам также понадобится обработчик с именем или прослушивание Reboot server
для выполнения задачи перезагрузки. Что-то вроде этого подойдет:
- name : Reboot server
ansible.builtin.reboot:
msg: "Reboot initiated by Ansible after OS update"
reboot_timeout: 3600
test_command: uptime
Надеюсь, этот ответ поможет всем, кто ищет решение этой проблемы.
решение3
СТАРАЯ тема, но она помогла мне собрать этот быстрый скрипт Ansible, который может кому-то помочь.
---
- hosts: allhosts
gather_facts: False
tasks:
- name: check latest kernel installed
shell: rpm -q kernel --queryformat '%{installtime} %{version}-%{release}.%{arch}\n' | sort -n -k1 | tail -1 | cut -d ' ' -f 2
register: kernel_installed_latest
- name: Check running kernel version
shell: uname -r
register: kernel_version
- fail:
msg: "latest kernel version {{kernel_installed_latest.stdout}} doesnt match running kernel {{kernel_version.stdout}}"
when: (kernel_installed_latest.stdout != kernel_version.stdout)
решение4
Другой альтернативой является выполнение обновлений ядра по отдельности и запуск обработчика для перезапуска системы, если требуется обновление ядра.
tasks
- name: Upgrade all packages, excluding kernel
ansible.builtin.yum:
name: '*'
state: latest
exclude: kernel*
- name: Upgrade kernel
ansible.builtin.yum:
name: 'kernel*'
state: latest
notify: restart host
handlers:
- name: restart host
ansible.builtin.reboot: