Ответ на 2021 год

Ответ на 2021 год

Я использую 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-restartingdnf недоступен через 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:

Связанный контент