원격 시스템에서 스크립트를 실행하려면 예상을 사용하십시오.

원격 시스템에서 스크립트를 실행하려면 예상을 사용하십시오.

이 프로젝트를 완료하는 데 필요한 대부분의 정보를 자동화했지만 유일하게 뒤처지는 것은 원격 시스템에서 로컬 셸 스크립트를 실행하는 것입니다.

우리는 "expect" 라이브러리를 사용하는 스크립트가 어떤 Linux 명령도 인식하지 못한다는 것을 알고 있습니다.

여기에 제가 시도한 두 가지 사용 사례가 있습니다.

  1. Expect 스크립트를 사용하여 원격 서버에 필요한 명령 목록을 실행하면 스크립트를 실행하고 scp를 사용하여 출력을 로컬 시스템에 푸시합니다.

    chmod 777 localscript.sh
    cat > script1.sh <<- "ALL"
    #!/usr/bin/expect
    set password [lindex $argv 0];
    set ipaddress [lindex $argv 1];
    set timevalue [lindex $argv 2];
    set timeout $timevalue
    spawn /usr/bin/ssh username@$ipaddress /bin/bash < ./localscript.sh
    expect "assword:"
    send "$password\r"
    set timeout $timevalue
    spawn /usr/bin/scp username@$2:"/path/from/source/*" /path/to/destination/folder/
    expect "assword:"
    send "$password\r"
    interact
    ALL
    chmod 777 script1.sh
    ./script1.sh $password $2 $timevalue
    
  2. 별도의 Expect 스크립트로 원격 서버에서 필요한 명령 목록을 실행하고 scp를 사용하여 다른 스크립트의 파일을 가져옵니다.

    cat > script1.sh <<- "ALL"
    #!/usr/bin/expect
    set password [lindex $argv 0];
    set ipaddress [lindex $argv 1];
    set timevalue [lindex $argv 2];
    set timeout $timevalue
    spawn /usr/bin/ssh username@$ipaddress /bin/bash < ./localscript.sh
    expect "assword:"
    send "$password\r"
    interact
    ALL
    cat > script2.sh <<- "ALL2"
    #!/usr/bin/expect
    set password [lindex $argv 0];
    set ipaddress [lindex $argv 1];
    set timevalue [lindex $argv 2];
    set timeout $timevalue
    spawn /usr/bin/scp username@ipaddress:"/path/from/source/*" /path/to/destination/folder/
    expect "assword:"
    send "$password\r"
    interact
    ALL2
    chmod 777 localscript.sh script1.sh script2.sh
    ./script1.sh  $password $2 $timevalue
    sleep 5
    ./script2.sh  $password $2 $timevalue
    

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

나는 위의 코드가 그 자체로 모두 유효해야 한다고 생각합니다. 그러나 동일한 출력은 매우 예상치 못한 것 같습니다.

  1. 비밀번호를 입력하면 ssh 및 scp 명령이 거의 동시에 실행되므로 localscript에 작업을 완료하는 데 충분한 시간이 주어지지 않습니다. 다음은 내가 본 출력입니다.

    spawn /usr/bin/ssh [email protected] /bin/bash < ./localscript.sh
    Warning private system unauthorized users will be prosecuted.
    [email protected]'s password: spawn /usr/bin/scp [email protected]:"/home/some/file/*" /another/file/
    Warning private system unauthorized users will be prosecuted.
    [email protected]'s password:
    scp: /home/some/file/*: No such file or directory
    

참고: 이 기능은 "기대" 없이도 잘 작동합니다.

  1. 여기서는 ssh와 scp를 각각 실행하지만 localscript.sh 파일의 존재를 인식하지 못하는 것 같습니다.

    spawn /usr/bin/ssh [email protected] /bin/bash < ./localscript.sh
    Warning private system unauthorized users will be prosecuted.
    [email protected]'s password:
    bash: localscript.sh: No such file or directory
    Warning private system unauthorized users will be prosecuted.
    [email protected]'s password:
    scp: /home/some/file/*: No such file or directory
    

이 문제에 대한 피드백을 주시면 매우 감사하겠습니다. 첫 번째 접근 방식이 효과적인 솔루션일 수 있지만 스폰이 너무 빠르고 "sleep" 또는 "after" 명령이 작동하지 않습니다. 두 번째 방법도 통할 것 같은데, 리눅스에서 "expect"를 사용할 때 일반적으로 사용하는 방법과는 다르게 원격 서버에서 로컬 스크립트를 실행하는 방법이 있는 것 같습니다.

답변1

몇 가지 참고사항:

  • Expect shebang 줄이 잘못되었습니다. # #!/usr/bin/expect그냥 그래야 합니다.#!/usr/bin/expect
  • 원격 호스트에 ssh를 사용하지만 로컬 시스템을 통해 scp를 사용합니다. 이것이 당신의 의도입니까?
    • spawn그렇지 않은 경우 두 번째 항목으로 변경해야 합니다 send.
    • 나는 이것이 scp "파일을 찾을 수 없음" 오류의 원인이라고 생각합니다.
  • $2당신은 대신 사용$ipaddress
  • 생성된 프로세스와 실제로 상호 작용하지 않으려면 프로세스가 끝날 때까지 기다리십시오 expect eof.interact
  • 쉘 스크립트는 "script1.sh" 및 "script2.sh"를 생성하지만 "localscript.sh"는 생성하지 않습니다.
  • ".sh"는 예상 코드에 대한 설명 확장이 아닙니다. ".exp"가 더 좋습니다.
  • 모든 쉘 변수를 인용하십시오../script1.sh "$password" "$2" "$timevalue"

나는 이렇게 쓸 것입니다. 분명히 테스트되지 않은 것 같습니다.

#!/bin/bash
export password=$1
export ipaddress=$2
export timevalue=${3:--1}    # use default -1 if not specified\

[[ -z "$password" ]]  && { echo "Error: missing password";   exit 1; }
[[ -z "$ipaddress" ]] && { echo "Error: missing IP address"; exit 1; }

/usr/bin/expect -d <<END_EXPECT
    set timeout $env(timevalue)

    spawn sh -c "/usr/bin/ssh username@$env(ipaddress) /bin/bash < ./localscript.sh"
    expect "assword:"
    send "$env(password)\r"
    expect eof

    spawn /usr/bin/scp username@$env(ipaddress):"/path/from/source/*" /path/to/destination/folder/
    expect "assword:"
    send "$env(password)\r"
    expect eof
END_EXPECT

-d예상되는 디버그 출력을 켜는 옵션을 추가했습니다 . 더 이상 필요하지 않으면 제거하십시오.

문제는 generate 명령이 쉘 리디렉션을 수행하는 방법을 모른다는 것입니다. generate는 "ssh", "user@host", "/bin/bash", "<"(리터럴보다 작음) 및 " ./localhost.sh" . 여기서는 리디렉션이 올바르게 수행될 수 있도록 ssh 명령을 명시적으로 실행하기 위해 쉘을 사용하고 있습니다.

관련 정보