Rocky Linux, AlmaLinux: update nào cần reboot?
dnf update có thể vẫn chạy kernel và library cũ. Dùng needs-restarting để biết chính xác lúc nào cần reboot máy, lúc nào chỉ cần restart service.
Bản cập nhật nào cần reboot trên Rocky Linux và AlmaLinux
Trên Rocky Linux và AlmaLinux, dnf update ghi các file mới vào disk rồi dừng lại. Kernel mà bạn đã boot vẫn tiếp tục chạy. Mỗi process đã mở một library vẫn dùng bản copy mà nó đã mở, vì Linux giữ file cũ trên disk cho đến khi process cuối cùng đang giữ file đó thoát. Vì vậy, máy có thể báo không còn update nào khả dụng nhưng vẫn đang chạy code mà các update đó đã thay thế. Điều này không khác nhau giữa hai distribution, vì cả hai đều build lại từ cùng các source của Red Hat. Việc chọn Rocky hay Alma phụ thuộc vào cam kết tương thích và hỗ trợ CPU, không phụ thuộc vào bất kỳ điều gì bạn sẽ thấy trong phần này. Các command bên dưới cũng chính là những command mà một máy CentOS từng dùng. Đây không phải là sự trùng hợp: cả hai project đều được xây dựng để thay thế CentOS sau thông báo Stream năm 2020.
Bản update nào cần reboot và bản nào chỉ cần restart service là câu hỏi bạn phải hỏi chính máy đó. Command trả lời câu hỏi này là needs-restarting. Các update được chia thành 3 tầng. Kernel và một danh sách ngắn các package cốt lõi cần reboot toàn bộ máy. Các bản update library thông thường cần restart những service đang sử dụng chúng. Mọi thứ khác đã được áp dụng ngay khi RPM chạy xong.
Cài đặt needs-restarting
needs-restarting là một DNF plugin. Plugin này nằm trong dnf-plugins-core, gói thường đã có sẵn trên hầu hết các bản cài Rocky và Alma. Lệnh /usr/bin/needs-restarting là một wrapper nhỏ được cung cấp trong dnf-utils.
sudo dnf install -y yum-utils
needs-restarting --helpHai cách viết này chạy cùng một đoạn code vì wrapper gọi DNF subcommand:
needs-restarting -r
dnf needs-restarting -rCả hai package đều đến từ repository riêng của distribution, nên bạn không cần bật EPEL hoặc repository CRB cho việc này.
Trên dòng Rocky Linux 10 và AlmaLinux 10, dnf là DNF 5 và needs-restarting là một command riêng của nó, thuộc package dnf5-plugins. Ở đó, dnf needs-restarting không có option sẽ trả lời trực tiếp việc có cần reboot hay không. -r vẫn được chấp nhận, và manual ghi rõ option này không có tác dụng, chỉ tồn tại để các script của DNF 4 tiếp tục hoạt động.
Bậc 1: các bản cập nhật cần reboot
Trước tiên, hãy chạy kiểm tra reboot. Lệnh này chỉ đọc RPM database và thời điểm hệ thống boot, không đọc gì khác, nên chạy nhanh và không cần root.
needs-restarting -rKhi không có thay đổi quan trọng nào kể từ lần boot, lệnh in ra 2 dòng:
No core libraries or services have been updated since boot-up.
Reboot should not be necessary.Khi có thay đổi, lệnh in ra Core libraries or services have been updated since boot-up:, sau đó là tên các package tìm thấy, rồi:
Reboot is required to fully utilize these updates.
More information: https://access.redhat.com/solutions/27943Exit code chứa cùng một kết quả: 0 khi không cần reboot, 1 khi cần reboot. Đây là phần bạn dùng để viết script.
if ! needs-restarting -r >/dev/null; then
logger -t updates "reboot pending on $(hostname -s)"
fiExit code 1 ở đây là kết quả bình thường, không phải lỗi. Với set -e, needs-restarting -r không được bảo vệ sẽ kết thúc script ngay tại dòng đó. Vì vậy, ví dụ trên bọc lệnh này trong if.
Các package làm cho kết quả kiểm tra yêu cầu reboot là một danh sách hard-code ngắn nằm trong plugin. Ở các phiên bản hiện tại, danh sách này gồm kernel, kernel-core, kernel-rt, glibc, linux-firmware, systemd, dbus, dbus-broker, dbus-daemon và microcode_ctl. Các bản build plugin cũ có danh sách ngắn hơn một chút, nên hãy kiểm tra bản đang dùng thay vì giả định.
Mỗi mục có mặt trong danh sách vì một lý do rõ ràng. Package kernel mới chỉ ghi file vào /boot và /lib/modules, còn kernel đang chạy không thể tự thay thế trong khi vẫn hoạt động, nên thay đổi chỉ có hiệu lực sau khi boot kernel đó. Mọi process trên máy đều link đến glibc. Vì vậy, “restart các service bị ảnh hưởng” cũng đồng nghĩa với restart cả PID 1, còn reboot là cách an toàn để thực hiện việc đó. dbus và dbus-broker xử lý mọi kết nối client trên hệ thống, nên dừng bus trên máy đang chạy sẽ làm gián đoạn các client đang kết nối. linux-firmware và microcode_ctl được load khi boot. Trên VPS, phần microcode thường không tạo ra thay đổi nào có thể quan sát được vì hypervisor host quản lý CPU vật lý.
Bạn có thể thêm package riêng. Mọi file .conf trong /etc/dnf/plugins/needs-restarting.d/ đều được đọc như một danh sách tên package, mỗi dòng một tên. Các tên đó sẽ được thêm vào danh sách package yêu cầu reboot.
echo 'openssl-libs' | sudo tee /etc/dnf/plugins/needs-restarting.d/openssl.confĐó là một lựa chọn về policy, không phải cách sửa lỗi. Cách này có nghĩa là: “khi thư viện TLS thay đổi, tôi muốn reboot hơn là phải tìm và xử lý mọi service đã map thư viện đó”.
Thực tế gợi ý reboot được suy ra như thế nào
needs-restarting -r không so sánh phiên bản kernel đang chạy với kernel mới nhất đã cài. Nó so sánh timestamp. Với từng package trong danh sách core đó, nó đọc thời điểm cài RPM rồi so sánh với thời điểm hệ thống boot. Nếu một core package được cài sau lần boot gần nhất, kết quả là “reboot required”. Thời điểm boot được lấy từ UnitsLoadStartTimestamp của systemd qua D-Bus khi có thể, hoặc lấy giá trị muộn hơn giữa thời gian sửa đổi của /proc/1 và trường btime trong /proc/stat.
Cơ chế này có một hệ quả cần biết. Nếu bạn cài kernel, reboot, rồi hệ thống quay lại kernel cũ hơn vì boot default đang bị ghim, thời điểm cài kernel lúc này đã cũ hơn thời điểm boot và needs-restarting -r sẽ không còn cảnh báo. Nó đang trả lời đúng câu hỏi của chính nó. Nhưng đó không phải câu hỏi bạn đã hỏi. Hãy kiểm tra kernel riêng.
uname -r
rpm -q --last kernel
sudo grubby --default-kernelLệnh đầu tiên in ra kernel đang chạy. Dòng đầu tiên của rpm -q --last kernel là kernel được cài gần đây nhất. grubby --default-kernel in ra kernel mà bootloader sẽ chọn trong lần khởi động tiếp theo. Nếu 3 giá trị này không khớp, hãy sửa boot default trước khi reboot một máy mà bạn không thể truy cập qua console.
Tầng 2: các bản cập nhật cần restart service
Khi RPM thay thế một shared library, nó unlink file cũ rồi ghi file mới. Process đã map file cũ vẫn giữ inode cũ và tiếp tục thực thi code cũ. openssl-libs là trường hợp quan trọng nhất: một bản sửa lỗi trong libcrypto chỉ có hiệu lực trên web server sau khi web server đó restart.
sudo needs-restarting -sLệnh này liệt kê các systemd service có file của chính service đó hoặc file của dependency được cập nhật sau khi service khởi động. Dùng sudo. Nếu không chạy với root, tool chỉ đọc được các entry /proc cho process của chính bạn, nên kết quả bị thiếu mà không báo lỗi; danh sách ngắn trông như một tin tốt.
sudo needs-restarting
sudo needs-restarting --exclude-servicesLệnh đầu tiên in PID và command line của mọi process bị ảnh hưởng. Lệnh thứ hai loại các process đã được một systemd service quản lý, để lại login shell, các session tmux, cron job và mọi thứ bạn tự khởi chạy. Những process đó không tự restart.
Nếu một service trong danh sách cũng thuộc package cấp reboot, tool sẽ in Warning: The following services should not be restarted but require a reboot: phía trên service đó. Hãy hiểu đúng theo nghĩa đen và reboot thay vì restart service.
Restart từng service còn lại một lần, rồi kiểm tra service đó trước khi chuyển sang service tiếp theo.
sudo systemctl restart nginx
systemctl status nginxKhông pipe danh sách vào systemctl restart. SSH session của chính bạn là lý do. Trên họ RHEL, sshd.service đi kèm KillMode=process, nên khi restart, nó gửi signal cho daemon đang listen và giữ nguyên các process xử lý từng connection; session đang mở vẫn tồn tại. Xác nhận điều này trên máy của bạn bằng systemctl cat sshd | grep KillMode, và lần đầu tiên vẫn nên giữ một session thứ hai mở.
Bạn cũng có thể tìm các process tương tự mà không cần DNF. Cách này hữu ích khi bạn muốn xem các path của file liên quan:
sudo dnf install -y lsof
sudo lsof -n +c 0 2>/dev/null | grep -w DELDEL đánh dấu một file đã được map nhưng đã bị xóa khỏi disk. Đọc các path trước khi thực hiện thao tác. File tạm đã xóa và file nằm trên memory cũng xuất hiện ở đây; chúng không phải là lý do để restart bất kỳ service nào.
Tầng 3: mọi trường hợp còn lại
Hầu hết các bản cập nhật thuộc nhóm này và không cần làm gì thêm. Một package có các file chỉ được đọc khi command khởi động, chẳng hạn như curl, tar, vim hoặc chính dnf, được áp dụng đầy đủ khi RPM chạy xong, vì lần chạy tiếp theo sẽ đọc binary mới. Các file cấu hình, script, tài liệu và package dữ liệu cũng hoạt động như vậy. needs-restarting sẽ không đề cập đến bất kỳ thành phần nào trong số đó. Việc không có thông báo là kết quả đúng, không phải do bỏ sót phát hiện.
Điểm cần lưu ý duy nhất ở tầng này là thời gian chạy. Một process đã khởi động trước khi cập nhật sẽ tiếp tục chạy executable cũ cho đến khi thoát, dù package đó có vẻ không đáng kể. sudo needs-restarting --exclude-services được dùng chính xác cho trường hợp này.
Vì sao máy chạy dnf-automatic có thể giữ các bản sửa lỗi chưa áp dụng trong nhiều tuần
Đây là lúc sự khác biệt giữa ba tầng không còn là chuyện lý thuyết. Cập nhật tự động bằng dnf-automatic cài package theo timer, còn giá trị mặc định của reboot trong /etc/dnf/automatic.conf là never. Khi dùng apply_updates = yes và reboot = never, máy có thể cài 6 bản cập nhật kernel và một bản sửa lỗi glibc trong 6 tuần nhưng vẫn chạy kernel và thư viện C mà nó đã boot từ tuần 0. Log cập nhật trông hoàn hảo. Hệ thống đang chạy không có những bản cập nhật đó.
Cách sửa là thêm 3 dòng vào /etc/dnf/automatic.conf:
[commands]
upgrade_type = security
apply_updates = yes
reboot = when-needed
reboot_command = "shutdown -r +5 'Rebooting after applying package updates'"reboot chấp nhận never, when-changed và when-needed. never là giá trị mặc định và để bạn tự quyết định mọi việc. when-changed reboot sau bất kỳ transaction nào làm thay đổi package. Cách này thô nhưng dễ dự đoán. when-needed hỏi DNF xem transaction vừa áp dụng có yêu cầu reboot hay không, nên một đêm chỉ cập nhật userspace sẽ không reboot. reboot_command là lệnh thực sự được chạy, còn giá trị mặc định sẽ cảnh báo người dùng đã đăng nhập trước 5 phút. Đặt random_sleep và lịch của timer để việc này diễn ra trong một khung giờ mà bạn có thể theo dõi máy khởi động lại.
Kiểm tra unit bạn đã enable bằng systemctl list-timers 'dnf-*'. dnf-automatic có nhiều biến thể được phát hành kèm theo và chúng không hoạt động giống nhau, nên chỉ xem file cấu hình thì chưa biết chính xác unit nào đang chạy.
Sau một lần chạy theo lịch, hãy hỏi trực tiếp máy thay vì chỉ xem log:
needs-restarting -r; echo "exit: $?"
uname -r
rpm -q --last kernel | head -1Nếu không thể sắp xếp thời điểm reboot, live kernel patching trên VPS là lựa chọn khác. Cách này áp dụng một số bản sửa lỗi kernel vào kernel đang chạy mà không cần reboot. Nó chỉ xử lý một phần các vấn đề của kernel và không xử lý glibc hoặc các service của bạn. Vì vậy, hãy xem đây là cách giãn thời gian giữa các lần reboot, không phải cách loại bỏ hoàn toàn việc reboot. Khi cần reboot, hãy thực hiện có chủ đích và duy trì phiên đăng nhập cho đến khi máy phản hồi, vì cập nhật kernel là nguyên nhân phổ biến nhất khiến máy không khởi động lại được. Hãy đọc cách xử lý khi VPS không boot sau khi cập nhật kernel trước khi reboot một máy không có quyền truy cập console, đồng thời đưa bước kiểm tra reboot vào checklist bảo trì server định kỳ để bạn không chỉ nhớ đến việc này sau khi xảy ra sự cố.
Cùng một tác vụ trên Ubuntu và Debian
Một fleet không đồng nhất cần các lệnh tương đương. Trên Ubuntu và Debian, cờ reboot là một file, không phải một command: các package script tạo /run/reboot-required, còn /run/reboot-required.pkgs liệt kê những package đã yêu cầu file này, vì vậy [ -f /run/reboot-required ] là lệnh tương đương trực tiếp của needs-restarting -r. Tài liệu cũ thường ghi /var/run/reboot-required. Đây là cùng một file, vì /var/run là symlink đến /run. Phía service là needrestart, được cài mặc định trên các bản Ubuntu Server gần đây. Service này chạy trong apt upgrade và có thể chạy riêng bằng sudo needrestart -r l để liệt kê những gì cần restart mà không thay đổi gì. Khoảng trống do automatic update tạo ra cũng giống như vậy, và cách khắc phục cũng giống nhau: unattended-upgrades trên Ubuntu nhận Unattended-Upgrade::Automatic-Reboot "true"; và Unattended-Upgrade::Automatic-Reboot-Time "02:00"; trong /etc/apt/apt.conf.d/50unattended-upgrades.
Các trường hợp lỗi và những gì bạn sẽ thấy
needs-restarting: command not foundcó nghĩa làyum-utilschưa được cài đặt. Hãy cài nó, hoặc gọidnf needs-restartingthay thế. Cách này hoạt động ngay khidnf-plugins-corecó mặt.- Script dừng tại bước kiểm tra reboot mà không báo lỗi là do
set -etrả về exit code 1. Mã này có nghĩa là “cần reboot”, vì vậy hãy xử lý nhánh này thay vì để nó kết thúc script. needs-restarting -skhông in gì ngay sau khi cập nhật library thường có nghĩa là bạn đã chạy nó mà không cósudo. Khi không có quyền root, nó chỉ thấy các process của chính bạn.needs-restarting -rbáo không cần reboot trong khiuname -rhiển thị version cũ có nghĩa là bạn đã boot bằng kernel cũ hơn. Lệnh kiểm tra so sánh thời điểm cài đặt với thời điểm boot, và cả hai thời điểm đó đều đã ở quá khứ. Hãy xemgrubby --default-kernel.- Một service xuất hiện lại trong lần chạy tiếp theo, chỉ vài phút sau khi bạn restart nó, thường là do một thành phần khác đang restart service đó, hoặc unit không khởi động lại thành công. Hãy đọc
systemctl statuscủa unit đó trước khi restart lần thứ hai.
FAQ
dnf update có khởi động lại service trên Rocky Linux không?
Theo nguyên tắc là không. Transaction ghi các file rồi kết thúc. Một số package có RPM scriptlet để khởi động lại service của chính chúng trong lúc upgrade, nên hành vi phụ thuộc từng package chứ không phải một bảo đảm áp dụng cho toàn hệ thống. Hãy xem sudo needs-restarting -s là nguồn thông tin chính: lệnh này liệt kê các service có file của chính chúng hoặc file của dependency đã thay đổi sau khi service khởi động, bất kể scriptlet đã thực hiện gì.
Vì sao needs-restarting -r báo không cần reboot dù đã cài kernel mới hơn?
Vì lệnh này so sánh thời điểm cài RPM của một danh sách ngắn các core package với thời điểm system boot. Nó không bao giờ so sánh version của kernel đang chạy với version mới nhất đã cài. Nếu bạn cài kernel, reboot, rồi hệ thống khởi động lại bằng kernel cũ hơn vì bootloader mặc định trỏ đến kernel đó, thời điểm cài sẽ cũ hơn thời điểm boot nên kiểm tra không báo gì. Chạy uname -r, rpm -q --last kernel và sudo grubby --default-kernel để xem chính xác tình trạng.
Package nào kích hoạt cảnh báo reboot trên Rocky và Alma?
Một danh sách được hard-code bên trong plugin. Trong các version hiện tại, danh sách này gồm kernel, kernel-core, kernel-rt, glibc, linux-firmware, systemd, dbus, dbus-broker, dbus-daemon và microcode_ctl. Bạn có thể mở rộng danh sách này: đặt file .conf vào /etc/dnf/plugins/needs-restarting.d/, trong đó ghi tên package, mỗi tên một dòng. Các tên này cũng được tính vào kết quả kiểm tra reboot.
dnf-automatic có thể tự reboot server không?
Có. Đặt reboot = when-needed trong section [commands] của /etc/dnf/automatic.conf. Khi đó, hệ thống chỉ reboot nếu transaction đã áp dụng yêu cầu reboot. when-changed reboot sau bất kỳ thay đổi package nào, còn never là giá trị mặc định. reboot_command điều khiển cách reboot; giá trị mặc định sẽ cảnh báo người dùng đang đăng nhập trước 5 phút. Chỉ bật tùy chọn này trên máy mà bạn có thể khôi phục quá trình boot, vì reboot không có người giám sát trên VPS không có quyền truy cập console sẽ khiến hệ thống rơi vào trạng thái lỗi nghiêm trọng.
needs-restarting có kiểm tra process bên trong container không?
Không theo cách hữu ích. Lệnh này đối chiếu các process đang chạy với RPM database của host. Các package bên trong container image không nằm trong database đó, nên một library lỗi thời đã được đóng gói trong image sẽ không xuất hiện. Hãy rebuild image và redeploy. Phía host vẫn quan trọng: container runtime và kernel mà container dùng chung là package của host, nên chúng vẫn được phát hiện.