Shell Daily 2025-12-19: 優雅退場 (Trap)
寫腳本時,我們通常會在末尾寫上一句 rm /tmp/data_export.tmp 來清理現場。但如果腳本執行中途報錯退出了?或者用户不耐煩按了 Ctrl+C 強行終止?那行清理代碼永遠不會執行,垃圾文件就會日積月累。
要想寫出“死得體面”、不留垃圾的健壯腳本,你不能只關注開始,更要關注結束。這時你需要 trap。
怎麼用
trap 命令允許你在腳本接收到特定信號(Signal)時,觸發預定義的操作。
- 語法:
trap 'command_to_execute' SIGNAL_LIST - 兼容性:POSIX 通用標準。所有主流 Shell 均支持。
適用場景
- 清理臨時文件:無論腳本是正常結束還是被殺掉,確保刪除
/tmp下的文件。 - 釋放資源:刪除文件鎖 (Lock file) 或關閉後台起的子進程。
- 回滾操作:如果部署腳本中斷,自動恢復之前的配置文件。
示例 1:全能的 EXIT 偽信號
這是最常用、價值最高的技巧。不同於 INT (Ctrl+C) 或 TERM (kill),EXIT 是一個 Shell 偽信號。無論腳本以何種方式結束(正常跑完、exit 1 報錯、被用户中斷),只要 Shell 進程退出,它都會觸發。
temp_file="/tmp/report_$(date +%s).csv"
touch "$temp_file"
# 註冊陷阱:腳本退出時,自動刪除臨時文件
trap 'rm -f "$temp_file"' EXIT
echo "Processing data..."
# 即使下面這行命令失敗導致腳本退出,或者你狂按 Ctrl+C
# rm 命令依然會被執行
sleep 10
示例 2:調用清理函數
如果清理工作很複雜,不要把代碼全塞在單引號裏,寫個函數更清晰:
pid_file="/var/run/my_daemon.pid"
cleanup() {
echo "Cleaning up..."
rm -f "$pid_file"
# 還可以做更多,比如通知監控系統
echo "Script stopped at $(date)"
}
# 註冊函數到 EXIT 信號
trap cleanup EXIT
echo $$ > "$pid_file"
# 模擬耗時任務
do_heavy_work