我仍在学习如何编写 bash 脚本,因此我根据在 Google 上搜索到的几个答案拼凑了这个脚本。
#!/bin/bash
set -e
run_receiver(){
pushd event-receiver
npm run clean
npm run build
node dist/index.js "$@"
popd
}
run_simulator(){
pushd simulator
npm run clean
npm run build
node dist/index.js "$@"
popd
}
run_receiver "$@" | awk '{ print "[receiver]", $0 }' 2>&1 &
run_simulator "$@" | awk '{ print "[simulator]", $0 }' 2>&1 &
#do other things....
该脚本同时运行多个节点应用程序并[name]
在每个节点上添加前缀,以便我可以识别哪个命令生成了每个日志。
现在我想在每行中添加日期或某种时间戳。有人能告诉我如何实现吗?谢谢
答案1
首先,您可能希望在2>&1
之前添加awk
,因为如果您想将时间戳和名称添加到错误消息以及标准输出中,则需要先进行此操作。否则,awk 将看不到标准错误消息。因此您需要:
run_receiver "$@" 2>&1 | awk '{ print "[receiver]", $0 }' &
run_simulator "$@" 2>&1 | awk '{ print "[simulator]", $0 }' &
接下来,对于时间戳,您可以使用date
并将的输出date
作为变量传递给awk
:
run_receiver "$@" 2>&1 | awk -v date="$(date)" '{ print date,"[receiver]", $0 }' &
但这并不是您真正想要的:那只会在awk
启动时计算一次日期,因此所有命令都会有相同的日期戳。您需要awk
在每一行输入上计算日期,因此您需要一些更复杂的东西:
run_receiver "$@" 2>&1 |
awk '{ com="date -Iseconds"; com | getline date; print date,"[receiver]", $0 }' &
它将存储date -Iseconds
在变量中com
,然后执行com
,将输出传递给 awkgetline
并将其存储在 awk 变量中,date
然后打印该变量。但是,awk
Ubuntu 中的默认设置实际上mawk
是mawk
缓冲其输入,所以你还需要告诉它不要缓冲,否则时间戳将不正确。所以你还需要再做一点调整:
run_receiver "$@" 2>&1 |
awk -Winteractive '{
com="date -Iseconds";
com | getline date;
close(com);
print date,"[receiver]", $0
}' &
这将产生如下输出:
[receiver] 2022-09-23T13:33:23+03:00 line 1
[receiver] 2022-09-23T13:33:24+03:00 line 2
[receiver] 2022-09-23T13:33:25+03:00 line 3
[receiver] 2022-09-23T13:33:26+03:00 line 4
您还可以使用 GNU awk
(gawk
在 Ubuntu 上调用),它提供了一些用于日期操作的内置函数:
run_receiver "$@" 2>&1 |
gawk '{ date=strftime("%Y-%m-%d %H:%M:%S"); print "[receiver]",date,$0}'
产生如下输出:
[receiver] 2022-09-23 13:35:42 line 1
[receiver] 2022-09-23 13:35:43 line 2
[receiver] 2022-09-23 13:35:44 line 3
[receiver] 2022-09-23 13:35:45 line 4
答案2
您可以使用包ts
中的命令moreutils
(可从“universe”存储库获得),将您的命令合并[name]
到可选格式字符串中,以消除对的需要awk
。例如:
run_receiver "$@" 2>&1 | ts '[receiver] %Y-%m-%d %H:%M:%S'