別再只靠 cron 了:用 systemd 計時器做 Linux 定時備份,失敗了也會告訴你
幾乎每個用過 Linux 伺服器的人都寫過 cron。寫一行「0 2 * * * /home/user/backup.sh」,備份就每天凌晨兩點自動跑,簡單又順手。可是當備份真的出問題時,cron 往往安安靜靜,什麼也不說——磁碟滿了、指令路徑錯了、腳本中途出錯,早上打開信箱才發現,昨晚根本沒有備份,而你還以為一切正常。這篇文章想介紹一個更穩妥的做法:用 systemd 計時器(timer)來排程備份,失敗了也能被看見。
先說 cron 的三個常見弱點。第一,失敗是靜默的。cron 任務的輸出預設寄給本機郵件或直接丟掉,很多人從來不看,於是失敗可以連續幾星期都沒人發現。第二,執行環境很精簡,PATH 比互動式 shell 短,crontab 裡寫的指令在本機測試明明能跑,放進 cron 卻找不到指令,這類問題非常普遍。第三,錯過了就不補跑。伺服器剛好在凌晨兩點重啟或關機,當天的備份就直接跳過,不會稍後補做。
systemd 計時器的做法是把「什麼時候跑」和「跑什麼」分開。跑什麼寫成一個 service 單元,什麼時候跑寫成一個 timer 單元,timer 到時間就觸發 service。好處是狀態集中:用 systemctl 就能看到下一次執行時間、上一次結果和日誌,排程、執行、日誌都在同一個體系裡,不用再到處找。
舉一個每天凌晨兩點備份網站資料的例子。先寫備份腳本,假設是 /usr/local/bin/backup.sh,內容是把 /var/www 打包、加上日期命名,再用 rsync 同步到備份目錄,結尾用 set -euo pipefail,讓任何一步失敗就立刻以非零狀態退出。腳本務必用絕對路徑,變數要加雙引號,這是避免 cron 式環境問題的基本功。寫好後記得 chmod +x,並手動跑一次,確認真的能產生備份檔。
接著寫 service 單元 /etc/systemd/system/backup.service,內容大概是:Description 寫清楚用途,Type=oneshot 表示一次性的任務,ExecStart 指向備份腳本,WorkingDirectory 寫明工作目錄。再寫 timer 單元 /etc/systemd/system/backup.timer,指定 OnCalendar=daily、時間是 02:00,Persistent=true 是關鍵:就算機器在兩點時關機,開機後也會補跑一次錯過的備份;再加上 RandomizedDelaySec=300,讓多台機器的備份時間錯開幾分鐘,避免同時衝擊儲存。
啟用的指令只有三行:先 systemctl daemon-reload 讓 systemd 讀入新的單元檔,再 systemctl enable --now backup.timer,最後用 systemctl list-timers --all 檢查,應該能看到 backup.timer 的下一次觸發時間。想看執行結果,用 systemctl status backup.service 和 journalctl -u backup.service,輸出、結束狀態和錯誤訊息都在這裡,不需要再猜。
計時器最有價值的一點,是能把失敗變成看得見的事件。在 service 裡加上 OnFailure=notify-failure.service,指向一個簡單的通知單元,例如呼叫 webhook 或寄送訊息到團隊頻道,備份失敗時就會主動提醒。當然通知本身也要有備援:至少每週做一次還原演練,從備份檔實際還原一個檔案,確認備份不是「看似成功、實則打不開的空殼」。
最後整理一份檢查清單,方便照著做:腳本先手動跑通,單元檔放好後重新載入並啟用計時器,第二天早上檢查 list-timers 和 journalctl,確認備份檔真的存在且大小合理,每週抽查還原一個檔案,每月檢查磁碟用量和保留期限,避免舊備份把磁碟塞滿。cron 沒有不好,簡單的任務用它完全足夠;但備份這種「出事才知道重要」的任務,值得用看得見失敗的排程方式。多花十分鐘設定,換來的是半夜能安心睡覺的底氣。
- 点赞
- 收藏
- 关注作者
评论(0)