2021 年答案

2021 年答案

/vmlinuz如果内核无法解析,我正在使用 Ansible 检查主机是否需要重新启动uname -r

尽管测试机器已经重新启动并且内核解析为同一个内核,但情况if总是识别出重新启动:

如果 [ $(readlink -f /vmlinuz) != /boot/vmlinuz-$(uname -r) ]; 则回显“rebo​​ot”; 否则回显“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

在这个例子中,它不匹配,需要重新启动。

您可以使用测试来比较字符串:

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模块可以满足这个问题的需要。它确定自上次启动以来系统软件包是否已更新,尽管这不仅限于内核更改。这种行为可以说比简单地将内核版本与已安装的软件包进行比较要好。

dnf模块needs-restarting无法通过ansible.builtin.dnfAnsible 模块访问,但可以通过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:

相关内容