Linux 伺服器維護清單:每週、每月與升級
整理 Linux server 每週與每月檢查、distribution release 升級及還原測試,逐項說明可避免的故障,補上多數人會跳過的備份還原驗證。
Linux server maintenance 實際包含哪些工作
Linux server maintenance 是一份依固定排程執行的簡短檢查清單,不是沒有終點的專案。每週確認更新已安裝、磁碟仍有可用空間、沒有服務停止,以及備份工作已完成。每月測試還原、檢查憑證到期日、稽核帳戶與 cryptographic key,並清理舊的 kernel 與 log。每個 distribution release 週期規劃版本升級,並執行一直延後的重新開機。
建立 server 是另一項工作,新 VPS 的前 10 分鐘涵蓋該部分。本頁說明接下來一年的維護工作。以下每個項目都指出它能避免的故障,因為沒有說明後果的檢查清單,使用者很快就會停止執行。
這裡的 commands 僅供示範,執行前應先閱讀。請將輸出與自己的 server 比對,因為可用空間或 process 數量的正常值取決於 server 的用途。不同 distribution 的檢查方式若有差異,本文會加以說明。範例使用 Debian 和 Ubuntu 搭配 apt。RHEL family 使用 dnf,且部分路徑不同。
如何選擇能持續執行的 Linux 伺服器維護週期
每週檢查涵蓋會自行變動的項目:套件、磁碟使用量、服務狀態及排程工作。這些項目會自行變化,因此最長大約只能間隔一週不查看。
每月檢查涵蓋緩慢累積的問題:即將到期的憑證、無人移除的帳號、堆積在 /boot 中的核心,以及持續增長、超出已失效輪替規則的日誌檔案。這些問題不會在明天立即造成故障,但最終都會造成故障。
版本檢查依行事曆執行。發行版版本是唯一具有外部期限的維護項目,因為目前版本的支援期限會到期,不論你是否已準備就緒。
將維護安排在固定時段,例如週一早上執行每週檢查,並在每月 1 日執行每月檢查。等「有空再做」的檢查清單不算檢查清單。機器數量超過少數幾台後,應從同一個位置執行這些工作,而不是手動逐台處理;詳見從同一個位置管理多台 Linux 伺服器。
每週:更新是否真的已安裝?
啟用 unattended-upgrades 不代表已確認它確實執行。服務可能被 mask,設定可能只允許使用你未採用的來源,而某個被 hold 的套件也可能導致之後每次執行都失敗。安裝方式請參閱 Ubuntu 的自動安全性更新。每週工作是確認已安裝的自動化機制確實完成了工作。
systemctl status unattended-upgrades
journalctl -u unattended-upgrades --since "8 days ago" --no-pager
sudo tail -n 50 /var/log/unattended-upgrades/unattended-upgrades.log
apt list --upgradable
apt-mark showholdapt list --upgradable 才是可靠的衡量方式,因為它回報目前狀態,而不是原本的意圖。仍出現在該清單中的安全性更新表示自動化機制未正常運作,因此請先讀取日誌,再假設該機器已完成修補。使用 apt-mark hold 鎖定的套件會永久略過更新且不回報任何資訊,這也是 apt-mark showhold 必須在同一輪檢查的原因。
這項檢查可避免以下問題:誤以為更新已自動完成,卻讓已知存在漏洞的套件執行數月。
每週:磁碟與 inode 餘裕
root 檔案系統已滿時,會導致看似與磁碟無關的問題。資料庫拒絕寫入,日誌記錄停止,套件升級在設定完成前失敗;某些環境甚至無法開啟新工作階段,因為系統無法寫入所需檔案。
df -h
df -i
sudo du -xh --max-depth=1 / | sort -h | tail -20df -i是多數人會略過的部分。inode 是用來儲存檔案中繼資料的固定數量結構。檔案系統可能耗盡 inode,即使 df -h 仍顯示有數 GB 的可用空間。此時寫入會以 No space left on device 失敗,旁邊的輸出卻顯示仍有可用空間。第一次遇到時,通常會花上一個小時才釐清原因。卡住的郵件佇列,或無人清理的工作階段目錄,所產生的數百萬個小檔案,通常是主因。
du -xh 會維持在同一個檔案系統中。對使用 bind mount 或附加儲存裝置的伺服器而言,這正是需要的行為。在 Docker 主機上,問題通常出在 image layer 與無用的 volume。清理方式請參閱 在 VPS 上清理 Docker 磁碟使用量。
可用空間反映的是容量。底層儲存裝置可能依自身時程發生故障,因此需要另外檢查。相關方法請參閱 在 VPS 上監控磁碟健康狀態。
每週:哪些服務無聲無息地停止了?
systemctl list-units --state=failed
systemctl list-timers --all
journalctl -p err --since "8 days ago" --no-pager當 unit 當機並達到重啟上限後,會停留在 failed 狀態,之後不會主動通知你。list-timers 更有用:它會顯示每個 timer 上次執行的時間,以及下次觸發的時間。因此,如果 LAST 的值早於該 timer 自身的間隔,表示該工作根本沒有執行。
重新啟動前,先使用 journalctl -u <unit> -n 100 --no-pager 讀取該 unit 的 journal。重啟只能清除表面症狀,之後你可能要等到同樣的問題在更糟的時間再次發生,才會重新檢查。
這項檢查可避免以下情況:monitoring agent、queue worker 或 backup service 可能在 3 週前發生記憶體尖峰後就一直停止運作。
每週:備份工作是否真的完成?
排程備份與備份完成是不同的事實,只有完成的備份可用於還原。請確認備份已完成。
systemctl list-timers --all | grep -i backup
journalctl -u <your-backup-unit> --since "8 days ago" --no-pager
ls -lh /path/to/backup/target | tail請確認兩件事。上次執行正常結束,且最新的封存檔既是近期建立,大小也大致符合預期。備份檔案若突然只有平時大小的十分之一,代表 dump 失敗但仍寫出了檔案。這是最危險的備份失敗形式,因為後續流程看起來都正常。
如果指令碼將 dump 透過 pipe 傳給壓縮程式,請在頂端加入 set -o pipefail。未加入時,pipe 的結束狀態會採用壓縮程式的狀態,而壓縮程式確實成功了:它只是將錯誤訊息壓縮起來。如此一來,工作每晚都會回報成功,卻只寫出一個內容為空的小型封存檔。
每月:在其他位置還原備份
這是大多數人會跳過的項目,也是決定其餘清單是否有意義的項目。
將備份還原到另一台機器或全新的容器,絕不要覆寫線上資料。接著開啟還原的內容,確認資料確實存在。計算資料表中的資料列數。開啟一份文件。登入還原的應用程式。完成資料擷取只能證明封存檔可讀,除此之外無法證明任何事。
儲存庫工具有各自的驗證功能:restic check --read-data-subset=5% 和 borg check --verify-data 會讀取已儲存的資料,而不是索引。執行這些工具,並將其視為基本的 smoke test,不可用來取代還原。驗證只能確認位元組仍然存在。還原則能確認這些位元組正是應用程式需要的資料。
有兩項細節通常要付出代價後才會學到。請在不會透過 agent 取得既有金鑰的機器上測試解密 passphrase,因為無法解密的備份就不算備份。也請記錄還原所需時間,因為這段時間才是實際的復原時間,而通常要到服務中斷時才會發現它。
每月:哪些憑證即將到期?
續期自動化可能會靜默失敗。certbot timer 可能已更新磁碟上的檔案,但網頁伺服器仍從記憶體提供舊憑證,因為重新載入服務的 deploy hook 並未執行。因此,請從伺服器外部檢查執行中的伺服器實際提供哪張憑證。
sudo certbot certificates
systemctl list-timers --all | grep -i certbot
echo | openssl s_client -connect example.com:443 -servername example.com 2>/dev/null | openssl x509 -noout -dates-servername旗標會設定 SNI(伺服器名稱指示)。任何託管多個網站的位址都必須使用此設定,否則取得的會是預設憑證,而不是你的憑證。如果 certbot 是透過 snap 安裝,timer 的名稱會不同。因此,請比對名稱中的文字,而不要假設某個 unit 名稱。
也要記得完全沒有自動化機制的憑證,例如郵件伺服器、VPN 或內部憑證授權單位所使用的憑證。這些憑證可能在週末到期,而瀏覽器與用戶端會直接拒絕這些憑證,不會只顯示警告。
每月:使用者、sudo 存取權與 SSH 金鑰
awk -F: '$3>=1000 && $3<65534 {print $1}' /etc/passwd
getent group sudo
sudo find /home /root -name authorized_keys -exec ls -l {} +
sudo sshd -T | grep -E 'permitrootlogin|passwordauthentication|pubkeyauthentication|port'
last -n 25sshd -T 會在每個 Include 合併後輸出有效設定,這就是 daemon 實際使用的設定。近期的 Ubuntu 映像檔會在 /etc/ssh/sshd_config.d/ 提供 drop-in 檔案。這些檔案可能覆寫主設定檔,因此只讀取 sshd_config 可能得出完全相反的結論。在 RHEL 系列中,管理群組是 wheel,不是 sudo,因此請調整 getent 那一行。
接著直接讀取 authorized_keys 檔案。存取權是透過金鑰授予,而不是依帳號授予。因此,承包商在六個月前結案後遺留的金鑰,仍是可用的登入方式,使用者清單不會標示這類金鑰。金鑰包含註解欄位。請善加利用,並刪除任何無法追溯到特定人員的金鑰。
若要檢查登入歷程,journalctl -t sshd --since "30 days ago" | grep -i accepted 會依 syslog 識別碼比對,而不是依 unit 名稱比對。這一點很重要,因為 Ubuntu 24.04 會透過 socket 啟用 SSH。因此,每個連線都會記錄在自動產生的個別連線 unit 下,單純執行 journalctl -u ssh 可能會遺漏這些記錄。
每月:舊核心與已滿的 /boot
/boot 通常是標準 VPS 映像中的獨立分割區,大小約為數百 MB。每次更新核心時,都會在其中新增映像與 initramfs。該分割區填滿後,下一次升級會在中途失敗,並使套件維持未設定狀態。這種問題不應在星期五突然發生。
uname -r
df -h /boot
dpkg -l 'linux-image-*' | grep '^ii'
sudo apt autoremove --purgeuname -r 一律先執行:它會顯示目前正在執行的核心,而該核心必須在任何移除作業中保留。apt autoremove 可處理 Debian 與 Ubuntu 上的正常情況,因為核心會標記為自動安裝,且目前使用中的核心受到保護。例外情況包括手動安裝的核心,或已經滿到連 apt 都無法執行的 /boot;這些情況請參閱 在 Ubuntu 上清除舊核心。
每月:日誌成長與 systemd journal
journalctl --disk-usage
sudo du -xh --max-depth=1 /var/log | sort -h | tail
sudo logrotate --debug /etc/logrotate.conflogrotate --debug 是試執行,不會寫入任何內容,因此可在運作中的伺服器上安全執行。建議執行這項指令,因為日誌輪替規則是依路徑比對:應用程式在升級期間變更日誌位置後,原本的規則便不再涵蓋該日誌檔案,檔案會持續無限制成長,直到填滿磁碟。
systemd 會限制 journal 的大小,但上限是檔案系統容量的一部分,而不是你指定的固定數值。如果需要明確的上限,請在 /etc/systemd/journald.conf 設定 SystemMaxUse=,然後重新啟動 systemd-journald。sudo journalctl --vacuum-time=14d 會立即回收空間,但這是一次性操作,不是持續套用的政策,因此應搭配設定變更一起使用。
每次發布:一再延後的重新開機
磁碟上的更新核心套件不代表目前正在執行的核心已更新。在重新開機前,機器仍會執行舊核心;即使系統支援 live patching,也只能涵蓋部分修補內容。
uname -r
ls -l /var/run/reboot-required
cat /var/run/reboot-required.pkgs
sudo needrestart該旗標檔案是 Debian 和 Ubuntu 採用的慣例,由套件指令碼寫入。RHEL 系列系統不會建立此檔案;在這些系統上,等效問題由 needs-restarting -r 回答,而該資訊來自 dnf-utils。近期 Ubuntu server 映像預設安裝的 needrestart,可進一步查看低於核心的層級:它會列出仍在對映已替換磁碟檔案庫的程序。因此,更新後的 OpenSSL 必須等到使用它的服務重新啟動後才會生效。
請排程重新開機,不要一直避開。使用 /etc/apt/apt.conf.d/50unattended-upgrades、Unattended-Upgrade::Automatic-Reboot "true"; 和 Unattended-Upgrade::Automatic-Reboot-Time "03:00";,將決定交給你指定的時間。計畫中的重新開機也是唯一能測試主機是否能恢復運作的方法,因為錯誤的 fstab 項目或從未啟用的服務,只有在開機時才會顯現問題。
每個版本:規劃發行版升級
Ubuntu LTS 發行版提供 5 年標準支援,非 LTS 中間版本則提供 9 個月支援,因此這項選擇會影響未來數年的升級工作量。相關取捨請參閱伺服器上的 LTS 與中間版本。
lsb_release -a
cat /etc/update-manager/release-upgradesdo-release-upgrade 會讀取該檔案,而 Prompt=lts 會將範圍限制為 LTS 到 LTS 的升級。LTS 到 LTS 的升級路徑通常會在新版本的第一個 point release 發佈時開放,而不是在版本發佈當天開放。因此,請確認系統實際提供的升級選項,不要依據自行假定的日期規劃。升級程序請參閱將 Ubuntu 24.04 升級至 26.04。
請預留 3 個月的緩衝時間。建立一份已測試還原流程的 snapshot,列出第三方 apt repository(升級時會停用這些 repository,且每個 repository 都必須針對新版本設定新的目標),並在開始前決定 rollback 方案。截至 August 2026,Ubuntu 24.04 LTS 的標準支援將持續至 April 2029,因此這是排程工作,不是緊急處置。
要自動化的項目,以及應保留手動處理的項目
將已經決定的工作自動化,例如安全性更新、日誌輪替、憑證續期及備份工作。警示也應自動化,因為依賴你記得執行的檢查,凌晨 2 點不會自行發生。外部監控服務,例如 使用 Uptime Kuma 自架狀態監控,可以偵測任何主機內部腳本都無法回報的問題,也就是主機無法連線。
以下兩項應保留手動處理:還原測試與帳號稽核。這兩項都需要人員判斷結果是否正確。如果你偏好在瀏覽器中查看主機狀態,而不是使用終端機,Cockpit 與 Webmin 的伺服器管理比較會比較這兩種常見的 Web 主控台。
自動化機制本身也需要檢查,因此這份清單中的第一項每週工作是驗證更新程式。無聲失敗的自動化比完全沒有自動化更糟,因為它同時消除了失敗提示,以及檢查相同項目的習慣。
完整檢查清單集中於此
每週與每月指令,可直接複製
# weekly
systemctl list-units --state=failed
systemctl list-timers --all
journalctl -u unattended-upgrades --since "8 days ago" --no-pager
apt list --upgradable
apt-mark showhold
df -h
df -i# monthly
sudo certbot certificates
awk -F: '$3>=1000 && $3<65534 {print $1}' /etc/passwd
getent group sudo
sudo sshd -T | grep -E 'permitrootlogin|passwordauthentication'
uname -r
dpkg -l 'linux-image-*' | grep '^ii'
journalctl --disk-usage此區塊刻意未列入還原測試。還原測試不是單一指令,也不應在同一台機器上執行。請在其他位置進行還原,然後開啟資料並確認內容確實存在。
FAQ
我應該多久執行一次 Linux 伺服器維護?
對於會自行變動的項目,應每週檢查:更新狀態、磁碟與 inode 剩餘空間、失敗的 unit,以及備份工作是否完成。對於緩慢累積的問題,應每月檢查:還原測試、憑證到期日、帳號與 SSH key 稽核、舊 kernel,以及日誌成長情況。每次 distribution release 則執行一次版本升級,並重新開機以載入目前的 kernel。健康的伺服器每週檢查只需幾分鐘。這正是應每週執行,而不是等到看起來有問題才執行的原因。
備份工作回報成功後,為什麼還要測試還原?
因為工作回報的是自身的 exit status,而該 status 可能為真,封存檔卻已無法使用。將 dump 透過 set -o pipefail 傳給 compressor 時,會回傳 compressor 的 status。因此,失敗的 dump 即使只產生錯誤訊息,仍可能以 zero 結束並寫入小型檔案。請將資料還原到另一台機器、開啟資料,並實際計算某項內容。還原測試也會記錄所需時間,而該時間才是實際的復原時間。
每次更新 kernel 後都必須重新開機嗎?
必須先重新開機,新 kernel 才會成為正在執行的 kernel。在 Debian 和 Ubuntu 上,存在 /var/run/reboot-required 表示某個 package 要求重新開機,而 /var/run/reboot-required.pkgs 會指出是哪個 package。在 RHEL 系列中不存在該檔案,使用 dnf-utils 的 needs-restarting -r 會回答相同問題。請在 /etc/apt/apt.conf.d/50unattended-upgrades 設定自動重新開機時段,不要無限期延後。因為一年未重新開機的機器,不僅使用舊 kernel,其開機路徑也未經測試。
哪些檢查可以安全地自動化?
將決策已經確定的工作自動化:security updates、log rotation、certificate renewal 及 scheduled backups。通知也應自動化,讓失敗的 unit 或即將用滿的磁碟無須人工執行 command 就能通知你。還原測試與 key 稽核應保留人工執行,因為這些工作都需要人員判斷結果是否正確。接著再對自動化機制本身加入一項檢查,因為更新工具無聲失敗時,看起來會和一切正常完全相同。