![使用 bash 腳本遠端執行多個命令](https://rvso.com/image/191769/%E4%BD%BF%E7%94%A8%20bash%20%E8%85%B3%E6%9C%AC%E9%81%A0%E7%AB%AF%E5%9F%B7%E8%A1%8C%E5%A4%9A%E5%80%8B%E5%91%BD%E4%BB%A4.png)
我必須透過 ssh 登入遠端伺服器並轉到 tmp 資料夾,然後必須執行 rm 命令。但是當我執行下面的腳本時,它會轉到遠端伺服器,但不會轉到臨時資料夾,也不執行 rm 命令。
#!/bin/bash
for i in `cat list`
echo $server
echo "------------------------------------------"
ssh $server << MYCOMMANDS
cd /tmp
rm log52.log
MYCOMMANDS
答案1
您的程式碼唯一真正的問題是您的循環缺少do
and done
,這會給您帶來語法錯誤,並且您正在使用它i
作為循環變量,但嘗試連接一些server
很可能未設定的變數。
除此之外,您正在使用cat
不含引號的命令替換,即一般來說如果您不確定您將讀取沒有空格和檔案名稱通配符的字串,那麼這是一個壞主意(儘管大多數主機的名稱在這方面表現良好)。
大多數時候,最好像這樣逐行讀取輸入:
while IFS= read -r remote; do
ssh -n "$remote" 'rm -f /tmp/log52.log'
done <list
我ssh -n
在這裡使用它來停止ssh
讀取其標準輸入流(它將連接到文件list
)。如果沒有-n
,ssh
將讀取 的剩餘內容list
,並且您的循環將僅運行一次迭代。
或者,如果您確實想從此處文件讀取命令:
while IFS= read -r remote; do
ssh -T "$remote" <<'END'
rm -f /tmp/log52.log
END
done <list
在這裡,我使用ssh -T
明確禁用偽終端分配,這是不需要的,因為我們不做任何需要使用者互動的事情。我這樣做是因為ssh
會注意到它的標準輸入流有數據,所以它會警告我們遠端系統上沒有可用的終端機來進行互動。我們不需要-n
這裡,因為我們正在從此處文件ssh
重新分配標準輸入流。ssh
但循環可以用單一命令代替
xargs -I {} ssh {} 'rm -f /tmp/log52.log' <list
...xargs
實用程式將在其中讀取線從檔案中list
,將命令替換{}
為ssh
從檔案讀取的行,並執行存取遠端系統以刪除特定檔案的操作。rm -f
如果沒有要刪除的文件,我通常不會導致錯誤。
的一些實作xargs
允許與eg 並行執行實用程式-P 4
(最多ssh
同時執行四個並發命令)。
答案2
#! /bin/bash
for i in `cat list`
do
echo $i
echo "-------------------------"
ssh $i "rm /tmp/log52.log"
done
如果您只需要刪除單個文件,您可能只想在一行中簡單地指定它。此外,您可能會發現添加-f
到rm
.
答案3
您不能像這樣簡單地重定向 ssh 會話的標準輸入。您應該會看到類似以下的錯誤訊息:
偽終端不會被分配,因為 stdin 不是終端
您需要使用 ssh 選項 -tt 來強制指派偽設備。嘗試這個:
#!/bin/bash
for i in `cat list`
echo $server
echo "------------------------------------------"
ssh -tt $server << MYCOMMANDS
cd /tmp
rm log52.log
MYCOMMANDS