2012-05-02 48 views
1

我們有一個由cron調用並作爲根運行的shell腳本。從Bash腳本中的函數寫入泄漏文件描述符

此腳本輸出日誌記錄和調試信息,並且在某個特定點上一直失敗。這一點根據腳本創建的輸出量而異(例如,如果我們啓用更多調試輸出,它會更快失敗)。

但是,如果腳本是作爲用戶直接調用的,那麼它的工作沒有問題。

我們已經創建了一個簡化的測試用例來演示這個問題。

的腳本是:

#!/bin/bash 
function log_so() { 
    local msg="$1" 
    if [ -z "${LOG_FILE}" ] ; then warn_so "It's pointless use log_so() if LOG_FILE variable is undefined!" ; return 1 ; fi 
    echo -e "${msg}" 
    echo -e "${msg}" >> ${LOG_FILE} 
    (
    /bin/true 
) 
} 


LOG_FILE="/usr/local/bin/log_bla" 

linenum=1 
while [[ $linenum -lt 2000 ]] ; do 
    log_so "short text: $linenum" 
    let linenum++ 
done 

這已經達到了最高的是244臨終時(通過cron調用)前。

其他一些搜索建議使用函數中的no-op子shell並調用/ bin/true,但不僅如此,子shell選項在主腳本中不可行。

我們也嘗試更改root的文件描述符限制,但這並沒有幫助,並且已嘗試對腳本使用#!/ bin/sh和#!/ bin/bash。

我們在Ubuntu 10.04 LTS上使用bash 4.1.5(1)發佈。

任何想法或建議的解決方法,將不勝感激。

+0

無法在Fedora 16 GNU bash版本4.2.24(1)上覆制 - 即使ulimit爲128也不會複製。建議遷移到更具體的論壇。 –

+1

我剛剛瞭解到這是一個在bash 4.1和更早的版本中已經在4.2版中得到糾正的bug,我不知道是否升級bash對我們來說是一個選項,所以仍然希望爲bash 4.1.x找到一個解決方案if一個存在。 –

回答

1

那麼手動打開fd然後清理它怎麼樣?我沒有測試過的bash 4.1,但它可能有幫助。

LOG_FILE="/usr/local/bin/log_bla" 

exec 9<> "$LOG_FILE" 

function log_so() { 
    local msg="$1" 
    if [ -z "${LOG_FILE}" ] ; then warn_so "It's pointless use log_so() if LOG_FILE variable is undefined!" ; return 1 ; fi 
    echo -e "${msg}" 
    echo -e "${msg}" >&9 
    return 0 
} 

linenum=1 
while [[ $linenum -lt 2000 ]] ; do 
    log_so "short text: $linenum" 
    let linenum++ 
done 

exec 9>&- 
+0

我們嘗試了這一點,並且在4.1中我們已經無法使用了。現在我們有一個解決方法,那就是重構腳本以刪除一些輸出並整合它。如果有一個解決方案不需要升級bash(而不是ATM選項),並允許更多的輸出,這將是相當有用的。 –