![在远程服务器上执行本地脚本时捕获主机名和数据](https://linux22.com/image/190060/%E5%9C%A8%E8%BF%9C%E7%A8%8B%E6%9C%8D%E5%8A%A1%E5%99%A8%E4%B8%8A%E6%89%A7%E8%A1%8C%E6%9C%AC%E5%9C%B0%E8%84%9A%E6%9C%AC%E6%97%B6%E6%8D%95%E8%8E%B7%E4%B8%BB%E6%9C%BA%E5%90%8D%E5%92%8C%E6%95%B0%E6%8D%AE.png)
尝试在远程主机上执行本地脚本时,无法将远程服务器的主机名获取到本地输出文件。
例如我正在执行下面的脚本。
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