2021年の答え

2021年の答え

/vmlinuzカーネルが に解決されない場合にホストを再起動する必要があるかどうかを確認するために、Ansible を使用していますuname -r

ifただし、テスト マシンが再起動され、カーネルが同じカーネルに解決されているにもかかわらず、常に再起動が識別されるという条件があります。

if [ $(readlink -f /vmlinuz) != /boot/vmlinuz-$(uname -r) ]; then echo 'reboot'; else 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。これは、システム パッケージが前回の起動以降に更新されたかどうかを判断しますが、カーネルの変更だけに限定されるわけではありません。この動作は、カーネル バージョンとインストール済みパッケージを単純に比較するよりも優れていると言えます。

dnfneeds-restartingモジュールは Ansible モジュール経由ではアクセスできませんが、またはそのエイリアス 経由で、または で直接的に、あるいは でより明示的にansible.builtin.dnf呼び出すことができます。ansible.builtin.shellansible.builtin.commandneeds-restarting -rdnf needs-restarting -r/usr/bin/dnf needs-restarting -r

この-rフラグはルート権限を必要としないようで、再起動が必要かどうかを報告するだけです。再起動が必要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:

関連情報