이 프로젝트를 완료하는 데 필요한 대부분의 정보를 자동화했지만 유일하게 뒤처지는 것은 원격 시스템에서 로컬 셸 스크립트를 실행하는 것입니다.
우리는 "expect" 라이브러리를 사용하는 스크립트가 어떤 Linux 명령도 인식하지 못한다는 것을 알고 있습니다.
여기에 제가 시도한 두 가지 사용 사례가 있습니다.
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
별도의 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
=========================
나는 위의 코드가 그 자체로 모두 유효해야 한다고 생각합니다. 그러나 동일한 출력은 매우 예상치 못한 것 같습니다.
비밀번호를 입력하면 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
참고: 이 기능은 "기대" 없이도 잘 작동합니다.
여기서는 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 명령을 명시적으로 실행하기 위해 쉘을 사용하고 있습니다.