期待されるスクリプトから特殊文字を送信するには?

期待されるスクリプトから特殊文字を送信するには?

特殊文字を含むパスワードを送信しようとしています#?!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

関連情報