我正在为 AWS EC2 编写一个 Terraform 模块,其中涉及在用户数据部分执行 bash。当我开发时,我编写的脚本中遇到了问题,但 AWS 和 Terraform 都没有提供任何错误日志,直到我在 AWS 支持中找到这一行论坛:
exec > >(tee /var/log/user-data.log|logger -t user-data -s 2>/dev/console) 2>&1
user_data
这一行成功写入了脚本执行的所有输出,/var/log/user-data.log
但我不理解整行。我知道exec >
将所有输出写入一个文件,在这种情况下>(..)
,但我不明白为什么使用它tee
或需要那里的管道。
答案1
让我们把它分成几部分:
exec
在 shell 本身上应用重定向,因此确实exec > somefile
会将 shell 及其子级的所有后续输出定向到该文件。
在这里,我们使用进程替换代替简单的文件名>( command... )
。它告诉 shell 在内部运行命令,并创建一个连接到该命令输入的文件名。foo > >(bar)
有点像foo | bar
,除了进程替换也可以用于更复杂的情况,并且不像管道那样调用子shell。 (<(command...)
相反,这将使输出该命令的出现就像来自文件一样。)
里面的命令是tee filename | logger ...
.tee
将其输入复制到 stdout 和给定文件,并将logger
其输入发送到系统日志。 (重定向2>/dev/console
将应用于来自 的错误输出logger
,如果系统日志不起作用,它可能会打印一些错误。)
然后是2>&1
,它告诉 shell 将错误消息(stderr)也重定向到相同的进程替换。
因此,重定向后,shell 输出的所有内容(正常输出和错误输出)都会(通过tee
)发送到文件并(通过logger
)发送到系统日志。
(我认为这些都不是 AWS 或 Linux 特有的,除非在 AWS 上的使用有一些特殊性logger
。)