在远程服务器上执行本地脚本时捕获主机名和数据

在远程服务器上执行本地脚本时捕获主机名和数据

尝试在远程主机上执行本地脚本时,无法将远程服务器的主机名获取到本地输出文件。

例如我正在执行下面的脚本。

ssh remotehost sh -s < sudo su - ; ./localscript --include Yes > output

上面工作正常。下面是一个示例输出

script executed data from the remote machine

但我需要像这样的主机名+数据。

remotehost: script executed data from the remote machine

因为我尝试使用 awk 但失败了,有人可以检查一下并提供帮助。

ssh remotehost sh -s < sudo su - ; ./localscript --include Yes | awk -vhostname=$(hostname) '{print hostname, $0}' > output

这给了我 localhost 主机名。如果我做错了,请纠正我。
也很抱歉,如果我没有正确解释这一点,请发表评论,我将修改和更正它。

我尝试了这个及其 wotking,但无法执行“grep”/“awk”输出

ssh remotehost sh -s < `./localscript --include Yes` 

ssh remotehost sh -s < `./localscript --include Yes | awk -vhostname=$(hostname) '{print hostname, $0}' > output`

答案1

如果您希望将输出保存到名为“output”的文件中当地的主持人:

scp -p ./localscript remotehost:
ssh -q remotehost <<'EOF' > output
./localscript --include Yes |
   awk -vhostname=$(hostname) '{print hostname, $0}'
EOF

ssh选项-q用于抑制警告消息“由于 stdin 不是终端,因此不会分配伪终端”。 - 这是必要的,因为标准输入是从heredoc重定向的。

这使用所谓的“Here Document”或“heredoc”来向ssh.这个词EOF只是一个任意词,本身没有特殊含义 - 但它通常与heredocs一起使用,因为它代表“文件结束”(EOT也经常用于“文本结束”)。可以使用您要重定向的文本中不单独成行的任何单词。

从该单词后面的下一行 (EOF) 到该单词的下一次出现(单独一行)的所有内容都被视为命令的输入ssh,并在远程主机上执行。

该单词周围的引号EOF使得整个定界文档有效地位于单引号字符串内。来自man bash(搜索“此处文档”):

这里的文件

这种类型的重定向指示 shell 从当前源读取输入,直到看到仅包含分隔符(没有尾随空格)的行。到该点读取的所有行都将用作命令的标准输入(或文件描述符 n,如果指定了 n)。

这里文档的格式是:

[n]<<[-]word
        here-document
delimiter

不对 word 执行任何参数和变量扩展、命令替换、算术扩展或路径名扩展。

如果引用了 word 的任何部分,则分隔符是对 word 删除引号的结果,并且此处文档中的行不会扩展。

如果 word 不加引号,则此处文档的所有行都会进行参数扩展、命令替换和算术扩展,字符序列 <newline 被忽略,并且必须使用 \ 来引用字符 、$ 和 `。

如果您希望将输出保存到名为 output 的文件中偏僻的主持人:

scp -p ./localscript remotehost:
ssh -q remotehost <<'EOF'
./localscript --include Yes |
   awk -vhostname=$(hostname) '{print hostname, $0}' > output
EOF

请注意> output两个版本中重定向的位置:<<'EOF'第一个版本紧接在 后,awk第二个版本紧接在 后。


不过,似乎您真正想做的是重新发明现有工具的一个非常基本的版本,例如并行分布式 Shell (pdsh)

我强烈建议您使用pdsh(或几个类似的程序之一)而不是重新发明它。它应该适用于大多数发行版(绝对适用于 debian、ubuntu 等)。

例如,在我的家庭网络上,我有四台机器(ganesh、indra、kali 和 hex - 我对最后一台机器的命名方案感到厌倦,并选择了 Discworld 而不是印度教神)。我已将 pdsh 配置为知道这些主机位于“all”组中,因此我可以运行以下命令:

$ pdsh -g all 'uptime; uname -a'
hex:  18:35:00 up 45 days, 21:07,  1 user,  load average: 0.33, 0.41, 0.43
hex: Linux hex 5.10.0-4-amd64 #1 SMP Debian 5.10.19-1 (2021-03-02) x86_64 GNU/Linux
kali:  18:35:00 up 20:40,  2 users,  load average: 1.46, 0.92, 0.68
kali: Linux kali 5.10.0-6-amd64 #1 SMP Debian 5.10.28-1 (2021-04-09) x86_64 GNU/Linux
ganesh:  18:35:00 up 45 days, 21:23, 22 users,  load average: 1.34, 1.67, 1.85
ganesh: Linux ganesh 5.10.0-4-amd64 #1 SMP Debian 5.10.19-1 (2021-03-02) x86_64 GNU/Linux
indra:  18:35:00 up 5 days, 19:51,  2 users,  load average: 0.00, 0.03, 0.02
indra: Linux indra 5.10.0-6-amd64 #1 SMP Debian 5.10.28-1 (2021-04-09) x86_64 GNU/Linux

请注意,它已经执行了您尝试使用该awk命令执行的操作 - 在输出中添加远程计算机的主机名前缀。

另请注意:不能保证输出的顺序能够像这样很好地分组。 pdsh并行运行多个 ssh 连接,远程计算机将花自己的时间做出响应。当然,您可以将输出通过管道传输到sort -k1,1.

pdsh包括一个用于pdcp将文件复制到远程主机的实用程序。例如,如果我想复制./localscript到我的所有机器并在它们上运行它,我会运行:

pdcp -p -g all ./localscript '~/'
pdsh -g all ./localscript

顺便说一句,pdsh还附带了一个很好的实用程序,称为dshbak它可以重新格式化输出,并按其来自的主机对其进行分组。

$ pdsh -g all 'uptime; uname -a' | dshbak 
----------------
kali
----------------
 18:35:12 up 20:41,  2 users,  load average: 1.51, 0.96, 0.70
Linux kali 5.10.0-6-amd64 #1 SMP Debian 5.10.28-1 (2021-04-09) x86_64 GNU/Linux
----------------
indra
----------------
 18:35:12 up 5 days, 19:51,  2 users,  load average: 0.00, 0.03, 0.02
Linux indra 5.10.0-6-amd64 #1 SMP Debian 5.10.28-1 (2021-04-09) x86_64 GNU/Linux
----------------
ganesh
----------------
 18:35:12 up 45 days, 21:23, 22 users,  load average: 1.52, 1.70, 1.86
Linux ganesh 5.10.0-4-amd64 #1 SMP Debian 5.10.19-1 (2021-03-02) x86_64 GNU/Linux
----------------
hex
----------------
 18:35:12 up 45 days, 21:07,  1 user,  load average: 0.26, 0.39, 0.42
Linux hex 5.10.0-4-amd64 #1 SMP Debian 5.10.19-1 (2021-03-02) x86_64 GNU/Linux

相关内容