从Bash脚本中的函数写入泄漏的文件描述符

从Bash脚本中的函数写入泄漏的文件描述符,bash,unix,ubuntu-10.04,file-descriptor,Bash,Unix,Ubuntu 10.04,File Descriptor,我们有一个由cron调用的shell脚本,它以root用户身份运行 此脚本输出日志记录和调试信息,并在某个特定点失败。这一点根据脚本创建的输出量而有所不同(例如,如果启用更多调试输出,则会更快失败) 但是,如果作为用户直接调用脚本,那么它就可以正常工作 我们已经创建了一个简化的测试用例来演示这个问题 剧本是: #!/bin/bash function log_so () { local msg="$1" if [ -z "${LOG_FILE}" ] ; then warn_so "It

我们有一个由cron调用的shell脚本,它以root用户身份运行

此脚本输出日志记录和调试信息,并在某个特定点失败。这一点根据脚本创建的输出量而有所不同(例如,如果启用更多调试输出,则会更快失败)

但是,如果作为用户直接调用脚本,那么它就可以正常工作

我们已经创建了一个简化的测试用例来演示这个问题

剧本是:

#!/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上使用Bash4.1.5(1)版本


如果您有任何关于解决方法的想法或建议,我们将不胜感激。

手动打开fd,然后将其清理干净怎么样?我没有Bash4.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>&-
LOG_FILE=“/usr/local/bin/LOG_bla”
exec 9“$LOG_文件”
函数log_so(){
本地消息=“1美元”
如果[-z“${LOG_FILE}”];则警告_so“如果LOG_FILE变量未定义,则使用LOG_so()毫无意义!”;返回1;fi
echo-e“${msg}”
echo-e“${msg}”>&9
返回0
}
linenum=1
而[$linenum-lt 2000]];做
log_so“短文本:$linenum”
让linenum++
完成
执行董事9>&-

用手打开fd,然后将其清理干净怎么样?我没有Bash4.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>&-
LOG_FILE=“/usr/local/bin/LOG_bla”
exec 9“$LOG_文件”
函数log_so(){
本地消息=“1美元”
如果[-z“${LOG_FILE}”];则警告_so“如果LOG_FILE变量未定义,则使用LOG_so()毫无意义!”;返回1;fi
echo-e“${msg}”
echo-e“${msg}”>&9
返回0
}
linenum=1
而[$linenum-lt 2000]];做
log_so“短文本:$linenum”
让linenum++
完成
执行董事9>&-

即使ulimit为128,也无法在4.2.24(1)版本的Fedora16上复制。建议迁移到更具体的论坛。我刚刚了解到,这是bash 4.1及更高版本中的一个错误,已在4.2中得到纠正,我不知道升级bash是否是我们的选择,因此仍然希望找到bash 4.1.x的解决方案(如果存在)。无法在Fedora 16、GNU bash 4.2.24(1)版本上复制,即使ulimit为128。建议迁移到更具体的论坛。我刚刚了解到,这是bash 4.1及更高版本中的一个错误,已在4.2中得到纠正,我不知道升级bash是否是我们的选择,因此仍然希望为bash 4.1.x找到一个解决方案(如果存在)。我们尝试了这个方法,但在4.1中,它不起作用。我们现在有一个解决方案,涉及到对脚本进行重构,以删除一些输出并整合它。如果有一个解决方案不需要升级bash(而不是optionatm),并且允许更多的输出,这将是非常有帮助的。我们尝试了这个方法,但在4.1版本中,它不起作用。我们现在有一个解决方案,涉及到对脚本进行重构,以删除一些输出并整合它。如果有一个解决方案不需要升级bash(而不是optionatm),并且允许更多的输出,那将非常有帮助。