2013-10-02 78 views
1

我寫了一個大型的Bash程序,它由幾個在整個深層目錄樹中組織的shell腳本組成。該程序非常複雜,擁有熟練的調試和日誌記錄基礎架構至關重要。 在其中一個子腳本中,我編寫了一個記錄器函數,該函數能夠接收日誌消息,並將這些日誌消息路由到適當的MySQL表。腳本範圍重定向到內部記錄器功能

記錄器功能具有隻接受一個參數,日誌消息,並且可以被想象爲echo內置直接打印到數據庫中,與正被內部確定路由的一個特殊版本的純簡單的輸入接口。 在代碼這轉化爲:

# generic code, somewhere in the program 
if success; then 
    log_f "Previous function returned success" 
else log_f "Previous function returned failure" 
fi 

這種方法具有可僅能夠登錄被明確地意在直通log_f那些消息的缺陷;也就是說,外部二進制文件或Bash本身生成的任何錯誤消息都不會保存在數據庫中。

一個簡單的解決方案可能沿着exec >log 2>&1行,這將註冊從標準輸入和標準錯誤到log。但是,我需要將日誌消息存儲在數據庫中而不是文件中。

另外,exec似乎與管道重定向不兼容,如exec | log_f。 (log_f修改爲支持stdin)。 我能想到的唯一的解決辦法,這是醜陋的,是他們的調用過程中可以設置整個腳本(S)的重定向,如:

# I am a starter of sub-scripts 
a_script_in_the_tree.sh 2>&1 | log_f 

然而,這將是最好讓每個腳本管理其自己的內部日誌記錄方法,使用其範圍內可用的自己的一組函數。

+1

您是否知道'{cmd1; ...; } | log_f'?它處理大括號範圍內的代碼的I/O重定向,與'exec'類似,但並不像'exec'那樣激進 - 可用於管道(關於設置和讀取變量的位置的注意事項)。 –

+0

如果我想收集腳本中的所有輸出,這將需要將程序的幾乎每個和每個命令分別管理給記錄器。一個瘋狂的恕我直言。 – davide

+0

我剛剛意識到整個腳本可以放在'{}'內,除了'log_f'的定義。但是,我有全局變量,唉。 – davide

回答

1

一個簡單的解決方案可以沿着exec >log 2>&1

線走命名管道可能需要日誌文件的位置,雖然這需要一個FIFO到SQL過程中要消耗的輸出和發送它到數據庫。這會讓您對每個腳本重定向「自力更生」,同時增加每個腳本啓動冪等消費者所需的負擔。這會把另一個醜陋交易嗎?

下面是一個簡單的一對驗證這個想法,有需要的日誌記錄服務腳本的腳本:

$ cat nplog.sh 
#!/bin/bash 

logfifo=/tmp/log.fifo 
if [ ! -p $logfifo ]; then 
    # should maybe spawn npreader here 
    echo logging system is not running: $logfifo does not exist 1>&2 
    exit 1 
fi 

exec > $logfifo 2>&1 

while true; do 
    date 
    cat /does.not.exist 
    sleep 1 
done 

和cheezy讀者

$ cat npreader.sh 
#!/bin/bash 

# oversimplified for illustration. should remove the fifo upon exit so 
# that clients can't attach when reader is down 

logfifo=/tmp/log.fifo 
mkfifo $logfifo 
cat $logfifo 
0

剛出來我的頭:

exec > >(log_f) 2>&1