【问题标题】:What guidelines are there for logging script output? [closed]记录脚本输出有哪些准则? [关闭]
【发布时间】:2016-12-14 00:08:14
【问题描述】:

剧本写作有权威吗?是否不鼓励使用大/长 bash 脚本,从而使日志记录变得不必要?

我尝试了几种不同的方法来记录脚本输出,但在决定它们之间时想参考一些东西:

  1. 将一些行回显/打印到控制台供用户读取,“手动”将更完整的信息写入日志文件(通过调用添加时间戳并写入文件的“日志”函数)。用另一个函数检查命令的退出代码。
  2. 将命令输出通过管道传输到从标准输入读取的日志函数,然后将其写入文件(带有时间戳),最后将组合输出回显到控制台。

示例 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 "$?"

【问题讨论】:

    标签: linux bash logging


    【解决方案1】:

    BashFAQ #106直接就位;下面将讨论一些个人的最佳实践,但所讨论的常见问题解答是由 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 提供了一种在不污染标准错误的情况下使用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 命令),其中foobarbaz 的值由read 填充,作为参数作为跟踪的一部分传递文件。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-12-15
      • 2013-10-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-09-19
      相关资源
      最近更新 更多