Expect 스크립트를 통해 원격 스크립트 매개변수를 보내는 방법

Expect 스크립트를 통해 원격 스크립트 매개변수를 보내는 방법

동적 쉘 스크립트를 생성하기 위해 heredoc "stop_remoteServer_script.sh"를 사용하는 프로그램이 있습니다.

아래 Heredoc 템플릿

cat<<_STOP > stop_remoteServer_script.sh
#!/bin/bash

serverName=\$1
function getServerpid {
        pid=\$( ps -ef|grep \${serverName}|grep -v grep |awk '{print \$2}' )
        echo \$pid
}

function kill_soaServer {
        echo "Killing \${serverName} ........"
        ps -ef|grep \${serverName} |grep -v grep|awk '{print \$2}'|xargs kill -9
        echo "status of killing server is $?"
}

check_soaServer=\$( getServerpid );

while [[ "X\${check_soaServer}" != "X" ]]
do
        cmd_status=\$( kill_soaServer  )
        sleep 30s
        check_soaServer=\$( getServerpid  )
done

kill_soaServer \${serverName}
_STOP

실행을 위해 원격 상자로 전송된 실제 스크립트

템플릿 출력

#!/bin/bash

serverName=$1
function getServerpid {
        pid=$( ps -ef|grep ${serverName}|grep -v grep |awk '{print $2}' )
        echo $pid
}

function kill_soaServer {
        echo "Killing ${serverName} ........"
        ps -ef|grep ${serverName} |grep -v grep|awk '{print $2}'|xargs kill -9
        echo "status of killing server is 0"
}

check_soaServer=$( getServerpid );

while [[ "X${check_soaServer}" != "X" ]]
do
        cmd_status=$( kill_soaServer  )
        sleep 30s
        check_soaServer=$( getServerpid  )
done

kill_soaServer ${serverName}

이제 서버 이름 매개변수를 사용하여 원격 상자에서 위에서 생성된 코드를 호출하는 예상보다 낮은 코드 블록이 있습니다.

sName=$1

CMD="ssh -o StrictHostKeyChecking=no  ${remoteUserName}\@${remoteHostName} "

# script with parameter
script="./stop_remoteServer_script.sh ${sName}"

/usr/bin/expect<<END
set force_conservative 0
spawn bash  -c "${CMD} /bin/bash < ${script} "
expect  "* password: "
send -- "${MYPWD}\r"
expect  "*$*"
expect eof

END

내가받는 오류는 다음과 같습니다

spawn bash -c ssh -o StrictHostKeyChecking=no  [email protected]  /bin/bash < ./stop_remoteServer_script.sh soa_server2
[email protected]'s password:
/bin/bash: soa_server2: No such file or directory

누구든지 매개변수를 보내는 방법을 도와줄 수 있습니까? 수동으로 작동합니다.

===================

제안된 추가 시도:

가상박스를 이용하여 간단한 네트워크를 만들고 아래에서 시도해보았습니다.

메인 프로그램

#!/bin/bash
# script with parameter
echo "running exp example"
sName="abc123ibc"
script="a.sh"
echo "thes script is $script \n"
/usr/bin/expect -d <<END
set force_conservative 0
set timeout -1
set prompt "*$*"
puts "before swapn"
spawn scp ./a.sh -o StrictHostKeyChecking=no ansibleadm\@192.168.1.102:/home/ansibleadm/
expect "id_rsa*"
send -- "ansibleadm\r"
expect  "*$*"
expect eof
puts "second spawn"
spawn ssh  -o StrictHostKeyChecking=no ansibleadm\@192.168.1.102  /bin/bash -c  ./a.sh $sName > log.txt
expect "id_rsa*"
send -- "ansibleadm\r"
expect ""
puts "after spawn"
expect eof
END

애쉬도 있어요

#!/bin/bash
  
sleep 12s
echo "inside swapned script"
touch ~/sample.txt
cat > ~/sample.txt<<EOF
hi suman $1
EOF

Sample.txt에서 내가 항상 얻는 것은 아래에 누락된 변수입니다.

[ansibleadm@AppServer ~]$ cat sample.txt 
hi suman 

원하는 디버거를 활성화했으며 아래는 디버그 로그입니다.

