是否有一些写剧本的权限?是否不鼓励使用大型/长型bash脚本,这种方式不需要进行日志记录?
我尝试了几种不同的方法来记录脚本输出,但是在决定它们时需要引用一些东西:
示例1:
log_file='test.log' log () { # Writes a message to the log with a full timestamp and log level, "INFO" if not specified. # Requires a global variable, "$log_file" # Example: log 'Something happened' # or: log 'Bad stuff happened' 'WARNING' local log_msg="$1" local log_lvl="$2" if [ -z "$log_lvl" ]; then log_lvl="INFO" fi local log_prefix="$(printf '[%s] [%s]' "$(date +'%Y/%m/%d %T.%3N')" "$log_lvl")" printf '%-36s %s\n' "$log_prefix" "$log_msg" >> "$log_file" }
示例2:
set -o pipefail log_file='test.log' log () { # Relies on stdin! local msg="$(cat -)" echo "$msg" echo '['"$(date)"']' "$msg" >> "$log_file" } echo test |& log echo "$?" not_a_command |& log echo "$?" echo finished |& log echo "$?"
答案 0 :(得分:1)
BashFAQ #106直接就位;下面将讨论一些个人最佳实践,但有问题的FAQ是由Freenode #bash IRC频道背后的同一个人维护的社区资源,更完整,并且在发生任何冲突时进行控制。
运行echo "foo" >>"$filename"
会在运行echo
之前打开输出文件名,然后再关闭它。这使得记录非常高开销;不要那样做。代替:
# in bash 4.1 or later
exec {log_fd}>"$filename" # open a log file for output
echo "Log this statement" >&"$log_fd" # and write to it efficiently
在早期版本的bash中,您需要自己分配FD:
# manually selecting FD 3 to use for logging
exec 3>"$filename"
echo "Log this statement" >&3
在bash中,这意味着如果可能的话,你应该避免使用子shell或外部进程。在bash 4中,下面是一个示例,说明如何执行此操作:
[[ $logfile ]] && exec {log_fd}>"$logfile"
log() {
# log to stderr unconditionally
printf '%s\n' "$*" >&2
# log to logfile if we have a file descriptor for it
[[ $log_fd ]] && printf '[%(%Y-%m-%dT%H:%M:%S)T] %s\n' -1 "$*" >&"$log_fd"
}
请注意bash 4.2扩展名%(...)T
作为外部date
命令的内置替换,以及缺少任何可能打开新文件描述符或生成子shell的操作。
对于bash 4.0或更新版本,BASH_XTRACEFD
提供了一种在不污染stderr的情况下使用set -x
的方法(通过为要发出的语句级跟踪指定备用文件描述符)。使用它!
#!/usr/bin/env bash
PS4=':${BASH_SOURCE##*/}:${LINENO}+' ## set prefix format for logged lines
[[ $tracefile ]] && exec {BASH_XTRACEFD}>>"$tracefile" && set -x
如果您的脚本使用tracefile=foo.trace
运行,则上面将附加执行期间调用该文件的所有操作的完整逐行日志,其中包含源文件和前面每行的行号。一般来说,这可以让您获得比其他方式更详细的日志记录,并且工作量大大减少。
有一些例外:set -x
输出不是非常有用的一个地方是显示read
的结果。可以使用noop:
while read -r foo bar baz; do
: foo="$foo" bar="$bar" baz="$baz"
# ...put your other logic here...
done <inputfile.txt
这将记录:
(相当于true
的noop命令)的调用,其值foo
,bar
和baz
填充{ {1}}作为跟踪文件的一部分作为参数传递。