SSHを介して実行されたリモートコマンドは正しい戻りコードを返しません。条件が失敗しても、戻りエラーコードは常に「0」です。

SSHを介して実行されたリモートコマンドは正しい戻りコードを返しません。条件が失敗しても、戻りエラーコードは常に「0」です。

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

サーバー側でリモートシャットダウンステータスコードを操作する方法は?

答え1

コードの主な問題は、$?呼び出し前の拡張です。sshこれは引用符によるものです。二重引用符で囲まれた文字列内のすべての拡張は、文字列が使用される前に拡張されます。これに加えて、使用中の二重引用符文字列にはssh別の二重引用符部分が含まれています。これらの部分は引用しないabc、の引用符で囲まれていない部分文字列と同じです"123"abc"456"


リモートホストで複雑なコマンドを実行するのではなく、コマンドをファイルに保存してから、ssh次の手順を実行します。catpasswdgrep

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。アプローチに従って検索すると、marc両方が一致します。より慎重に一致させるには、行全体を一致させる代わりにパターンを使用することをお勧めします(まだこれを行っている場合は、上記で紹介したパターンを削除してください)。marcomarc"^$userid:"-Fgrep

passwd次のコマンドを使用すると、ファイルの解析を完全に回避することもできます。

getent passwd "$userid" >/dev/null

ユーザーが存在する場合はゼロ終了コード(成功)を返し、そうでない場合はゼロ以外の値を返します。

つまり、

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

ただし、これによりsshユーザーごとにリモートホストを一度呼び出すことができます。各呼び出し間の接続を閉じないと、効率が向上する可能性があります(次は1分間接続を開いたままにします)。

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

答え2

$?結果コードをこのようにキャプチャしてみてはいかがでしょうか...

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

変数に割り当てることで[ $n -gt 0 ]テストできます。

答え3

提案された変更を適用した後に結果を得るための2つの方法が見つかりました。

最初の回避策:forループの使用

#!/bin/bash/expect
DATE=`date "+%d-%m-%Y_%H-%M-%S"`
for i in `cat /root/project_finduser/serverlist`;
do
        echo -e "\n*******************" 
        echo -e "$i" 
           for a in `cat /root/project_finduser/userslist`;
           do
             echo -e "\n" 
             echo -n "$a :" 
           if ssh "root@${i}" cat /etc/passwd | grep -w -q -F -e "$a";
           then
             echo "User exsits"
           else
             echo "User not exsits"
           fi 
done 
done >>"/tmp/userfind_${DATE}.txt"

2番目の解決策:Whileループの使用{whileループは最初の行以降にファイルからパラメータの読み込みを停止するため、sshコマンドを介して-nオプションを渡しました。}

    #!/bin/bash
    DATE=`date "+%d-%m-%Y_%H-%M-%S"`
    while IFS= read -r ipaddress;
    do
          echo -e "\n*******************"
          echo -e "$ipaddress"
               while IFS= read -r userid;
               do
                    echo -e "\n"
                    echo -n "$userid : "
               if ssh -n "root@${ipaddress}" getent passwd "$userid" >/dev/null;
               then
                    echo -n "User exsits"
               else
                    echo -n "User not exsits"
               fi 
done < /root/project_finduser/userslist
done < /root/project_finduser/serverlist  >"/tmp/userfind_${DATE}.txt"

出力:


192.168.56.103

sandeep: ユーザーの終了

学生:ユーザーが存在します。

ram:ユーザーが存在しません

sitea:ユーザーが存在しません

swati: ユーザー出口

学生:ユーザーが存在します。


192.168.56.104

sandeep: ユーザーが存在しません

学生:ユーザーが存在します。

ram:ユーザーが存在しません

sitea:ユーザーが存在しません

スワティ:ユーザーが存在しません

学生:ユーザーが存在します。

関連情報