shell - 重定向到日志文件时如何在 stdout 和 stderr 输出前加上时间戳?

标签 shell logging pipe stdout init

在 Linux 中,我在初始化脚本 (SysVInit) 中启动了一个名为 $cmd 的程序。我已经将 $cmd 的 stdout 和 stderr 重定向到两个不同的日志文件中,分别称为 $stdout_log$stderr_log。现在我还想在打印到日志文件的每一行前面添加一个时间戳。

我尝试编写一个名为 log_pipe 的函数,如下所示:

log_pipe() {
    while read line; do
        echo [$(date +%Y-%m-%d\ %H:%M:%S)] "$line"
    done
}

然后将我的脚本的输出通过管道传输到此函数,然后将它们重定向到日志文件,如下所示:

$cmd | log_pipe >> "$stdout_log" 2>> "$stderr_log" &

我得到的是一个空的 $stdout.log (stdout) 应该没问题,因为 $cmd 通常不打印任何内容。以及一个只有时间戳但没有错误文本的 $stderr.log 文件。

我的错误推理在哪里?

PS:因为问题存在于一个初始化脚本中,所以我只想使用基本的 shell 命令而不需要额外的包。

最佳答案

在任何 POSIX shell 中,尝试:

{ cmd | log_pipe >>stdout.log; } 2>&1 | log_pipe >>stderr.log

另外,如果你有 GNU awk(有时称为 gawk),那么 log_pipe 可以变得更简单和更快:

log_pipe() {  awk '{print strftime("[%Y-%m-%d %H:%M:%S]"),$0}'; }

例子

例如,让我们创建命令 cmd:

cmd() { echo "This is out"; echo "This is err">&2; }

现在,让我们运行命令并查看输出文件:

$ { cmd | log_pipe >>stdout.log; } 2>&1 | log_pipe >>stderr.log
$ cat stdout.log
[2019-07-04 23:42:20] This is out
$ cat stderr.log
[2019-07-04 23:42:20] This is err

问题

cmd | log_pipe >> "$stdout_log" 2>> "$stderr_log"

以上将标准输出从 cmd 重定向到 log_pipelog_pipe 的 stdout 被重定向到 $stdout_loglog_pipe 的 stderr 被重定向到 $stderr_log问题是 cmd 的标准错误永远不会被重定向。它直接进入航站楼。

例如,考虑这个 cmd:

cmd() { echo "This is out"; echo "This is err">&2; }

现在,让我们运行命令:

$ cmd | log_pipe >>stdout.log 2>>stderr.log
This is err

我们可以看到 This is err 没有发送到文件 stderr.log。相反,它出现在终端上。 log_pipe 永远不会看到它。 stderr.log 仅捕获来自 log_pipe 的错误消息。

关于shell - 重定向到日志文件时如何在 stdout 和 stderr 输出前加上时间戳?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56896871/

相关文章:

shell - KornShell 脚本 - 当子进程中断时父进程未完成 (TRAP INT)

Linux脚本按行中的日期时间模式过滤文本文件中的行

logging - 过滤发送或退回邮件的 postfix 日志

具有大对象的 Python 多处理管道将挂起

c# - 如何在顶部导航中没有后退按钮的情况下在 Xamarin Shell 中切换页面

python - 登录 Flask 微服务内部

java - 登录java程序

c - fgetc 在轮询管道后仍然阻塞

python - 使用管道表达 Pandas 子集

linux - 如何在子shell中找出父shell的用户?