1. 程式人生 > >Linux shell指令碼使用while迴圈執行ssh的注意事項

Linux shell指令碼使用while迴圈執行ssh的注意事項

如果要使用ssh批量登入到其它系統上操作時,我們會採用迴圈的方式去處理,那麼這裡存在一個巨大坑,你必須要小心了。

一、場景還原:

我現在是想用一個指令碼獲取一定列表伺服器的執行時間,首先我建立一個名字為ip.txt的IP列表(一個IP一行),再建好金鑰實現不用密碼直接登入。然後寫指令碼如下:

[code language=”shell”]#!/bin/bash
while read ips;
do
echo $ips;
done < ip.txt[/code]

指令碼實現了逐行讀取列表中的IP,但是:

[code language=”shell”]#!/bin/bash
while read ips;
do
echo $ips;
upt=`ssh

[email protected]$ips "uptime"`;
echo $upt;
done < ip.txt[/code]

指令碼只對第一個IP做了檢測,就直接跳出來了。

二、問題分析:

while使用重定向機制,ip.txt檔案中的資訊都已經讀入並重定向給了整個while語句,所以當我們在while迴圈中再一次呼叫read語句,就會讀取到下一條記錄。問題就出在這裡,ssh語句正好回讀取輸入中的所有東西。為了禁止ssh讀所有東西增加一個< /dev/null,將ssh 的輸入重定向輸入。

三、解決策略:

1、使用for迴圈代表while,因為for沒有一次把檔案內容快取獲取過來,程式碼段修改如下:

[code language=”shell”]for ips in `cat ip.txt`; do
echo ${ips};
upt=`ssh [email protected]${ips} uptime`;
echo $upt;
done[/code]

2、若堅持使用while迴圈,那麼需要對ssh增加-n引數,為什麼增加了-n引數也可以解決問題呢?通過man ssh檢視-n引數的說明:
Redirects stdin from /dev/null (actually, prevents reading from stdin)
這就和

修改後的程式碼如下:

[code language=”shell”]#!/bin/bash
while read ips;
do
echo $ips;
upt=`ssh -n [email protected]$ips "uptime"`;
echo $upt;
done < ip.txt[/code]