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
次の手順を実行します。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
。アプローチに従って検索すると、marc
両方が一致します。より慎重に一致させるには、行全体を一致させる代わりにパターンを使用することをお勧めします(まだこれを行っている場合は、上記で紹介したパターンを削除してください)。marco
marc
"^$userid:"
-F
grep
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:ユーザーが存在しません
スワティ:ユーザーが存在しません
学生:ユーザーが存在します。