将 stdout 和 stderr 发送到文件、系统日志和终端

将 stdout 和 stderr 发送到文件、系统日志和终端

对于我正在启动的某些云计算机,我尝试记录到特定文件、系统日志和终端/控制台。

在我的机器设置/云初始化脚本的顶部,我有以下内容:

#!/bin/bash
exec &> >(tee "/tmp/box-setup.log" | logger -t box-setup)
apt-get install -y some-package

这对于将输出发送到文件和系统日志非常有效,但它不会通过管道将输出发送到终端。

一般来说,没有终端输出并不是一个大问题,除非我从远程控制台进行调试。当这种情况发生时,我完全失明了,因为 bash 脚本执行时控制台是空白的。

有没有一种简单的方法使用bash重定向或其他方式将所有输出(标准输出和标准错误)同时传输到文件、系统日志和终端?

我运行的是 Ubuntu 16.04。

答案1

添加一个嵌套进程替换和另一个,tee如下所示:

exec &> >(tee >(tee "/tmp/box-setup.log" | logger -t box-setup))

主进程替换中的第一个tee将 STDOUT/STDERR 发送到终端,也发送到嵌套进程替换,tee内部将内容保存在文件中/tmp/box-setup.log,管道也用于将输出发送到loggerSTDIN。

答案2

我完全失明了,因为 bash 脚本执行时控制台是空白的。

您可能想以不同的方式解决该问题:在后台运行 bash 脚本,然后运行less /tmp/box-setup.log并按 F 键以在将行添加到其正在监视的文件中时不断更新屏幕(如tail -f)。

如果在后台运行脚本出现问题,请使用tmuxscreen将多个会话复用到一个 ssh 连接上。less在另一个 shell 中使用相同的命令。


原来的问题:

tee可以复制到多个目的地。使用特殊文件将其中之一设为终端/dev/tty。我认为它总是指当前进程的控制tty。或者可能更好/dev/stderr,因为tee的 stderr 仍然连接到 shell 的 stderr。 (这可以让您使用 &> /dev/null 使脚本静音)。

exec &> >(tee /dev/stderr "/tmp/box-setup.log" | logger -t box-setup)

顺便说一句,这相当于但比(tee /dev/stderr | tee "/tmp/box-setup.log" | logger ...).

可以使用一些文件描述符克隆来提供tee原始脚本的标准输出,而不是标准错误。

答案3

只需将/dev/stderr(您的选择)作为输出添加到tee.

exec &> >(tee /dev/stderr "/tmp/box-setup.log" | logger -t box-setup)

标准输出和标准错误将被合并。如果您想保留它们的顺序,则无法将它们分开,这通常是可取的。无论如何,如果他们都去同一个地方(例如航站楼)也没关系。

相关内容