我正在尝试发送包含 的特殊字符(密码)#?!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
您可以printf
在 bash 中使用将字符串转换为转义字符,例如:
#!/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