挺好用!Shell腳本日志技巧
本文轉載自微信公眾號「Linux開發那些事兒」,作者LinuxThings。轉載本文請聯系Linux開發那些事兒公眾號。
執行shell腳本時,常常會打印一些日志到控制臺,根據輸出的日志,來判斷腳本功能正確與否
但是,太多日志打印的話,會讓閱讀變得很困難,從日志信息里面找到我們關心的那部分也變得很不方便了
所以,有一個好用的shell腳本日志接口是非常有必要的,本文將聊聊實踐中日志打印的一些技巧
常見日志打印方式
編寫 shell 腳本時,最簡單的日志打印是使用 echo 輸出,比如: 下面是打印一個測試程序的日志
- [root@VM-0-2-centos ~]# echo "this is a log test..."
- this is a log test...
上面的方式使用起來非常簡單,編寫效率也很高,對于一些功能簡單,代碼量少的shell腳本,非常適合這種日志打印的方式,簡單快捷
通用接口
上面的小節中,每次都用 echo ,沒有一個統一的輸出格式,如果需要在每條日志開頭加上指定內容, 就需要修改腳本中每一處的日志,這就變成了一個體力活了
針對這點,可以定義一個輸出函數,所有的的輸出統一調用這個函數, 現有測試腳本 t.sh 內容如下
- #!/bin/bash
- function log()
- {
- echo "$@"
- }
另外新建一個測試腳本 ta.sh
- #!/bin/bash
- source ./t.sh
- log "this is a test..."
- log "today is `date '+%Y-%m-%d'` "
執行 ./ta.h 命令,結果如下
- [root@VM-0-2-centos shell_log]# ./ta.sh
- this is a test...
- today is 2021-07-27
如果現在想在每一行日志前面加上當前時間的話,直接修改 t.sh 中的 log 函數, t.sh調整后的腳本如下
- #!/bin/bash
- function log()
- {
- echo "$(date '+%Y-%m-%d %H:%M:%S') $@"
- }
然后再次執行 ./ta.sh 命令,結果如下
- [root@VM-0-2-centos shell_log]# ./ta.sh
- 2021-07-27 19:55:54 this is a test...
- 2021-07-27 19:55:54 today is 2021-07-27
上面只修改了 log 函數,ta.sh 中的每一行日志開頭就都輸出了當前的時間, $@ 表示傳入log 函數的所有參數
打印開關
調試腳本的時候,會加上很多的日志打印,當調試完了之后,需要關閉所有的日志輸出,上面已經把日志打印統一到一個函數中了,這時我們只需要禁止執行 log 函數的 echo 語句即可,修改之后的 t.sh 內容如下
- #!/bin/bash
- function log()
- {
- [ 0 -gt 1 ] && echo "$(date '+%Y-%m-%d %H:%M:%S') $@"
- }
當 [ 0 -gt 1 ] 表示條件結果為 false 的時候,echo 語句就不會執行,這樣就能關閉所有的日志打印
也可以在 t.sh 中加一個變量,表示是否開啟日志,當開啟的時候,才會有日志打印,開關關閉時,同時會關閉日志打印功能,調整后的 t.sh 內容如下
- #!/bin/bash
- LOG_OPEN=0
- function log()
- {
- [ $LOG_OPEN -eq 1 ] && echo "$(date '+%Y-%m-%d %H:%M:%S') $@"
- }
需要開啟日志的時候,把 LOG_OPEN 設置為1,關閉日志打印,設置為0即可
日志等級
在不同的腳本邏輯中,打印的日志應該有不同的作用,有些是臨時變量值的輸出,作為調試用的,有些是一些狀態轉換或者達到不同階段的提示信息,還有些是嚴重的錯誤,需要重點輸出并提醒用戶
以上這些可以通過日志等級來實現,把日志劃分等級,不同的等級屏幕上輸出不同的顏色,便于查看,直接來看修改后的 t.sh 腳本內容吧
- #!/bin/bash
- #日志級別 debug-1, info-2, warn-3, error-4, always-5
- LOG_LEVEL=3
- #調試日志
- function log_debug(){
- content="[DEBUG] $(date '+%Y-%m-%d %H:%M:%S') $@"
- [ $LOG_LEVEL -le 1 ] && echo -e "\033[32m" ${content} "\033[0m"
- }
- #信息日志
- function log_info(){
- content="[INFO] $(date '+%Y-%m-%d %H:%M:%S') $@"
- [ $LOG_LEVEL -le 2 ] && echo -e "\033[32m" ${content} "\033[0m"
- }
- #警告日志
- function log_warn(){
- content="[WARN] $(date '+%Y-%m-%d %H:%M:%S') $@"
- [ $LOG_LEVEL -le 3 ] && echo -e "\033[33m" ${content} "\033[0m"
- }
- #錯誤日志
- function log_err(){
- content="[ERROR] $(date '+%Y-%m-%d %H:%M:%S') $@"
- [ $LOG_LEVEL -le 4 ] && echo -e "\033[31m" ${content} "\033[0m"
- }
- #一直都會打印的日志
- function log_always(){
- content="[ALWAYS] $(date '+%Y-%m-%d %H:%M:%S') $@"
- [ $LOG_LEVEL -le 5 ] && echo -e "\033[32m" ${content} "\033[0m"
- }
把日志級別分成 5 個等級,分別是 : debug日志、info日志、警告日志、錯誤日志、一直都打印的日志 ,每個級別對應一個函數接口,而且每個級別可以定義不同的字符顏色,方便在屏幕上查看錯誤以及警告,上述腳本中錯誤日志是紅色,警告日志是黃色,其他級別的日志是綠色
修改 ta.sh 腳本, 內容如下
- #!/bin/bash
- source ./t.sh
- log_debug "this is debug log..."
- log_info "this is info log..."
- log_warn "this is warn log..."
- log_err "this is error log..."
- log_always "this is always log.."
把 t.sh 中 LOG_LEVEL 設置為 1 , 執行 ./ta.sh 命令,結果如下
再次調整 t.sh 中 LOG_LEVEL 為 3 , 執行 ./ta.sh 命令,結果如下
從上面兩次結果可以知道,日志級別設置為 debug級別 ( LOG_LEVEL = 1 ) 時,所有的等級的日志都會輸出,當把日志級別設置為 info級別 ( LOG_LEVEL = 3 ) 后,只輸出 warn日志、error日志 以及 always日志
如果想關閉所有級別的日志,把日志級別調到比 always日志 更高的級別,也即 LOG_LEVEL 的值大于 5 就行了
寫入文件
當腳本是定時調用的時候,有時需要查詢一段時間內腳本運行情況,這種情況下腳本一般都是后臺運行的,要查詢一段時間的日志,就需要把日志寫入到日志文件中
比如:定時備份數據庫的shell腳本,就需要記錄下每次備份時的情況,便于后期查詢用
調整下 t.sh 腳本,增加日志寫入文件語句,修改后的腳本內容如下
- #!/bin/bash
- #日志級別 debug-1, info-2, warn-3, error-4, always-5
- LOG_LEVEL=3
- #日志文件
- LOG_FILE=./log.txt
- #調試日志
- function log_debug(){
- content="[DEBUG] $(date '+%Y-%m-%d %H:%M:%S') $@"
- [ $LOG_LEVEL -le 1 ] && echo $content >> $LOG_FILE && echo -e "\033[32m" ${content} "\033[0m"
- }
- #信息日志
- function log_info(){
- content="[INFO] $(date '+%Y-%m-%d %H:%M:%S') $@"
- [ $LOG_LEVEL -le 2 ] && echo $content >> $LOG_FILE && echo -e "\033[32m" ${content} "\033[0m"
- }
- #警告日志
- function log_warn(){
- content="[WARN] $(date '+%Y-%m-%d %H:%M:%S') $@"
- [ $LOG_LEVEL -le 3 ] && echo $content >> $LOG_FILE && echo -e "\033[33m" ${content} "\033[0m"
- }
- #錯誤日志
- function log_err(){
- content="[ERROR] $(date '+%Y-%m-%d %H:%M:%S') $@"
- [ $LOG_LEVEL -le 4 ] && echo $content >> $LOG_FILE && echo -e "\033[31m" ${content} "\033[0m"
- }
- #一直都會打印的日志
- function log_always(){
- content="[ALWAYS] $(date '+%Y-%m-%d %H:%M:%S') $@"
- [ $LOG_LEVEL -le 5 ] && echo $content >> $LOG_FILE && echo -e "\033[32m" ${content} "\033[0m"
- }
實際上是在每個日志級別的接口中增加了 echo $content >> $LOG_FILE 語句,表示將日志寫入文件中, $LOG_FILE 表示日志文件
目前日志級別是 warn日志 級別,執行 ./ta.sh 命令,結果如下
從上述結果可以看出,執行 ./ta.sh 命令之后,除了屏幕會輸出日志外,本地目錄下也會生成一個 log.txt 文件,文件內容和屏幕上的日志是一樣的
小結
本文介紹了shell腳本中日志打印的一些技巧, 這些技巧都是從實踐中總結出來的,文中提供了腳本的全部代碼,可以拿來直接使用,也可根據實際的需求自行調整