【发布时间】:2019-12-31 19:15:29
【问题描述】:
想要记录所有stdout 和stderr 以分隔文件并为每一行添加时间戳。
尝试了以下方法,但没有时间戳。
#!/bin/bash
debug_file=./stdout.log
error_file=./stderr.log
exec > >(tee -a "$debug_file") 2> >(tee -a "$error_file")
echo "hello"
echo "hello world"
this-will-fail
and-so-will-this
添加时间戳。 (只希望在日志输出前加上时间戳。)
#!/bin/bash
debug_file=./stdout.log
error_file=./stderr.log
log () {
file=$1; shift
while read -r line; do
printf '%(%s)T %s\n' -1 "$line"
done >> "$file"
}
exec > >(tee >(log "$debug_file")) 2> >(tee >(log "$error_file"))
echo "hello"
echo "hello world"
this-will-fail
and-so-will-this
后者将时间戳添加到日志中,但它也有可能弄乱我的终端窗口。重现这种行为并不是直截了当的,它只是偶尔发生。我怀疑它必须与子程序/缓冲区仍然有输出流过它。
弄乱我的终端的脚本示例。
# expected/desired behavior
user@system:~ ./log_test
hello
hello world
./log_test: line x: this-will-fail: command not found
./log_test: line x: and-so-will-this: command not found
user@system:~ # <-- cursor blinks here
# erroneous behavior
user@system:~ ./log_test
hello
hello world
user@system:~ ./log_test: line x: this-will-fail: command not found
./log_test: line x: and-so-will-this: command not found
# <-- cursor blinks here
# erroneous behavior
user@system:~ ./log_test
hello
hello world
./log_test: line x: this-will-fail: command not found
user@system:~
./log_test: line x: and-so-will-this: command not found
# <-- cursor blinks here
# erroneous behavior
user@system:~ ./log_test
hello
hello world
user@system:~
./log_test: line x: this-will-fail: command not found
./log_test: line x: and-so-will-this: command not found
# <-- cursor blinks here
为了好玩,我在脚本末尾放了一个sleep 2,看看会发生什么,问题再也没有发生过。
希望有人知道答案或可以指出正确的方向。
谢谢
编辑
从 Charles Duffy 回答的另一个问题来看,我想要实现的目标在 bash 中是不可能实现的。 Separately redirecting and recombining stderr/stdout without losing ordering
【问题讨论】:
-
是的,你有一个竞争条件,因为所有这些进程都是彼此异步运行的。 如果
write()沿边界分割,使其不包含整行,则可以将它们混合。 -
顺便说一句,
$(date +%s)是真的如果你把它放在一个内部循环中执行很慢,足够慢以至于它实际上会严重影响你的输出速度。如果您使用的是 bash 4.3+,最好printf '%(%s)T %s\n' -1 "$line" -
哇!我不知道
%(%$strftime_string)TBTW,另一种选择是ts来自ubuntu 上的moreutils包。跨系统复制这个二进制文件通常是可行的。 -
顺便说一句,在不相关的说明中,您应该正确地将标准错误重定向到标准错误:
exec > >(tee -a "$debug_file") 2> >(tee -a "$error_file" >&2) -
@anishsane, ...在任何 daemontools 风格的工具套件(runit,&c)中都有
ts的等价物,因此在任何您可能碰巧在的平台;见 f/e cr.yp.to/daemontools/tai64n.html
标签: bash redirect stdout stderr