Shell

通過 ssh 執行的遠端命令不會返回正確的返回碼。返回錯誤程式碼始終為“0”,即使條件失敗

  • April 28, 2019

在 Linux 機器上執行遠端腳本期間,我沒有得到正確的退出返回碼。該腳本用於檢查使用者是否存在。

我的腳本如下:-

#!/bin/bash
DATE=`date "+%d-%m-%Y_%H:%M:%S"`
for i in `cat /home/sandeep/server_ip_list/serverlist_New`
do 
    ipaddress=${i}
    echo -e "\n***************" >> /tmp/userfind_${DATE}.txt
    echo -e "$ipaddress" >> /tmp/userfind_${DATE}.txt
    for b in `cat /home/sandeep/Project_finduser01/userslist`
    do     
        userid=${b}
        echo -e "\n" >> /tmp/userfind_${DATE}.txt
        echo -n "$userid" >> /tmp/userfind_${DATE}.txt
        ssh -t sandeep@${ipaddress} "grep $userid /etc/passwd > /dev/null;
        if [ "$?" = "0" ];  
        then
            echo -n " : User exsits"
        else
            echo -n " : User not exsits"
        fi" >> /tmp/userfind_${DATE}.txt 
done 
done

無論使用者是否存在,我總是得到以下輸出:

***************
10.25.59.12


sandeepj: User exsits

pravin: User exsits

ram: User exsits

sita: User exsits

raj.singh: User exsits

如何在伺服器端操作遠端退出狀態碼?

您的程式碼中的主要問題$?是在呼叫之前進行了擴展ssh。這是由於引用。雙引號字元串中的所有擴展都在使用該字元串之前進行擴展。除此之外,您使用的雙引號字元串ssh包含其他雙引號部分。這些部分將不加引號,就像子字元串abc不加引號一樣"123"abc"456"


與其嘗試在遠端主機上執行複雜的命令,不如讓ssh命令文件,然後:cat``passwd``grep

if ssh -n "sandeep@$ipaddress" cat /etc/passwd | grep -q -F -e "$userid"
then
   echo "User exists"
else
   echo "User does not exist"
fi >>"/tmp/userfind_$DATE.txt"

此外,請考慮使用 while 循環從使用者和伺服器列表中讀取:

while IFS= read -r userid; do
  # ...
done </home/sandeep/Project_finduser01/userslist

您還可以將最外層循環重定向到您的輸出文件,而不是重定向每一個echo

while ...; do
   while ...; do
      # stuff
   done <userlist
done <serverlist  >"/tmp/userfind_$DATE.txt"

如果您的使用者列表很長,您可能只想passwd從遠端主機獲取一次,然後多次查詢

while ...; do
   scp "sandeep@$ipaddress:/etc/passwd" passwd.tmp
   while ...; do
      if grep -q -F -e "$userid" passwd.tmp; then
         # exists
      fi
   done <userlist
done <serverlist  >"/tmp/userfind_$DATE.txt"

更有效的方法是將使用者列表讀入一個awk數組,然後將passwd文件中的使用者名與它們進行匹配。那將完全擺脫最裡面的循環。

使用者名位於文件的特定欄位中passwd。使用您的方法,您將匹配兩者marcmarco如果您搜尋marc. 為了更仔細地匹配,請考慮使用模式,例如"^$userid:"而不是匹配整行(-F如果您仍在使用,請刪除我在上面介紹的內容grep)。

您也可以passwd完全避免解析文件

getent passwd "$userid" >/dev/null

如果使用者存在,則返回零退出程式碼(成功),否則返回非零。

IE,

if ssh -n "sandeep@$ipaddress" getent passwd "$userid" >/dev/null
then
   # exists
else
   # does not exist
fi

不過,這將對ssh每個使用者的遠端主機進行一次呼叫。通過不關閉每個呼叫之間的連接可以提高效率(下面將保持連接打開一分鐘):

if ssh -n -o ControlMaster=auto -o ControlPersist=1m "sandeep@$ipaddress" getent passwd "$userid" >/dev/null
then
   # exists
else
   # does not exist
fi

為什麼不像這樣擷取結果程式碼$?……

ssh user@host 'cmd arg;echo $?'

如果將其分配給變數,則可以[ $n -gt 0 ]對它進行測試。

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