更新

更新

我有一个提供 IP 地址的期望脚本:

#!/bin/expect -f
set nodename [lindex $argv 0]
spawn virsh console $nodename
expect "Escape character is"
send "\n"
expect "localhost login: " {
    send "root\n"
    expect "Password: "
    send "cloud123\n"
}
expect "~]#" {
        send "\n"
        send "ifconfig | grep 192.168.1. | awk \'{print \$2}\'"
        send "\n"
        expect '(\d+\.\d+\.\d+\.\d+)'
        send "logout"
}

我希望脚本返回此 IP 地址。我从 shell 脚本中调用这个 Expect 脚本,如下所示

#!/bin/bash
ip=$(expect GetIP.exp nodetwo)
echo $ip

如何让我的 Expect 脚本将输出返回到 shell 脚本?

答案1

好的,打开和关闭日志记录不起作用 - 可能是计时问题。

当像这样调用时,下面的期望脚本对我有用

# ip=$(./virsh-expect nodetwo | tr -d '\r' | grep '^192.168')
# echo $ip 
192.168.122.99

tr这里需要注意的重要一点是,在 shell 脚本中使用 grep 查找 IP 时会从输出中删除回车符。 Expect 脚本甚至不会尝试“期望”它,它只是期望下一个 root shell 提示符并退出。

我还使期望脚本更加通用 - 它只期望“登录:”而不是“本地主机登录:”(这在任何实际具有主机名的虚拟机上都会失败......而且大多数都会失败),以及一个简单的“#”用于 root shell 提示符。

#!/usr/bin/expect -f
set nodename [lindex $argv 0]
spawn virsh console $nodename
expect "Escape character is"
send "\n\n"
expect "login: " {
    send "root\n"
    expect "Password: "
    send "cloud123\n"
}   
expect "# " {
        send "ifconfig | awk \'/192\.168/ {print \$2}\'"
        send "\n"
        expect "# "
        send "exit"
}

expect另一种选择是根本不使用,而是使用 perlExpect.pm或 pythonpexpect代替。它们的工作方式与预期会话几乎相同,expect但更容易从预期会话中提取数据。


我仍然认为有比使用expecton更好的方法来获取虚拟机的 IP 地址virsh console

这是一种方法,可以从中提取 MAC 地址,然后在usingvirsh dumpxml中查找匹配的 dnsmasq-dhcp 条目:/var/log/daemon.logawk

# mac=$(virsh dumpxml nodetwo | sed -n -e "/mac address/ s/.*'\([^']*\)'.*/\1/ p" | tail -1)
# ip=$(awk "/dnsmasq.*DHCPACK.*$mac/ {print \$7}" /var/log/daemon.log  | tail -1)
# echo $ip
192.168.122.99

在我的系统上,虚拟机有两个网络接口,我只对最后一个网络接口感兴趣,所以我tail -1在线使用virsh dumpxml。上tail -1线awk是为了确保我们只得到最新的该 MAC 地址的 dhcp 分配。

(实际上,我在系统上测试的虚拟机称为“sid”,而不是“nodetwo”,但我编辑了输出以及期望脚本中的密码,以满足您的问题。还有我正在使用的IP地址对于我的虚拟机来说,是 192.168.122.x 而不是 192.168.1.x - 但这在细节上是微不足道的差异)


更新

昨晚我不得不自己使用这个来查找我创建的 freebsd 虚拟机的 IP。我使用 ISCdhcpd而不是dnsmasq,因此日志格式略有不同。此版本适用于dnsmasqdhcpd

$ cat find-vm-ip-by-name.sh
#!/bin/bash

mac=$(virsh dumpxml "$1" | sed -n -e "/mac address/ s/.*'\([^']*\)'.*/\1/ p" | tail -1)
ip=$(awk "/dnsmasq.*DHCPACK.*$mac/ {print \$7} ; /dhcpd.*DHCPACK.*$mac/ {print \$8}" /var/log/daemon.log  | tail -1)
echo $ip

答案2

您可以尝试以下方法:

send_user $ip

“send_user”输出被发送到标准输出。这用于在脚本运行时向屏幕发送消息。它非常适合用户反馈、横幅和生成错误消息。

相关内容