2012-05-02 50 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选项),并允许更多的输出,这将是相当有用的。 –