Rocky/Almaで再起動が必要な更新を確認する方法
dnf update後も古いカーネルやライブラリが動作する理由を解説します。needs-restartingで、再起動が必要な更新とサービス再起動で済む更新を確認できます。
Rocky Linux と AlmaLinux で再起動が必要な更新
Rocky Linux と AlmaLinux では、dnf update が新しいファイルをディスクに書き込み、そこで処理を終了します。起動中のカーネルは動作し続けます。すでにライブラリを開いているプロセスは、開いた時点のコピーを使い続けます。Linux は、そのファイルを保持している最後のプロセスが終了するまで、古いファイルをディスク上で保持するためです。そのため、マシンが利用可能な更新はないと報告していても、更新によって置き換えられたコードが実行されている場合があります。両方のディストリビューションは同じ Red Hat ソースを再ビルドしているため、この点に違いはありません。Rocky と Alma の選択は、ここで確認できる内容ではなく、互換性の方針と CPU サポートを基準に決まります。以下のコマンドが CentOS のマシンで使われていたものと同じなのも偶然ではありません。両プロジェクトは 2020 年の Stream 発表後に CentOS の代替として構築されたためです。
再起動が必要な更新と、サービスの再起動だけで済む更新を判断するには、マシンに確認する必要があります。その答えを返すコマンドが needs-restarting です。更新は 3 つの層に分類されます。カーネルと一部の主要パッケージでは、完全な再起動が必要です。通常のライブラリ更新では、それらを使用するサービスを再起動する必要があります。それ以外の更新は、RPM の処理が完了した時点ですでに適用されています。
Install needs-restarting
needs-restarting は DNF のプラグインです。このプラグインは dnf-plugins-core に含まれており、ほとんどの Rocky および Alma のインストール環境にすでに存在します。/usr/bin/needs-restarting コマンドは、dnf-utils に含まれる小さなラッパーです。
sudo dnf install -y yum-utils
needs-restarting --helpどちらの表記でも同じコードが実行されます。ラッパーが次の DNF サブコマンドを呼び出すためです。
needs-restarting -r
dnf needs-restarting -rどちらのパッケージもディストリビューション独自のリポジトリから提供されるため、この用途で EPEL または CRB リポジトリを有効にする必要はありません。
Rocky Linux 10 および AlmaLinux 10 系では、dnf は DNF 5 で、needs-restarting は dnf5-plugins パッケージに含まれる独自のコマンドです。この場合、オプションなしで dnf needs-restarting を実行すると、再起動が必要かどうかが直接表示されます。-r も引き続き受け付けられますが、マニュアルには効果がなく、DNF 4 用のスクリプトを引き続き動作させるためだけに存在すると記載されています。
Tier 1: 再起動が必要な更新
まず再起動チェックを実行します。このチェックは RPM データベースとシステムの起動時刻だけを読み取り、それ以外にはアクセスしません。そのため高速で、root も必要ありません。
needs-restarting -r起動後に重要な変更がない場合は、次の 2 行を出力します。
No core libraries or services have been updated since boot-up.
Reboot should not be necessary.変更がある場合は、Core libraries or services have been updated since boot-up:、検出したパッケージ名、続いて次の内容を出力します。
Reboot is required to fully utilize these updates.
More information: https://access.redhat.com/solutions/27943終了コードも同じ結果を示します。再起動が不要な場合は 0、必要な場合は 1 です。スクリプトではこの終了コードを利用します。
if ! needs-restarting -r >/dev/null; then
logger -t updates "reboot pending on $(hostname -s)"
fiここでの終了コード 1 は正常な結果であり、失敗ではありません。set -e のもとでは、保護されていない needs-restarting -r によって、その行でスクリプトが終了します。そのため、上の例では if で囲んでいます。
再起動が必要と判定されるパッケージは、プラグイン内にハードコードされた短い一覧に含まれています。現在のバージョンでは、kernel、kernel-core、kernel-rt、glibc、linux-firmware、systemd、dbus、dbus-broker、dbus-daemon、microcode_ctl が含まれます。古いプラグインのビルドでは一覧が少し短い場合があるため、推測せずに実際の一覧を確認してください。
各エントリが一覧に含まれる理由は、明確に説明できます。新しい kernel パッケージは /boot と /lib/modules にファイルを書き込むだけです。実行中の kernel 自体を置き換えることはできないため、起動するまで変更は反映されません。システム上のすべてのプロセスは glibc にリンクしています。そのため「影響を受けるサービスを再起動する」とは PID 1 も再起動することになり、再起動のほうが安全です。dbus と dbus-broker はシステム上のすべてのクライアント接続を処理しているため、稼働中のマシンで bus を停止すると、接続中のクライアントが停止します。linux-firmware と microcode_ctl は起動時に読み込まれます。また VPS では、microcode による変更は通常、確認可能な影響を及ぼしません。物理 CPU はハイパーバイザーのホストが管理しているためです。
独自のパッケージを追加することもできます。/etc/dnf/plugins/needs-restarting.d/ 配下にある .conf ファイルは、1 行に 1 つのパッケージ名を記載した一覧として読み込まれます。記載した名前は再起動対象の一覧に追加されます。
echo 'openssl-libs' | sudo tee /etc/dnf/plugins/needs-restarting.d/openssl.confこれは修正ではなく、ポリシー上の選択です。「TLS ライブラリが変更されたら、そのライブラリを読み込んだすべてのサービスを特定するよりも、再起動する」という方針を示します。
再起動のヒントが実際に何に基づいているか
needs-restarting -r は、実行中のカーネルバージョンと、インストール済みの最新カーネルを比較しているわけではありません。タイムスタンプを比較しています。対象となるコアパッケージごとに RPM のインストール時刻を読み取り、システムの起動時刻と比較します。コアパッケージが最後の起動後にインストールされていれば、結果は「再起動が必要」です。起動時刻は、利用可能な場合は D-Bus 経由で systemd の UnitsLoadStartTimestamp から取得します。それ以外の場合は、/proc/1 の更新時刻と /proc/stat の btime フィールドのうち、後の時刻を使用します。
この仕組みには、知っておくべき点が 1 つあります。カーネルをインストールして再起動した後、ブートのデフォルトが固定されているため古いカーネルで起動した場合、インストール時刻は起動時刻より前になります。そのため needs-restarting -r は何も表示しなくなります。これは、needs-restarting -r 自身が尋ねている問いには正しく答えています。しかし、それはあなたが確認したい問いではありません。カーネルは別途確認してください。
uname -r
rpm -q --last kernel
sudo grubby --default-kernel最初のコマンドは、現在実行中のカーネルを表示します。rpm -q --last kernel の 1 行目は、最後にインストールされたカーネルです。grubby --default-kernel は、次回にブートローダーが選択する項目を表示します。この 3 つの結果が一致しない場合は、コンソール経由で接続できないマシンを再起動する前に、ブートのデフォルトを修正してください。
Tier 2: サービスの再起動が必要な更新
RPM が共有ライブラリを置き換えると、古いファイルのリンクを解除して新しいファイルを書き込みます。すでに古いファイルをメモリーマッピングしているプロセスは、古い inode を保持したまま、古いコードを実行し続けます。openssl-libs が最も重要なケースです。libcrypto の修正は、その Web サーバーを再起動して初めて Web サーバーに反映されます。
sudo needs-restarting -sこれは、サービスの起動後に、そのサービス自身のファイルまたは依存関係にあるファイルが更新された systemd サービスを一覧表示します。sudo を使用します。root で実行しない場合、このツールは自分のプロセスに対応する /proc エントリしか読み取れません。そのため、実際より少なく表示され、短い一覧が問題のない状態に見えてしまいます。
sudo needs-restarting
sudo needs-restarting --exclude-services1 つ目のコマンドは、影響を受けるすべてのプロセスの PID とコマンドラインを表示します。2 つ目のコマンドは、すでに systemd サービスで管理されているプロセスを除外します。残るのは、ログインシェル、tmux セッション、cron ジョブ、手動で起動したプロセスです。これらは自動的には再起動されません。
一覧にあるサービスが再起動ではなく再起動 tier のパッケージにも該当する場合、ツールはその上に Warning: The following services should not be restarted but require a reboot: を表示します。これは文字どおりに解釈し、サービスを再起動する代わりにシステムを再起動してください。
残りのサービスは 1 つずつ再起動し、次へ進む前にそれぞれを確認します。
sudo systemctl restart nginx
systemctl status nginx一覧を systemctl restart にパイプしないでください。SSH セッションが切断される原因になります。RHEL 系では、sshd.service が KillMode=process とともに提供されます。そのため、待ち受け中のデーモンにシグナルを送信し、接続ごとのプロセスはそのままにして、開いているセッションを維持します。systemctl cat sshd | grep KillMode を使って、自分の環境でもこの動作を確認してください。それでも、初回は必ず 2 つ目のセッションを開いたままにしてください。
DNF を使わずに同じプロセスを確認することもできます。関係するファイルパスを確認したい場合に便利です。
sudo dnf install -y lsof
sudo lsof -n +c 0 2>/dev/null | grep -w DELDEL は、ディスクから削除されたメモリーマッピング済みファイルを示します。操作する前にパスを確認してください。削除済みの一時ファイルやメモリーバックドファイルもここに表示されますが、それらを理由に再起動する必要はありません。
Tier 3: その他すべて
ほとんどの更新はここに該当し、追加の対応は必要ありません。curl、tar、vim、または dnf 自体のように、コマンドの起動時にだけファイルが読み込まれるパッケージは、RPM の処理が完了した時点で完全に適用されます。次回の実行時に新しいバイナリが読み込まれるためです。設定ファイル、スクリプト、ドキュメント、データパッケージも同様に動作します。needs-restarting にこれらが表示されることはありません。この表示がないことが、検出漏れではなく正しい結果です。
この層で注意が必要なのは、反映に要する時間です。更新前に起動したプロセスは、パッケージの変更内容がどれほど小さくても、終了するまで古い実行ファイルを使い続けます。まさにそのために sudo needs-restarting --exclude-services があります。
dnf-automatic を使用するマシンに未適用の修正が数週間残る理由
ここで、3 つの層が単なる知識ではなくなります。dnf-automatic による自動更新はタイマーでパッケージをインストールします。/etc/dnf/automatic.conf のデフォルトの reboot 設定は never です。apply_updates = yes と reboot = never の設定では、マシンが 6 週間で 6 回の kernel 更新と glibc の修正をインストールしても、0 週目に起動した kernel と C library を使い続けることがあります。更新ログには問題がありません。しかし、実行中のシステムには更新内容が反映されていません。
/etc/dnf/automatic.conf に次の 3 行を追加します。
[commands]
upgrade_type = security
apply_updates = yes
reboot = when-needed
reboot_command = "shutdown -r +5 'Rebooting after applying package updates'"reboot には never、when-changed、when-needed を指定できます。never がデフォルトで、再起動の判断はすべて管理者に委ねられます。when-changed はパッケージを変更したトランザクションの後に再起動するため、単純ですが動作を予測しやすい設定です。when-needed は、適用したトランザクションに再起動が必要かどうかを DNF に確認します。そのため、ユーザー空間だけを更新する夜間処理では再起動しません。実際に再起動を実行するのは reboot_command です。デフォルトでは、ログイン中のユーザーに 5 分前に警告します。random_sleep とタイマーのスケジュールを、マシンの再起動を監視できる時間帯に設定してください。
systemctl list-timers 'dnf-*' で有効にした unit を確認します。dnf-automatic には複数の variant があり、動作はすべて同じではありません。そのため、設定ファイルだけでは何が実行されるのか分かりません。
スケジュール実行の後は、ログではなくマシンに確認します。
needs-restarting -r; echo "exit: $?"
uname -r
rpm -q --last kernel | head -1再起動の時間を設定できない場合は、VPS での live kernel patching がもう 1 つの方法です。再起動せずに、実行中の kernel へ一部の kernel 修正を適用できます。ただし、対象は kernel 問題の一部に限られ、glibc やサービスには対応しません。そのため、再起動をなくす方法ではなく、再起動の間隔を延ばす方法として扱ってください。再起動するときは意図的に実行し、マシンが応答するまでログインしたままにします。kernel 更新は、マシンが復帰しない最も一般的な原因だからです。コンソールアクセスのないマシンを再起動する前に、VPS が kernel 更新後に起動しない場合の対処方法を確認してください。また、再起動の確認を 定期的なサーバー保守チェックリスト に組み込み、インシデント後にだけ思い出す作業にならないようにします。
Ubuntu と Debian で同じ処理を行う
混在するサーバー群では、それぞれに対応する方法が必要です。Ubuntu と Debian では、再起動を示すフラグはコマンドではなくファイルです。パッケージスクリプトが /run/reboot-required を作成し、/run/reboot-required.pkgs にそのファイルを要求したパッケージが一覧表示されるため、[ -f /run/reboot-required ] は needs-restarting -r に相当する単純な確認方法です。古いドキュメントでは /var/run/reboot-required と記載されていますが、これは同じファイルを指します。/var/run が /run へのシンボリックリンクだからです。サービス側は needrestart です。最近の Ubuntu Server のリリースではデフォルトでインストールされ、apt upgrade の実行時に動作します。また、sudo needrestart -r l を単独で実行すると、何も変更せずに再起動が必要な対象を一覧表示できます。自動更新に関する問題も同じで、解決方法も同じです。Ubuntu の unattended-upgrades では、/etc/apt/apt.conf.d/50unattended-upgrades に Unattended-Upgrade::Automatic-Reboot "true"; と Unattended-Upgrade::Automatic-Reboot-Time "02:00"; を指定します。
障害パターンと確認できる内容
needs-restarting: command not foundは、yum-utilsがインストールされていないことを示します。yum-utilsをインストールするか、dnf-plugins-coreが存在すればすぐに動作するdnf needs-restartingを代わりに呼び出します。- エラーメッセージを表示せず、再起動チェックで停止するスクリプトは、
set -eで終了コード 1 になっています。このコードは「再起動が必要」という意味です。そのため、スクリプトを終了させるのではなく、この終了コードを分岐処理します。 - ライブラリの更新直後に
needs-restarting -sが何も表示しない場合は、通常、sudoなしで実行しています。root でなければ、自分のプロセスしか確認できません。 needs-restarting -rが再起動不要と報告し、uname -rに古いバージョンが表示される場合は、古い kernel で起動しています。このチェックはインストール時刻と起動時刻を比較しますが、どちらも現在の起動より前のものです。grubby --default-kernelを確認してください。- 再起動した数分後、次回の実行時にサービスが再び起動している場合は、通常、別の仕組みがサービスを再起動しているか、unit が正常に復帰していません。もう一度再起動する前に、その unit の
systemctl statusを確認してください。
FAQ
Rocky Linux で dnf update を実行すると、サービスは再起動しますか?
原則として、再起動しません。トランザクションによってファイルが書き込まれ、処理が終了します。ただし、一部のパッケージには、アップグレード時に自身のサービスを再起動する RPM scriptlet が含まれています。そのため、動作はシステム全体で保証されるものではなく、パッケージごとに異なります。scriptlet の動作にかかわらず、サービスの起動後にそのサービス自身または依存関係にあるファイルが変更されたサービスを列挙する sudo needs-restarting -s を、判断の基準にしてください。
新しい kernel をインストールしたのに、needs-restarting -r が再起動不要と表示するのはなぜですか?
RPM による一部の主要パッケージのインストール時刻を、システムの起動時刻と比較しているためです。実行中の kernel のバージョンと、インストール済みで最も新しい kernel のバージョンを比較しているわけではありません。kernel をインストールして再起動した後、bootloader の既定値が古い kernel を指しているために、その kernel で起動した場合、インストール時刻は起動時刻より前になります。そのため、チェックでは問題が検出されません。実際の状態を確認するには、uname -r、rpm -q --last kernel、sudo grubby --default-kernel を実行してください。
Rocky と Alma で再起動のヒントを発生させるパッケージはどれですか?
plugin 内にハードコードされた一覧があり、現在のバージョンでは kernel、kernel-core、kernel-rt、glibc、linux-firmware、systemd、dbus、dbus-broker、dbus-daemon、microcode_ctl が登録されています。この一覧は拡張できます。/etc/dnf/plugins/needs-restarting.d/ に .conf ファイルを配置し、1 行に 1 つずつパッケージ名を記述すると、それらの名前も再起動の判定対象になります。
dnf-automatic は単独でサーバーを再起動できますか?
はい。/etc/dnf/automatic.conf の [commands] セクションで reboot = when-needed を設定すると、適用したトランザクションで再起動が必要な場合に限り、サーバーを再起動します。when-changed はパッケージに変更があった場合に再起動し、never が既定値です。再起動方法は reboot_command で制御します。既定値では、ログイン中のユーザーに 5 分前の警告が表示されます。起動後の復旧手段を確保できるマシンでのみ有効にしてください。コンソールにアクセスできない VPS で無人再起動が発生すると、復旧が困難になります。
needs-restarting はコンテナ内のプロセスを検出しますか?
実用上は検出できません。実行中のプロセスをホストの RPM データベースと照合するため、コンテナイメージ内のパッケージはそのデータベースに登録されていません。そのため、イメージに組み込まれた古いライブラリは表示されません。イメージを再ビルドして再デプロイしてください。一方、ホスト側の状態は引き続き重要です。コンテナランタイムと、コンテナが共有する kernel はホストのパッケージであり、これらは検出されます。