![更新](https://linux22.com/image/76058/%E6%9B%B4%E6%96%B0.png)
我有一个提供 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
但更容易从预期会话中提取数据。
我仍然认为有比使用expect
on更好的方法来获取虚拟机的 IP 地址virsh console
。
这是一种方法,可以从中提取 MAC 地址,然后在usingvirsh dumpxml
中查找匹配的 dnsmasq-dhcp 条目:/var/log/daemon.log
awk
# 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
,因此日志格式略有不同。此版本适用于dnsmasq
和dhcpd
:
$ 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”输出被发送到标准输出。这用于在脚本运行时向屏幕发送消息。它非常适合用户反馈、横幅和生成错误消息。