[ansibleadm@Centos-Control ~]$ ./exp.sh 
running exp example
thes script is a.sh \n
expect version 5.45.4
argv[0] = /usr/bin/expect  argv[1] = -d  
set argc 0
set argv0 "/usr/bin/expect"
set argv ""
executing commands from command file
before swapn
spawn scp ./a.sh -o StrictHostKeyChecking=no [email protected]:/home/ansibleadm/
parent: waiting for sync byte
parent: telling child to go ahead
parent: now unsynchronized from child
spawn: returns {33533}

expect: does "" (spawn_id exp6) match glob pattern "id_rsa*"? no
Enter passphrase for key '/home/ansibleadm/.ssh/id_rsa': 
expect: does "\rEnter passphrase for key '/home/ansibleadm/.ssh/id_rsa': " (spawn_id exp6) match glob pattern "id_rsa*"? yes
expect: set expect_out(0,string) "id_rsa': "
expect: set expect_out(spawn_id) "exp6"
expect: set expect_out(buffer) "\rEnter passphrase for key '/home/ansibleadm/.ssh/id_rsa': "
send: sending "ansibleadm\r" to { exp6 }

expect: does "" (spawn_id exp6) match glob pattern "*"? yes
expect: set expect_out(0,string) ""
expect: set expect_out(spawn_id) "exp6"
expect: set expect_out(buffer) ""

a.sh                                                                                        100%  114   165.9KB/s   00:00    
-o: No such file or directory
StrictHostKeyChecking=no: No such file or directory
expect: read eof
expect: set expect_out(spawn_id) "exp6"
expect: set expect_out(buffer) "\r\n\ra.sh                                                                                          
 ||| 0%    0     0.0KB/s   --:-- ETA\ra.sh                                                                                        
 ||| 100%  114   165.9KB/s   00:00    \r\n-o: No such file or directory\r\nStrictHostKeyChecking=no: No such file or directory\r\n"
second spawn
spawn ssh -o StrictHostKeyChecking=no [email protected] /bin/bash -c ./a.sh abc123ibc > log.txt
parent: waiting for sync byte
parent: telling child to go ahead
parent: now unsynchronized from child
spawn: returns {33541}

expect: does "" (spawn_id exp10) match glob pattern "id_rsa*"? no
Enter passphrase for key '/home/ansibleadm/.ssh/id_rsa': 
expect: does "\rEnter passphrase for key '/home/ansibleadm/.ssh/id_rsa': " (spawn_id exp10) match glob pattern "id_rsa*"? yes
expect: set expect_out(0,string) "id_rsa': "
expect: set expect_out(spawn_id) "exp10"
expect: set expect_out(buffer) "\rEnter passphrase for key '/home/ansibleadm/.ssh/id_rsa': "
send: sending "ansibleadm\r" to { exp10 }

expect: does "" (spawn_id exp10) match glob pattern ""? yes
expect: set expect_out(0,string) ""
expect: set expect_out(spawn_id) "exp10"
expect: set expect_out(buffer) ""
after spawn

expect: read eof
expect: set expect_out(spawn_id) "exp10"
expect: set expect_out(buffer) "\r\n"
[ansibleadm@Centos-Control ~]$ 

답변1

빌드가 너무 복잡해졌습니다.

CMD="ssh -o StrictHostKeyChecking=no  ${remoteUserName}\@${remoteHostName} "

# script with parameter
script="./stop_remoteServer_script.sh ${sName}"

/usr/bin/expect<<END
  set force_conservative 0
  spawn ${CMD} bash ${script}
  ...

스크립트에 실행 권한이 있으면 bash삭제할 수도 있습니다.


$script 변수에 공백이 포함되어 있기 때문에:

  1. 이것:/bin/bash < ${script}
  2. 다음과 같이 됩니다:/bin/bash < ./stop_remoteServer_script.sh soa_server2
  3. 배쉬는 다음과 같이 설명합니다./bin/bash soa_server2 < ./stop_remoteServer_script.sh
  4. "soa_server2: 해당 파일이 없습니다" 오류가 발생합니다.

답변2

bashstdin에서 명령을 읽어오도록 하려면 이 -s옵션과 호출에 전달할 인수가 필요합니다. 예를 들어:

$ echo 'date +$1' | bash -s %Y
2021

따라서 명령 뒤에 추가하십시오 -s./bin/bashspawn


-c명령 다음에 오는 매개변수 의 경우 $0먼저 설정해야 합니다. 예를 들면 다음과 같습니다 .

bash -c 'echo $(date +$1)' dummy %Y

관련 정보