我希望 shell 脚本能够将其所有输出记录到外部文件中stdout
,stderr
并将时间戳添加到每行(加上一些额外的项目),而不更改脚本的调用方式。输出重定向应该发生在脚本本身内。我也不应该单独更改脚本或管道命令中的任何现有代码。理想情况下,我只需要在脚本中添加几行。
使用这两个答案:
我已经到了可以在 Bash 上运行的地步了
#! /usr/bin/env bash
CUSTOM_PREFIX1="FancyScript"
CUSTOM_PREFIX2="SomeRunID_12-3-4.5"
LOG_FILE="/var/log/script.log"
touch $LOG_FILE
exec 1>> >(while IFS= read -r line; do printf '[%s] %s %s: %s\n' "$(date '+%Y-%m-%d %H:%M:%S')" "${CUSTOM_PREFIX1}" "${CUSTOM_PREFIX2}" "${line}"; done >> "${LOG_FILE}")
exec 2>&1
# Script continues...
d
echo "Hello"
运行上面的脚本不会产生任何输出,并产生以下日志文件:
# cat /var/log/script.log
[2022-02-23 03:11:45] FancyScript SomeRunID_12-3-4.5: Development/shell_log.sh: line 12: d: command not found
[2022-02-23 03:11:45] FancyScript SomeRunID_12-3-4.5: Hello
到目前为止一切顺利,但我想改变两件事。
- 使其在 POSIX shell (
sh
) 中工作而不依赖于 Bash。常规sh
不喜欢exec 1>> >(...)
(while IFS= read ....)
我想将其通过管道传输到脚本本身内的函数,而不是那个长子进程。就像是pipe_log() {...}
答案1
我认为logger
专门为此编写:写入系统日志文件。
有关详细信息,请参阅上面该实用程序的logger(1)
手册 ( man logger
) 和 POSIX 规范的链接。
答案2
最多先进的Unix 工具箱中的文本处理实用程序是ex
/vi
和awk
,m4
均来自 70 年代。它们都没有时间格式化功能(尽管使用 POSIX awk
,您可以通过 获取纪元时间srand()
,并且 awk 或 vi 的几种实现都具有时间格式化功能作为扩展)。
perl
然而,从 80 年代中期开始,POSIX 就非常普遍了,鉴于它只有一种实现,因此 POSIX 不必参与其标准化。
因此,您始终可以将sh
脚本包装在:
{
your-script here
} 2>&1 | perl -MPOSIX -pse '
$_ = strftime("[%Y-%m-%dT%T%z]", localtime) . " $prefix$_"
' -- '-|=1' "-prefix=$CUSTOM_PREFIX" >> /path/to/file.log
为每一行添加时间戳。
请注意,%z
这些时间戳是明确且可后处理的。
答案3
我logger
上面提到的适用于较旧的系统日志记录环境。在较新的、基于 systemd 的系统上,该systemd-cat
实用程序更合适:
echo 'my message' | systemd-cat -p info -t /path/to/script/executing/this