在expect脚本中使用嵌套的spawn方法

时间:2016-09-19 13:14:52

标签: ssh nested expect spawning

我写了以下期望脚本:

/usr/bin/expect<<EOF
set SERVER_HOSTNAME "$env(SERVER_HOSTNAME)"

set USERNAME "$env(USERNAME)"
set PASSWORD "$env(PASSWORD)"

set timeout -1

spawn ssh "$USERNAME@$SERVER_HOSTNAME"
expect  {
        "Host key verification failed." { spawn ssh-keygen -R "$SERVER_HOSTNAME"; expect "known_hosts.old"; send_user "Updated host key details."; exp_continue}
        "continue connecting (yes/no)" { send "yes\r"; expect "Permanently added"; exp_continue}
        "assword:" { send_user "Keygen details are correctly mapped for this server\n"}
        }
EOF

这里我希望如果在产生“ssh”进程时无法验证服务器的主机密钥,那么嵌套的spawn进程“ssh-keygen -R”应该删除旧密钥。然后“ssh”进程应该尝试再次连接,以便可以添加对应于该服务器的新密钥。

但是在执行:

之后
send_user "Updated host key details."

方法,期望进程从此脚本退出。

我知道替代方案可以将此期望值分为两个步骤,如下所示:

 /usr/bin/expect<<EOF
set SERVER_HOSTNAME "$env(SERVER_HOSTNAME)"

set USERNAME "$env(USERNAME)"
set PASSWORD "$env(PASSWORD)"

set timeout -1

spawn ssh "$USERNAME@$SERVER_HOSTNAME"
expect  {
        "Host key verification failed." { spawn ssh-keygen -R "$SERVER_HOSTNAME"; expect "known_hosts.old"; send_user "Updated host key details."; exp_continue}            
        "continue connecting (yes/no)" { send "yes\r"; expect "Permanently added"; exp_continue}
       "assword:" { send_user "Keygen details are correctly mapped for this server\n"}
        }


spawn ssh "$USERNAME@$SERVER_HOSTNAME"
expect  {           
        "continue connecting (yes/no)" { send "yes\r"; expect "Permanently added"; exp_continue}
        "assword:" { send_user "Keygen details are correctly mapped for this server\n"}
        }

EOF    

但我们是否有办法一次性执行此期望呼叫。简而言之,我想知道,我们可以进行生成过程的嵌套吗?

1 个答案:

答案 0 :(得分:1)

空白在可维护代码方面走得很远:你不需要每行压缩这么多命令。

spawn ssh "$USERNAME@$SERVER_HOSTNAME"
expect {
    "Host key verification failed." {
        spawn ssh-keygen -R "$SERVER_HOSTNAME"
        expect "known_hosts.old"
        send_user "Updated host key details."
        exp_continue
    }
    "continue connecting (yes/no)" {
        send "yes\r"
        expect "Permanently added"
        exp_continue
    }
    "assword:" { 
        send_user "Keygen details are correctly mapped for this server\n"
    }
}

在这种情况下,您不需要与ssh-keygen进行互动,因此请使用exec来简单地调用它

    "Host key verification failed." {
        exec ssh-keygen -R "$SERVER_HOSTNAME"
        puts "Updated host key details."
        exp_continue
    }

如果你需要生成某些内容并与之交互,你需要知道有一个由spawn创建的隐式变量spawn_id,并由expect和send使用。在生成任何其他进程之前,您需要保存当前进程的spawn_id。例如:

spawn process1
set ids(1) $spawn_id
expect -i $ids(1) "some pattern"
send -i $ids(1) "some string\r"

spawn process2
set ids(2) $spawn_id
expect -i $ids(2) "some pattern from process2"
send -i $ids(2) "some string to process2\r"