Bash - 记录脚本

时间:2018-03-27 20:32:11

标签: bash logging

我有一个很长的(~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中省略一行,那么这个日志就是完美的。

2 个答案:

答案 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