【问题标题】:writing from a function in a Bash script leaking file descriptors从 Bash 脚本中的函数写入泄漏文件描述符
【发布时间】:2012-05-12 03:46:22
【问题描述】:

我们有一个由 cron 调用并以 root 身份运行的 shell 脚本。

此脚本输出日志记录和调试信息,并且在某一时刻失败了。这一点取决于脚本创建的输出量(例如,如果我们启用更多调试输出,它会更快地失败)。

但是,如果脚本以用户身份直接调用,则它可以正常工作。

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

脚本是:

#!/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 subshel​​l 并调用 /bin/true 但这不仅不起作用,而且 subshel​​l 选项在主脚本中也不可行。

我们还尝试更改 root 的文件描述符限制,但这没有帮助,并尝试将 #!/bin/sh 和 #!/bin/bash 用于脚本。

我们在 Ubuntu 10.04 LTS 上使用 bash 4.1.5(1)-release。

对于解决方法的任何想法或建议将不胜感激。

【问题讨论】:

  • 无法在 Fedora 16、GNU bash 版本 4.2.24(1)-release 上复制,即使 ulimit 为 128。建议迁移到更具体的论坛。
  • 我刚刚得知这是 bash 4.1 及更早版本中的一个错误,已在 4.2 中更正,我不知道升级 bash 是否适合我们,所以仍然想找到一个bash 4.1.x 的解决方案(如果存在)。

标签: bash unix ubuntu-10.04 file-descriptor


【解决方案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>&-

【讨论】:

  • 我们试过这个,但在我们拥有的 4.1 中它不起作用。我们现在有一个解决方法,涉及重构脚本以删除一些输出并整合它。如果有一个不需要升级 bash(不是 ATM 选项)并且允许更多输出的解决方案,那将非常有帮助。
猜你喜欢
  • 2015-09-23
  • 2011-01-15
  • 1970-01-01
  • 1970-01-01
  • 2014-09-20
  • 2020-01-05
  • 1970-01-01
  • 1970-01-01
  • 2023-04-09
相关资源
最近更新 更多