我有一份长达约2000行的脚本,我想记录下来以备将来调试。目前我的记录方式如下:
function log_with_time()
{
while read a; do
echo `date +'%H:%M:%S.%4N '` " $a" >> $LOGFILE
done
}
exec 7> >(log_with_time)
BASH_XTRACEFD=7
PS4=' exit($?)ln:$LINENO: '
set -x
echo "helloWorld 1"
这为所有运行的命令提供了非常好的日志记录:
15:18:03.6359 exit(0)ln:28: echo 'helloWorld 1'
我遇到的问题是xtrace似乎是异步的。在较长的脚本中,日志时间落后于实际调用命令的时间,并且退出代码与记录的命令不匹配。
肯定有更好的方法来解决这个问题,但如果我能同步xtrace就会很高兴。
...
简而言之:如何记录脚本中所有命令的时间、命令和退出代码?
...
(第一次发布,请提供反馈)
更新:
exec {BASH_XTRACEFD}>>$LOGFILE
PS4=' time:$(date +%H:%M:%S.%4N) ln:$LINENO: '
set -x
fail()
{
echo "fail" >> $LOGFILE
return 1
}
trap 'echo exit:$? >> $LOGFILE' DEBUG
fail
解决了我所有的同步问题。退出代码和时间戳都很好地工作。我现在唯一的问题是格式:xtrace 报告了陷阱本身。
time:18:30:07.6080 ln:27: fail
time:18:30:07.6089 ln:12: echo fail
fail
time:18:30:07.6126 ln:13: return 1
time:18:30:07.6134 ln:28: echo exit:1
exit:1
我尝试在trap中设置+x,但是set +x被记录了。如果我能找到一种方法从xtrace中省略一行,这个日志就完美了。
>(...)
中的内容都在一个FIFO的另一侧运行,运行在它自己的进程中。对BASH_XTRACEFD
的实际写入本身是完全同步的。 - Charles DuffyPS4
自动插入日期。 - Charles Duffyfunction funcname() {
是POSIX sh和古老的ksh声明约定的混合体(前者只是funcname() {
,后者是function funcname {
),并且与两者都不兼容。最好的做法是选择其中之一——我强烈建议选择POSIX形式,因为bash的ksh-esque函数声明语法实际上没有在ksh中具有相同的语义(在ksh中,它使得在函数中定义的变量默认为本地变量)。 - Charles Duffyprintf %(%H:%M:%S)T -1
命令,可以在不产生子shell并使用exec
系统调用替换该子shell为/usr/bin/date
副本(更不用说设置一对FIFO来读取该子shell的输出等操作)的情况下发出当前时间。 - Charles Duffy