将 bash 脚本输出重定向到系统日志后未打印提示



我找到了这篇文章,它解释了如何将bash脚本的输出重定向到syslog。这正是我所需要的,但有一个问题。

#!/bin/bash
# Don't ignore any error and return when first error occurs.
exec 1> >(logger -s -t $(basename $0)) 2>&1
set -e  
# a list of command(s) that can fail:
chown -R user1:user1 /tmp/myappData/* 
chown -R user1:user1 /tmp/myappTmp/* 
chown -R user1:user1 /tmp/myappLog/* 
#...
exit 0

当我执行上面的脚本时,发生错误,我看到有时在脚本执行后提示不会返回。我不知道为什么会发生这种情况。除非我按回车键,否则提示不会返回。

我担心如果应用程序使用此脚本,它可能无法返回正确的退出代码。

如果我注释掉"set -e",那么在脚本执行后,提示总是正确返回

所以我的问题是,设置脚本以使它在出错时退出并将相应的消息记录到 syslog 的正确方法是什么?

感谢您的帮助和建议!

这里的问题是脚本退出后logger管道仍在运行,因此要记录的一些最后内容会在父 shell 发出提示打印。如果向上滚动,则会发现提示隐藏在先前输出中的某个位置。


如果你有一个非常非常新的 bash,你可以收集过程替换的 PID,稍后wait它。

exec {orig_out}>&1 {orig_err}>&2 1> >(logger -s -t "${0##*/}") 2>&1; logger_pid=$!
[[ $logger_pid ]] || { echo "ERROR: Needs a newer bash" >&2; exit 1; }
cleanup() {
exec >&$orig_out 2>&$orig_err
wait "$logger_pid"
}
trap cleanup EXIT

对于较旧的 bash,您可以考虑其他技巧。例如,在 Linux 上,您可以使用flock命令在退出之前尝试获取对锁定文件的独占访问权限,前提是确保只要记录器正在运行,该锁就一直保持:

log_lock=$(mktemp "${TMPDIR:-/tmp}/logger.XXXXXX")
exec >(flock -x "$log_lock" logger -s -t "${0##*/}") 2>&1
cleanup() {
exec >/dev/tty 2>&1 || exec >/dev/null 2>&1
flock -x "$log_lock" true
}
trap cleanup EXIT

最新更新