Bash

在遠端伺服器上執行本地腳本時擷取主機名和數據

  • April 20, 2021

嘗試在遠端主機上執行本地腳本時,無法將遠端伺服器的主機名獲取到本地輸出文件。

例如,我正在執行下面的腳本。

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 主機名。如果我做錯了,請糾正我。

也很抱歉,如果我沒有正確解釋這一點,請發表評論,我會修改並更正它。

我試過這個和它的工作,但無法做“grep”/“awk”輸出

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

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

如果要將輸出保存到本地主機上名為“輸出”的文件中:

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

ssh 選項用於抑制警告消息“-q不會分配偽終端,因為標準輸入不是終端”。- 這是必要的,因為標準輸入是從heredoc 重定向的。

這使用所謂的“Here Document”或“heredoc”來提供輸入ssh。這個詞EOF只是一個任意詞,本身沒有特殊含義 - 但它通常與 heredocs 一起使用,因為它代表“文件結束”(EOT也經常用於“文本結束”)。可以使用在要重定向的文本中本身不在一行的任何單詞。

從該單詞 (EOF) 之後的下一行到它的下一次出現(單獨一行),所有內容都被視為ssh命令的輸入,並在遠端主機上執行。

單詞周圍的引號EOF使整個heredoc有效地位於單引號字元串中。來自man bash(搜尋“此處文件”):

這裡的文件

這種類型的重定向指示 shell 從目前源讀取輸入,直到看到僅包含分隔符(沒有尾隨空格)的行。然後,所有讀取到該點的行都用作命令的標準輸入(或文件描述符 n,如果指定了 n)。

這里文件的格式是:

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

不會對 word 執行參數和變數擴展、命令替換、算術擴展或路徑名擴展。

如果 word 的任何部分被引用,則分隔符是 word 上引號刪除的結果,並且 here-document 中的行不展開。

如果 word 不被引用,則 here-document 的所有行都經過參數擴展、命令替換和算術擴展,字元序列 <newline 被忽略,並且必須使用 \ 來引用字元、$ 和 `。

如果要將輸出保存到遠端主機上名為 output 的文件中:

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

注意&gt; output重定向在兩個版本中的位置:緊跟在&lt;&lt;'EOF'第一個版本之後awk,在第二個版本之後。


不過,您似乎真正想做的是重新發明現有工具的一個非常基本的版本,例如Parallel Distributed 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

引用自:https://unix.stackexchange.com/questions/645896