Câu trả lời:
Cách tốt nhất là tìm chương trình / dịch vụ nào sử dụng các thư viện cũ và khởi động lại chúng. Và bạn có thể đạt được nó bằng cách liệt kê tất cả các tệp được sử dụng bằng cách sử dụng 'lsof' và tìm những tệp có loại 'DEL'. DEL có nghĩa là tên tệp đã bị xóa khỏi hệ thống tệp nhưng nó vẫn bị kẹt trong bộ nhớ vì ai đó sử dụng nó.
Đây là dòng lệnh đầy đủ:
sudo lsof +c 0 | grep 'DEL.*lib' | awk '1 { print $1 ": " $NF }' | sort -u
Lý do bắt buộc duy nhất để khởi động lại là một hạt nhân mới (và bạn có thể khởi động lại bằng cách sử dụng kexec). Xem https://wiki.archlinux.org/index.php/Kexec để biết chi tiết, tóm tắt:
tải kernel mới, initramfs và chỉ định cmdline khởi động
kexec -l /boot/new-kernel --initrd=/boot/new-initramfs --reuse-cmdline
gọi kexec(sử dụng systemctlđể tắt máy đúng cách, kexec -esẽ thực thi trực tiếp)
systemctl kexec
Lưu ý rằng nếu bạn tạo kexec-load@.servicenhư được giải thích trong wiki, nếu bạn khởi động lại, systemdsẽ tự động khởi động lại bằng cách sử dụng kexecthay vì thực hiện khởi động lại bios
Phiên bản cải tiến nhỏ cung cấp tên dịch vụ systemd:
PIDS="(lsof +c0 -n 2> /dev/null | grep 'DEL.*lib' | awk '{print $2}' | sort -u)"
for PID in $PIDS; do
systemctl status $i
done | grep '●' | awk '{print $2}' | sort -u
hoặc một dòng:
for i in $(lsof +c0 -n 2> /dev/null | grep 'DEL.*lib' | awk '{print $2}' | sort -u); do systemctl status $i; done | grep '●' | awk '{print $2}' | sort -u
Lưu ý rằng có một số vấn đề:
systemctl daemon-reload nên được thực hiện trước khi khởi động lại bất cứ điều gì khácsystemdcần phải khởi động lại PID 1 , nó có thể được thực hiện bằng cách sử dụngsystemctl daemon-reexecsystemctl restart dbus.service phá vỡ một số dịch vụ khác, chúng cần được khởi động lại sau khi khởi động lại dbus:
systemd chinh no: systemctl daemon-reexecsystemd-logindsystemd-machineddbussystemctl restart sshdsẽ không khởi động lại được miễn là bạn được kết nối, tôi thấy 2 tùy chọn:
systemctl restart sshdsử dụng at/cron/systemdbộ hẹn giờSSHbằng cách sử dụng trình điều khiển từ xa (an toàn) khác, chẳng hạn nhưmoshscreen/tmuxcũng có thể chặn các dịch vụ như SSHkhởi động lại, cách dễ nhất là đóng các phiên này trước khi khởi động lại dịch vụMột cách dễ dàng là so sánh phiên bản của kernel đang chạy với kernel mới nhất trên đĩa. Tôi tìm thấy một kịch bản có thể làm điều đó một cách dễ dàng.
Khi tôi đã cài đặt một số hạt nhân, tôi đã sửa đổi tập lệnh để chỉ kiểm tra tập lệnh tương ứng với kernel đang chạy. Ví dụ: tôi hiện đã cài đặt phiên bản 4.9.79 và 4.14.16 và do đó cần kiểm tra /boot/vmlinuz-4.14-x86_64. Thật không may, điều này sẽ không hoạt động khi tôi bắt đầu sử dụng phiên bản 5.1, vì vậy sẽ cần một bản cập nhật (thay thế 4 bằng 3) hoặc tôi cần tìm một cách mạnh mẽ hơn.
Đây là kịch bản của tôi:
#!/bin/sh
NEXTLINE=0
FIND=""
CURRENT_KERNEL=`uname -r`
KERNEL_PATH="/boot/vmlinuz-${CURRENT_KERNEL:0:4}"
for I in `file $KERNEL_PATH*`; do
if [ ${NEXTLINE} -eq 1 ]; then
FIND="${I}"
NEXTLINE=0
else
if [ "${I}" = "version" ]; then NEXTLINE=1; fi
fi
done
if [ ! "${FIND}" = "" ]; then
if [ ! "${CURRENT_KERNEL}" = "${FIND}" ]; then
echo "Boot required"
else echo "No boot required"
fi
fi