2017-10-21 61 views
-1

我的輸入文件看起來像文件的下面bash腳本在遠程服務器上執行的命令打印輸出兩次

名稱:/ etc/hosts中

10.142.75.6 m1 

10.142.75.7 m2 

10.142.75.8 m3 

的下面腳本將查找主機名在/ etc/hosts中,並且應該打印命令「nproc」的輸出,但是它會打印輸出兩次,一次爲ip及其相應的主機名。

for hosts in $(cat /etc/hosts) ; 
do 
    ssh $hosts "uname -a" 
done 
+1

Bash用'10.142.75.6 m1 10.142.75.7 m2 10.142.75.8 m3'代替'$(cat/etc/hosts)'。 – Cyrus

+1

...但是你真的不應該在一般情況下使用'for $(cat ...)'。比方說,你有一個/ etc/hosts行,上面寫着'#* ALWAYS NOTIFY [email protected] *之前改變這個*' - 你當前的代碼將用一系列文件名替換這些'*'s,然後嘗試ssh這些文件。另請參閱[爲什麼不用'for for'讀取行](http://mywiki.wooledge.org/DontReadLinesWithFor) –

+0

順便說一句,通過使用'bash -x yourscript'運行它可能產生的記錄你的腳本正在做什麼目前的問題清楚。 –

回答

0

您可以使用cut僅讀取文件的第一列:

for hosts in $(cut -d' ' -f1 < /etc/hosts); 
do 
    echo "jps for $hosts" 
    ssh $hosts "uname -a" 
done 
+0

我不確定我是否看到這個被低估的原因 - 我顯然不認爲這是理想的,但是在任何方面它唯一的錯誤*是缺少'$ hosts'中的引號擴張。 –

+0

它也不會跳過hosts文件中的註釋,但這也相當小。 –

+0

我不認爲人們應該鼓勵不好的做法,因爲它可能適用於這個特定的文件。 – chepner

2

目前,你解析每一個字的文件作爲主機名 - 使您連接到每臺主機首先是其知識產權,然後是其名稱。


最好使用BashFAQ #1最佳實踐,通過一個文件讀取:

# read first two columns from FD 3 (see last line!) into variables "ip" and "name" 
while read -r ip name _ <&3; do 

# Skip blank lines, or ones that start with "#"s 
[[ -z $ip || $ip = "#"* ]] && continue 

# Log the hostname if we read one, or the IP otherwise 
echo "jps for ${name:-$ip}" 

# Regardless, connect using the IP; don't allow ssh to consume stdin 
ssh "$ip" "uname -a" </dev/null 

# with input to FD 3 from /etc/hosts 
done 3</etc/hosts 

在這裏,我們把第一列到shell變量ip,第二列(如果有的話)轉換爲name,並將所有後續列轉換爲變量_

相關問題