从Bash脚本中的函数写入泄漏的文件描述符
我们有一个由cron调用的shell脚本,它以root用户身份运行 此脚本输出日志记录和调试信息,并在某个特定点失败。这一点根据脚本创建的输出量而有所不同(例如,如果启用更多调试输出,则会更快失败) 但是,如果作为用户直接调用脚本,那么它就可以正常工作 我们已经创建了一个简化的测试用例来演示这个问题 剧本是:从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
#!/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),并且允许更多的输出,那将非常有帮助。