我有一个很长的(~2,000行)脚本,我试图记录以备将来调试。现在我有:
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,我会感到高兴。
...
tldr:我如何通常记录脚本中所有命令的时间,命令和退出代码?
...
(第一次发帖,感谢反馈)
更新
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
我已经尝试在陷阱中设置+ x但是然后设置+ x被记录。如果我能找到一种方法从xtrace中省略一行,那么这个日志就是完美的。
答案 0 :(得分:2)
异步行为来自进程替换 - >(...)
中的任何内容都在FIFO的另一端的子shell中运行。由于它是一个单独的过程,因此它本质上是不同步的。
但是,您根本不需要log_with_time
,因此您首先不需要BASH_XTRACEFD
重定向到流程替换。考虑:
# aside: $(date ...) has a *huge* amount of performance overhead here. Personally, I'd
# advise against using it, unless you really need all that precision; $SECONDS will
# be orders-of-magnitude cheaper.
PS4=' prior-exit:$? time:$(date +%H:%M:%S.%4N) ln:$LINENO: '
...此后:
$ true
prior-exit:0 time:16:01:17.2509 ln:28: true
$ false
prior-exit:0 time:16:01:18.4242 ln:29: false
$ false
prior-exit:1 time:16:01:19.2963 ln:30: false
$ true
prior-exit:1 time:16:01:20.2159 ln:31: true
$ true
prior-exit:0 time:16:01:20.8650 ln:32: true
答案 1 :(得分:0)
与Charles Duffy在评论中的对话,给予所有信任:
进程替换>(...)是异步的,允许日志写入落后于与xtrace不同步。 而是使用:
exec {BASH_XTRACEFD}>>$LOGFILE
PS4=' time:$(date +%H:%M:%S.%4N) ln:$LINENO: '
用于同步记录时间和行。
此外,在运行命令之前触发了xtrace,使其成为捕获退出代码的不良候选者。而是使用:
trap 'echo exit:$? >> $LOGFILE' DEBUG
记录每个命令的退出代码,因为陷阱在命令完成时触发。请注意,这不会报告函数调用中的每个步骤,如xtrace。 (可以在这里使用一些措辞帮助)
没有解决方案从xtrace中省略陷阱,但这已经足够了:
LOGFILE="SomeFile.log"
exec {BASH_XTRACEFD}>>$LOGFILE
PS4=' time:$(date +%H:%M:%S.%4N) ln:$LINENO: '
set -x
fail() # test function that returns 1
{
echo "fail" >> $LOGFILE
return 1
}
success() # test function that returns 0
{
echo "success" >> $LOGFILE
return 0
}
trap 'echo $? >> $LOGFILE' DEBUG
fail
success
echo "complete"
的产率:
time:14:10:22.2686 ln:21: trap 'echo $? >> $LOGFILE' DEBUG
time:14:10:22.2693 ln:23: echo 0
0
time:14:10:22.2736 ln:23: fail
time:14:10:22.2741 ln:12: echo fail
fail
time:14:10:22.2775 ln:13: return 1
time:14:10:22.2782 ln:24: echo 1
1
time:14:10:22.2830 ln:24: success
time:14:10:22.2836 ln:17: echo success
success
time:14:10:22.2873 ln:18: return 0
time:14:10:22.2881 ln:26: echo 0
0
time:14:10:22.2912 ln:26: echo complete