我有这个脚本,它将日志从每个 Kubernetes pod 发送到 stdout:
#!/usr/bin/env bash
set -e;
oc project cdt-dev
pods=$(oc get pods --show-all=false -o name)
for j in ${pods}; do
oc logs -f "$j" | bunyan -o short -l error &
done
wait;
我想要做的是在日志前面加上 pod 名称,如下所示:
#!/usr/bin/env bash
# ...
for j in ${pods}; do
oc logs -f "$j" | bunyan -o short -l error | echo "$j => $stdin" &
done
wait
我想你可以看到我想要做什么,我通过一个名为 Bunyan 的程序来传输日志,该程序解释日志,然后我想在每一行前面添加 pod 的名称 ($j)。但上面的说法不可能是正确的。有没有办法用普通的旧 bash 来做到这一点?
注意 $stdin 只是一些代表一行 stdin 的虚拟变量,这里并不真正存在。
答案1
一种选择是awk
:
for j in ...; do
oc ... | bunyan --color ... | awk -v node="$j" '{print node " " $0}'
done
运行示例:
$ for j in node1 node2 node3
> do
> echo stuff | awk -v node="$j" '{print node " " $0}'
> done
node1 stuff
node2 stuff
node3 stuff
另一种选择是sed
:
for j in node1 node2 node3; do
j=${j////\\/}
j=${j//&/\\&}
oc ... | bunyan --color ... | sed "s/^/$j /"
done
我们注意转义任何正斜杠或&
in j
,因为 sed 会专门解释s//
命令中的那些。我在那里使用了 bash-ism 在参数扩展中进行搜索和替换。两个正斜杠的意思是“替换所有匹配项”,并且双斜杠的\\
意思是在替换的文本中产生一个反斜杠。
答案2
这对我有用:
oc logs -f "$j" | bunyan -o short -l error | while read line; do echo "$j $line"; done &
但一个问题是我失去了终端样式,这很有帮助。有人知道如何保留控制字符等吗?