Shell 腳本的日誌功能實作
在 Linux 系統管理與自動化任務中,Shell 腳本(Shell Script)是不可或缺的工具。然而,許多初學者常忽略一個關鍵環節:日誌記錄(Logging)。當腳本出現錯誤或需要追蹤執行狀態時,缺乏日誌意味著你只能面對滿屏的標準輸出(stdout)或標準錯誤(stderr),難以釐清問題根源。
本篇將介紹如何在 Shell 腳本中實作專業級的日誌功能,包含日誌分級、時間戳記、以及將日誌寫入獨立檔案的技巧。
為什麼需要自訂日誌函數?
雖然 Linux 系統有 syslog 服務,但在簡單的自動化腳本中,直接使用 echo 輸出訊息更為直觀。然而,單純的 echo 缺乏結構化資訊。我們需要一個統一的日誌函數,它能提供以下功能:
- 時間戳記:精確記錄事件發生的時間。
- 日誌等級:區分資訊(INFO)、警告(WARN)與錯誤(ERROR)。
- 輸出分離:將日誌寫入檔案,同時可選擇是否顯示在終端機上。
實作日誌函數
我們可以使用 Bash 的函數功能來封裝日誌邏輯。以下是一個實用的日誌模組範例,您可以直接將其複製到您的腳本頂部或獨立為 logger.sh 檔案並透過 source 引入。
#!/bin/bash
# 設定日誌檔案路徑,預設為腳本執行目錄下的 script.log
LOG_FILE="${LOG_DIR:-/tmp}/script_$(date +%Y%m%d).log"
# 日誌等級常數
LOG_LEVEL_INFO=1
LOG_LEVEL_WARN=2
LOG_LEVEL_ERROR=3
# 當前日誌等級,可根據需求調整以過濾訊息
CURRENT_LOG_LEVEL=$LOG_LEVEL_INFO
# 日誌函數定義
log_message() {
local level=$1
local message=$2
# 檢查日誌等級,若低於設定等級則忽略
if [ "$level" -lt "$CURRENT_LOG_LEVEL" ]; then
return
fi
# 取得當前時間
local timestamp=$(date "+%Y-%m-%d %H:%M:%S")
# 根據等級設定顏色(僅在支援顏色的終端機有效)
local color=""
case $level in
$LOG_LEVEL_INFO) color="\033[0;32m" ;; # 綠色
$LOG_LEVEL_WARN) color="\033[0;33m" ;; # 黃色
$LOG_LEVEL_ERROR) color="\033[0;31m" ;; # 紅色
esac
local reset="\033[0m"
# 格式化日誌字串
local log_line="[${timestamp}] [${level}] ${message}"
# 寫入日誌檔案
echo -e "$log_line" >> "$LOG_FILE"
# 若等級為 WARN 或 ERROR,則同時輸出到標準錯誤 (stderr)
if [ "$level" -ge $LOG_LEVEL_WARN ]; then
echo -e "${color}[${timestamp}] [${level}] ${message}${reset}" >&2
else
# INFO 等級輸出到標準輸出 (stdout)
echo -e "${color}[${timestamp}] [${level}] ${message}${reset}"
fi
}
# 快捷函數,方便呼叫
log_info() { log_message $LOG_LEVEL_INFO "$1"; }
log_warn() { log_message $LOG_LEVEL_WARN "$1"; }
log_error() { log_message $LOG_LEVEL_ERROR "$1"; }
如何使用這個日誌系統?
將上述程式碼保存為 logger.sh,然後創建一個主腳本 main.sh 來測試其功能。
#!/bin/bash
# 引入日誌模組
source ./logger.sh
# 測試不同等級的日誌
log_info "腳本開始執行..."
log_info "正在檢查系統狀態..."
# 模擬一個警告情境
if [ ! -d "/tmp/test_dir" ]; then
log_warn "目錄 /tmp/test_dir 不存在,將自動建立..."
mkdir -p /tmp/test_dir
fi
# 模擬錯誤情境
if false; then
log_error "發生嚴重錯誤!"
else
log_info "模擬錯誤測試完成,未觸發錯誤路徑。"
fi
log_info "腳本執行結束。"
執行 bash main.sh 後,您會發現終端機上顯示了帶有顏色的時間戳記訊息,同時在 /tmp/ 目錄下會產生對應日期的日誌檔案(例如 script_20231027.log)。這種方式讓您在除錯時能輕鬆過濾出關鍵資訊。
常見問題
1. 日誌檔案權限問題
在 Ubuntu 或 Debian 系統上,若腳本以 sudo 執行,日誌檔案會以 root 權限建立。若後續以一般使用者執行腳本,可能會遇到「Permission denied」錯誤。
- 解決方案:建議將日誌目錄設定為
/var/log/myapp/並預先建立好適當權限,或在腳本開頭檢查權限並自動修正:touch "$LOG_FILE" && chmod 644 "$LOG_FILE"。
2. 日誌檔案過大影響效能 隨著時間推移,日誌檔案可能變得龐大,導致開檔速度變慢。
- 解決方案:引入
logrotate機制。您可以建立/etc/logrotate.d/myapp設定檔,設定日誌檔案在達到一定大小或時間後自動壓縮並清空舊檔,這是 Linux 系統管理的標準做法。
小結
實作自訂日誌函數是提升 Shell 腳本專業度的關鍵一步。透過時間戳記、日誌分級與顏色提示,不僅能加速除錯過程,也能讓日誌內容更具可讀性。建議您在撰寫任何生產環境的腳本時,都養成加入日誌記錄的習慣,這將是未來系統維護時最珍貴的資產。