重定向并记录脚本输出


8

我正在尝试整理以下代码段,设计目标是记录脚本的所有输出,而不应该是包装器。线越少越好。

我不在乎用户输入(在此阶段),目标脚本是非交互式运行的。

该代码段需要

  • 输出标准输出到日志,并始终回显到控制台
  • 输出stderr记录日志,并回显到控制台,如果已启用调试
  • stderr消息应带有时间戳和其他用途

目前,我有以下内容只能在最新版本的bash(4.2+?)下进行测试,例如在Ubuntu精确版中,但是在CentOS6上表现不佳。

DEBUG_LOG="${0##*/}.log"

# copy stdout to log always and echo to console
exec >  >(tee -a ${DEBUG_LOG})           

# copy stderr to log only, unless debugging is enabled
[ $DEBUG_TEST = "true" ] \
  && exec 2> >(tee -a ${DEBUG_LOG} >&2) \
  || exec 2>> ${DEBUG_LOG}

那这个

# Expand escaped characters, wrap at 70 chars on spaces, 
# and indent wrapped lines
msg_log() { 
  echo -e "$(date +%T) ${0##*/}: $1" \
    | fold -w70 -s | sed '2~1s/^/  /' >&2; 
}
msg_con() { 
  if [ "${DEBUG_TEST}" = "true" ]; then 
    msg_log "$1"
  else
    echo -e "$1" | fold -w70 -s | sed '2~1s/^/  /'; 
  fi
}

而不是echo我可以调用这些msg过程之一,例如msg_con "hello world"
然后,通过在调用时将其设置为环境变量,脚本输出也将转到stderr  DEBUG_TEST=true myscript

我已经阅读了exec可能无法在某些shell(例如busybox)中工作。https://stackoverflow.com/a/5200754上有一个mkfifo和fork组合,它的功能类似,但除非绝对需要,否则我不愿使用fork。

请更喜欢bash的示例,但是在sh下工作或更便携的东西会很好。有任何想法吗?

Answers:


1
function startLogging {
    exec > >(gawk -v pid=$$ '{ print strftime("%F-%T"),pid,$0; fflush(); }' | tee -a $logfile)
    [ ! -z "$DEBUG" ] && exec 2>&1 || exec 2> >(gawk -v pid=$$ '{ print strftime("%F-%T"),pid,$0; fflush(); }' >>$logfile)
    echo "=== Log started for $$ at $(date +%F-%T) ==="
}

您需要将$ logfile设置为某些内容


这有点酷,我阅读的方式是使用gawk添加消息标题。将那些也添加到命令输出中会带来额外的副作用。
格伦

使用gawk在每条日志行中添加时间戳(和进程ID)的原因是,每次写入输出并更新时间戳时,它将被执行。使用gawk而不是awk也很重要,因为我认为strftime函数是GNU扩展。
安吉洛

0

exec > filename应该可以在sh中使用,并且实际上可以在busybox v1.15.3(2011年11月)中使用。但是,>(command)由于它是bash扩展,因此进程替换是不可移植的。只是避免在脚本中使用它。为什么>>还不够?

exec 1>>${DEBUG_LOG}
exec 2>>${DEBUG_LOG}

另一个解决方案是在脚本之外指定重定向。当您的脚本在后台调用(通过cron或系统脚本等)时,应像这样调用它们

./my_script 1>>${DEBUG_LOG} 2>>${DEBUG_LOG}

当您手动调用脚本并想要查看输出时,只需调用它而无需重定向。


1
问题提问者希望脚本的输出同时进入控制台和日志文件。

0

这两个示例将完成您声明的目标

echo -n $(date) >> $DEBUG_LOG
command 2>&1 | tee -a $DEBUG_LOG

要么

echo -n $(date) >> $DEBUG_LOG
command >> $DEBUG_LOG 2>&1

0

您可以使用teecommand或scriptcommand都非常有用。


脚本看起来很酷,但是并不能真正满足我的需要,该行为必须在运行时进行修改。
格伦
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.