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

사용자가 존재하면 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: 사용자가 존재하지 않습니다

스와티: 사용자가 존재하지 않습니다

학생: 사용자가 존재합니다.

관련 정보