如何 return from shell 'read' 命令传入 expect 脚本?

How to return from shell 'read' command passed in expect script?

我对使用 expect 很陌生,对于将命令传递给 expect 脚本有点困惑,所以请耐心等待...我搜索了很多论坛,但似乎找不到 expect 脚本的示例使用读取命令获取用户输入。

在我的 Korn shell 脚本中,我调用了一个 expect 脚本 (expectssh.exp) 以通过 ssh 登录到另一台主机并获取有关该主机网络配置的用户输入(网络接口卡号和子网掩码)信息)。我将四个参数传递给 expect 脚本:远程主机 ip 地址、用户名、密码和 运行 的命令列表。我的期望脚本如下:

#!/usr/bin/expect
# Usage: expectssh <host> <ssh user> <ssh password> <script>

set timeout 60
set prompt "(%|#|\$) $"
set commands [lindex $argv 3];

spawn ssh [lindex $argv 1]@[lindex $argv 0]

expect {
"*assword:" { 
send -- "[lindex $argv 2]\r" 
expect -re "$prompt"
send -- "$commands\r" 
}

"you sure you want to continue connecting" {
send -- "yes\r"
expect "*assword:"
send -- "[lindex $argv 2]\r"
expect -re "$prompt"
send -- "$commands\r" 
}

timeout {
exit }
}

脚本 运行 很好,除了当它到达 'read' 命令时,脚本不会继续或在用户按下 enter 后退出。它只是挂起。

我传递给expect脚本的命令及其调用如下:

SCRIPT='hostname > response.txt;netstat -rn;read net_card?"What is the network interface card number?   " >> response.txt; read net_mask?"What is the subnet mask? " >> response.txt'

/usr/bin/expect ./expectssh.exp $hostip $usr $pswd "$SCRIPT"

关于如何在不挂起的情况下通过我的 expect 脚本传递读取命令有什么建议吗?

附带说明,因为我知道它会出现 - 我不允许进行基于密钥的自动 SSH 登录。我必须提示输入用户名和密码,这是通过调用此 expect 脚本的 Korn shell 脚本完成的。

感谢您提供的任何建议和帮助!

对于任何感兴趣的人,我可以通过做一些事情让 read 命令为用户输入工作:

(1) 将其放在 -re $prompt 块中,而不是在密码输入后附加 send -- "$commands\r"

(2) 将命令硬编码到脚本中,而不是将它们传入。

(3) 在命令后加上 interact 语句,以便在用户响应之前不会输入下一个发送命令。

我的 expect 块现在看起来像这样:

expect {
    -re "(.*)assword:" { 
        send -s "$pswd\r" 
        exp_continue
    }
    "denied, please try again" {
        send_user "Invalid password or account.\n"
        exit 5
    }
    "incorrect" {
        send_user "Invalid password or account.\n"
        exit 5
    }
    "you sure you want to continue connecting" {
        send -s "yes\r"
        exp_continue
    }
    -re $prompt {
        set timeout -1
        send -- "hostname > partnerinit\r"
        expect -exact "hostname > partnerinit\r"
        send -s "netstat -rn\r"
        expect -re "$prompt"
        send -- "read n_card?'Enter the network interface card number for this server (i.e. eth0):  '\r"
        interact "\r" return
        send -- "\r"
        send -- "echo $n_card >> partnerinit\r"
        send -- "msk=$(cat /etc/sysconfig/network-scripts/ifcfg-$n_card | grep NETMASK)\r"
        send -- "msk=$(echo ${msk#NETMASK=})\r"
        send -- "echo $msk >> partnerinit\r"
        send -- "cat partnerinit\r"
        set retval 0
    }
    timeout {
        send_user "Connection to host $host timed out.\n"
        exit 10
    }
    eof {
        send_user "Connection to host $host failed.\n"
        exit 1
    }
}

我还更新了脚本以根据用户输入的网络接口卡号自动确定子网掩码。我注意到,在有多个接口卡的盒子中,很难自动找到网络接口卡号。最好从小处着手,让用户输入它,然后在整个脚本运行后 fine-tune/automate 输入它。

现在我正在努力修改它以将我的 partnerinit 文件 scp 回我的本地主机并从每个预期条件return有意义的退出状态。