将服务器命令输出拆分到下一行

将服务器命令输出拆分到下一行

我正在准备一个 bash 脚本,其中我使用“pssh”在 1000 多个服务器上运行命令(保存在 /tmp/hosts 中)

pssh -h /tmp/hosts -i "uname;date"

[1] 13:10:56 [FAILURE] SERVER1 Exited with error code 255
Stderr: @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@       WARNING: POSSIBLE DNS SPOOFING DETECTED!          @
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
The ECDSA host key for SERVER1 has changed,
and the key for the corresponding IP address 10.238.36.42
has a different value. This could either mean that.............
......................
[2] 13:10:56 [SUCCESS] SERVER2
Linux
Fri Jan 25 12:10:56 UTC 2019
[3] 13:10:56 [SUCCESS] SERVER3
Linux
Fri Jan 25 13:10:56 CET 2019
[4] 13:10:56 [SUCCESS] SERVER4
Linux
Fri Jan 25 12:10:56 UTC 2019
[5] 13:10:56 [SUCCESS] SERVER5
Linux
Fri Jan 25 12:10:56 UTC 2019
[6] 13:10:56 [SUCCESS] SERVER6
Linux
Fri Jan 25 12:10:56 UTC 2019

我期望输出如下,如果有任何警告,则抑制警告

[FAILURE], SERVER1, Exited with error code 255
[SUCCESS], SERVER2,Linux,Fri Jan 25 12:10:56 UTC 2019
[SUCCESS], SERVER3,Linux,Fri Jan 25 12:10:56 UTC 2019
[SUCCESS], SERVER4,Linux,Fri Jan 25 12:10:56 UTC 2019
[SUCCESS], SERVER5,Linux,Fri Jan 25 12:10:56 UTC 2019
[SUCCESS], SERVER6,Linux,Fri Jan 25 12:10:56 UTC 2019
[FAILURE], HOST1, Exited with error code 255
[FAILURE], HOST2, Exited with error code 255

答案1

好吧,感谢@Imorg,你可以使用:

pssh -h /tmp/hosts -i "uname;date"  | grep -o \[[A-Z][A-Z][A-Z]*\].* | sed -Ee 's/(^\[FAILURE\]) (SERVER[0-9]*) (.*)/\1, \2, \3/g' -Ee 's/(^\[SUCCESS\]) (.*)/\1, \2,'"$(uname)"','"$(date)"'/g'

因此,grep -o \[[A-Z][A-Z][A-Z]*\].*输出如下:

[FAILURE] SERVER1 Exited with error code 255
[SUCCESS] SERVER2
[SUCCESS] SERVER3
[SUCCESS] SERVER4
[SUCCESS] SERVER5
[SUCCESS] SERVER6

并且sed -Ee 's/(^\[FAILURE\]) (SERVER[0-9]*) (.*)/\1, \2, \3/g'between strings containingFAILURE`和SERVER以及EXITED之间。

and will在前两个单词之间sed -Ee 's/(^\[SUCCESS\]) (.*)/\1, \2,'"$(uname)"','"$(date)"'/g'添加and will add 。,,output of uname command, output of date command

所以最终输出将如下所示:

[FAILURE], SERVER1, Exited with error code 255
[SUCCESS], SERVER2,Linux,Fri Jan 25 19:27:30 UTC 2019
[SUCCESS], SERVER3,Linux,Fri Jan 25 19:27:30 UTC 2019
[SUCCESS], SERVER4,Linux,Fri Jan 25 19:27:30 UTC 2019
[SUCCESS], SERVER5,Linux,Fri Jan 25 19:27:30 UTC 2019
[SUCCESS], SERVER6,Linux,Fri Jan 25 19:27:30 UTC 2019

答案2

我并不是 100% 确定你在问什么,但听起来以下内容可能对你有用:

# What you get
$ uname; date
Linux
Fri 25 Jan 13:09:13 GMT 2019

# What you want
$ echo "$(uname), $(date)"
Linux, Fri 25 Jan 13:09:42 GMT 2019

所以你的命令是:

pssh -h /tmp/hosts -i 'echo "$(uname), $(date)"'

(请注意单引号的使用 - 这很重要,这样您的本地 shell 就不会扩展进程子 shell)

它的作用是作为子 shell 运行unamedate并将结果作为变量返回到echo命令中。如上所述:

echo "$(uname), $(date)"
# expands as
echo Linux, Fri 25 Jan 13:10:57 GMT 2019

顺便说一句,我对 pssh 不太熟悉。我假设它只是运行您的用户在远程服务器/etc/group文件上定义的任何 $SHELL (或您的共享身份验证服务器)。如果没有,上面的技巧可能不起作用。不过,我建议您研究另一个系统来管理您的服务器群。例如,鉴于您倾向于使用 SSH,Ansible 可能适合您。


编辑:好的,我现在了解一些附加要求。

如果您只想要失败的第一行,那么您可以将其删除:

pssh -h /tmp/hosts -i 'echo "$(uname), $(date)"' | grep -Eo '\[(SUCCESS|FAILURE)\].*$'

(-E用于扩展正则表达式支持,因此您可以让(SUCCESS|FAILURE).-o只返回匹配模式而不是整行。

如果您确实需要逗号,那么您还可以将其附加到sed

pssh -h /tmp/hosts -i 'echo "$(uname), $(date)"' | egrep -o '\[(SUCCESS|FAILURE)\].*$' | sed -r 's:(\[(SUCCESS|FAILURE)\]):\1,:'

(我在上面的示例中使用了该:字符,sed因为我认为它更具可读性,因此您可以看到它在做什么。但是,/如果您愿意,您可以将其替换为更典型的字符)

其作用是查找[SUCCESS][FAILURE]返回该字符串(通过\1反向引用)加上逗号。

例子:

$ echo -e "sdfsdfsdf[FAILURE] $(uname), $(date)\nsdfsdf\nasdfsdf" | grep -Eo '\[(SUCCESS|FAILURE)\].*$' | sed -r 's:(\[(SUCCESS|FAILURE)\]):\1,:'
[FAILURE], Linux, Fri 25 Jan 16:15:03 GMT 2019

如果出于任何原因您可以返回除然后之外的其他内容[SUCCESS][FAILURE]那么代码可以(具有讽刺意味的是)进一步缩短[A-Z]+

pssh -h /tmp/hosts -i 'echo "$(uname), $(date)"' | egrep -o '\[[A-Z]+\].*$' | sed -r 's:(\[[A-Z]+\]):\1,:'

(SUCCESS|FAILURE)但我建议您暂时坚持使用该版本,以防[A-Z]+返回一些误报。

相关内容