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
사용자가 존재하면 0 종료 코드(성공)를 반환하고, 그렇지 않으면 0이 아닌 값을 반환합니다.
즉,
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
제안된 변경 사항을 적용한 후 결과를 얻을 수 있는 두 가지 방법을 찾았습니다.
첫 번째 해결 방법: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"
두 번째 해결 방법: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: 사용자가 존재하지 않습니다
스와티: 사용자가 존재하지 않습니다
학생: 사용자가 존재합니다.