如何从expect脚本中传递的shell'read'命令返回?

时间:2015-05-14 18:24:27

标签: linux shell ssh user-input expect

我真的很想使用expect,并且对于将命令传递给expect脚本有点困惑,所以请耐心等待...我已经搜索了很多论坛,但似乎无法找到一个使用的期望脚本的示例获取用户输入的read命令。

在我的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"

关于如何通过我的期望脚本传递read命令而不挂起的任何建议?

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

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

1 个答案:

答案 0 :(得分:1)

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

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

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

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

我的预期阻止现在看起来像这样:

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
    }
}

我还更新了脚本,根据用户输入的网络接口卡号自动确定子网掩码。引起我注意的是,在具有多个接口卡的盒子的情况下,找到网络接口卡号将非常难以自动化。最好从小开始,让用户输入它,并在整个脚本工作后稍微调整/自动化它。

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

相关问题