예상 스크립트에서 특수 문자를 보내는 방법은 무엇입니까?

예상 스크립트에서 특수 문자를 보내는 방법은 무엇입니까?

특수문자(password)가 포함된 비밀번호를 보내려고 합니다 #?!k;|C. 비밀번호는 동적이며 스크립트에 하드코딩할 수 없으므로 아래와 같이 변수로 전달합니다.

$ expect ./passwordlessSSH.exp $hostname "$password"

스크립트의 코드는 다음과 같습니다

#!/usr/bin/expect -f
 set host [lindex $argv 0]
set pass [lindex $argv 1]

spawn ssh-copy-id -i /home/hdpsvcs/.ssh/id_rsa.pub hdpsvcs@$host
expect {
  "yes" {
    send "yes\r"
  }
    "assword" {
    send "$pass \r"
}
exit 0

그러나 여전히 스크립트가 올바르게 실행되지 않습니다. 오류가 표시되지 않지만 변수가 올바르게 전달되지 않습니다. 출력은 다음과 같습니다.

$ expect ./passwordlessSSH.exp $hostname "$password"

 spawn ssh-copy-id -i /home/hdpsvcs/.ssh/id_rsa.pub test@otesthost
/usr/bin/ssh-copy-id: INFO: Source of key(s) to be installed:
"/home/test/.ssh/id_rsa.pub"
/usr/bin/ssh-copy-id: INFO: attempting to log in with the new key(s), to filter out any that are already installed
/usr/bin/ssh-copy-id: INFO: 1 key(s) remain to be installed -- if you are     prompted now it is to install the new keys
\S
Kernel \r on an \m
test@test's password: 
$

답변1

많은 검색 끝에 expect특수 문자를 이스케이프 처리하지 않으면 사용할 수 없다는 사실을 발견했습니다.Expect 스크립트와 함께 사용하기 위해 특수 문자로 비밀번호를 변환하십시오.동적 비밀번호의 특수 문자를 프로그래밍 방식으로 처리할 수 있는 짧은 Perl 스크립트가 제공됩니다.

#/bin/sh
pstr='$x%y!zpass' # plain, un-escaped string
estr=$(perl -e 'print quotemeta shift(@ARGV)' "${pstr}")
echo ${estr}      # show escaped string

생산하다:

\$x\%y\!zpass

편집하다: 명령줄에서 예상 스크립트로 보낼 수 없으므로 이것을 답변으로 받아들이지 마십시오. 그러나 위의 방법을 사용하면 기대 스크립트를 호출하는 bash 스크립트에 인수를 보내서 저에게 효과적이었습니다. OP 코드에 적용한 방법은 다음과 같습니다.

쿵쿵 스크립트:비밀번호 없는 SSH.sh

#/bin/sh
hostname=$1
pstr=$2 # plain, un-escaped string
estr=$(perl -e 'print quotemeta shift(@ARGV)' "${pstr}")
echo ${estr}      # show escaped string
/your/script/location/passwordlessSSH.exp $hostname ${estr}

예상 스크립트:비밀번호 없는 SSH.exp

#!/usr/bin/expect -f
set host [lindex $argv 0]
set pass [lindex $argv 1]

spawn ssh-copy-id -i /home/hdpsvcs/.ssh/id_rsa.pub hdpsvcs@$host
expect {
  "yes" {
    send "yes\r"
   }
    "assword" {
    send "$pass \r"
}
exit 0

구현하다:bash 스크립트를 실행하십시오.

./passwordlessSSH.sh $hostname "$password"

답변2

perl응답자가 환경 변수로 처리될 수 있을 것으로 기대하므로 왜 사용을 제안했는지 잘 모르겠습니다 . 예:

export IN=file1
export OUT=file2
export PASS='!@#$%^&*('
expect -c '
    set timeout -1
    spawn openssl enc -d -aes-256-cbc -salt -in "$env(IN)" -out "$env(OUT)"
    match_max 100000
    expect "password:"
    send -- "$env(PASS)\r"
    expect "password:"
    send -- "$env(PASS)\r"
    expect eof
    puts "$expect_out(buffer)"' #> /dev/null 2>&1

답변3

printfbash를 사용하여 문자열을 이스케이프 문자로 변환 할 수 있습니다 . 예를 들면 다음과 같습니다.

#!/bin/bash
pstr=$1
escaped_pstr=$(printf '%q' "$pstr")
echo $escaped_pstr

이 스크립트는 이스케이프된 문자열을 인쇄합니다.

# sh test.sh '$x%y!zpass'
\$x%y\!zpass

이것은 내 코드입니다.

#!/bin/bash

pstr=$1
escaped_pstr=$(printf '%q' "$pstr")

cat > /usr/bin/sshpswd << eof
#!/usr/bin/expect
spawn ssh -o StrictHostKeyChecking=no sshuser@$DNS_MGNT_IP
expect {
    "*password*" {send "$escaped_pstr\r";}
}
interact
eof
 
chmod +x /usr/bin/sshpswd
sshpswd

관련 정보