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


8

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

在机器设置/ cloud-init脚本的顶部,我有以下内容:

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

这在将输出发送到文件和syslog时非常有用,但不会通过管道将输出发送到终端。

一般而言,除了从远程控制台进行调试之外,没有终端输出不是一个大问题。发生这种情况时,我完全是盲目的,因为执行bash脚本时控制台是空白的。

是否有一种简单的方法使用bash重定向或其他方法将所有输出(标准输出以及标准错误)同时传输到文件,syslog和终端?

我正在运行Ubuntu 16.04。

Answers:


8

在其中添加一个嵌套的流程替换和另一个tee

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

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


我对多个tee调用感到困惑,它将分叉到n个流,这不应该等效吗?exec &> >(tee /tmp/box-setup.log >(logger -t box-setup))
ThorSummoner

3

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

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

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


原来的问题:

tee可以复制到多个目的地。使用/dev/tty特殊文件将其中一个作为终端。我认为它总是指当前过程的控制tty。也许更好,/dev/stderr因为tee的stderr仍连接到外壳的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原始脚本的stdout,而不是stderr。


1

只需将/dev/stderr(您的选择)添加为输出即可tee

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

标准输出和标准错误将合并。如果要保留其顺序,则无法将它们分开,这通常是合乎需要的。无论他们是否都去同一个地方(例如终端)都没关系。


tee的标准输出是记录器的管道,而不是终端。这是stderr在这一点上仍是终端的基础上,exec &> >(tee /dev/stderr > /dev/null)预期在交互shell工作。 stderr似乎比我的/dev/tty想法更好,因为它可以让您轻松地通过重定向关闭脚本。
彼得·科德斯
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.