如何在 Shell 脚本中像嵌套 If Else 循环一样使用 expect?
How to use expect in Shell script like nested If Else loop?
我在下面编写了 Shell 脚本,旨在通过执行 SSH 并执行命令从远程主机获取模型名称。
#!/bin/bash
> output.csv
IFS=","
echo "IP,Model Name" >> output.csv
while read ip
do
#echo "Current IP is: $ip"
model=expect -c 'spawn ssh username@'"$ip"' "show version | in cisco"; expect -re "The.*(yes/no)?"; send "yes\r"; expect -re ".*UNAUTH.*password:"; send "password\r";' | grep cisco
echo "$ip,$model" >> output.csv
done < Check_SSH.csv
当我手动执行以下命令时,它会给出预期的模型名称作为输出。
命令:
expect -c 'spawn ssh username@'"$ip"' "show version | in cisco"; expect -re "The.*(yes/no)?"; send "yes\r"; expect -re ".*UNAUTH.*password:"; send "password\r";' | grep cisco
但是当它像上面那样放入脚本时它不会产生任何输出。
此外,大多数服务器上都配置了 MOTD(每日消息)和“主机的真实性...”将服务器添加到 [=14] 中的消息=], 所以我尝试在脚本中处理它们,但是当 MOTD 没有出现或者远程已经存在于 .ssh/known_hosts
.
中时,Expect 无法处理这种情况
非常感谢获得此脚本的任何帮助 运行。
预期输出:
IP,Model Name
8.8.8.8,C9407R
8.8.8.1,C9407R
8.8.8.2,C9407R
8.8.8.3,C9407R
首先,您缺少执行预期代码的 Command Substitution 语法:
model=$(expect -c ...)
# ....^^.............^
接下来,要可选地期望模式,您需要expect {patt1 action1 patt2 action2 ...}
形式:
expect -c '
spawn ssh username@'"$ip"' "show version | in cisco"
expect {
-re "The.*(yes/no)?" {send "yes\r"; exp_continue}
-re ".*UNAUTH.*password:" {send "password\r"; exp_continue}
eof
}
'
这样,expect 可以匹配任何 模式。 exp_continue
命令 "loops" 在同一 expect
命令中,因此您可以匹配多个命令。当 "show version ..." 命令完成后 ssh 连接关闭时,eof
模式匹配。
换行以提高可读性。
放在一起:
model=$(
expect -c '
spawn ssh username@'"$ip"' "show version | in cisco"
expect {
-re "The.*(yes/no)?" {send "yes\r"; exp_continue}
-re ".*UNAUTH.*password:" {send "password\r"; exp_continue}
eof
}
' | grep -i cisco
)
我感觉您在 grep
部分还需要做更多的事情,但是您没有显示 expect 命令的输出。
更新:
- 使用
spawn -noecho ssh ...
所以 expect 不会打印 spawn 命令。
- 然后,您将获得 ssh 需要为登录过程显示的任何输出,然后是 "show" 命令输出:
- 如果您只需要 1 行输出,您可能需要将
grep
更改为 tail -n 1
。
- 否则,请显示您获得的输出,我们可以帮助您过滤掉噪音。
更新 2:滤除噪音
我假设正则表达式模式 cisco (.*) processor
是您需要匹配的:
model=$(
expect -c '
log_user 0
spawn ssh username@'"$ip"' "show version | in cisco"
expect {
-re "The.*(yes/no)?" {send "yes\r"; exp_continue}
-re ".*UNAUTH.*password:" {send "password\r"; exp_continue}
-re "cisco (.*) processor" {puts $expect_out(1,string)}
}
expect eof
'
)
log_user 0
关闭派生进程写入标准输出的能力。 Expect 仍然可以捕获它的输出。
我在下面编写了 Shell 脚本,旨在通过执行 SSH 并执行命令从远程主机获取模型名称。
#!/bin/bash
> output.csv
IFS=","
echo "IP,Model Name" >> output.csv
while read ip
do
#echo "Current IP is: $ip"
model=expect -c 'spawn ssh username@'"$ip"' "show version | in cisco"; expect -re "The.*(yes/no)?"; send "yes\r"; expect -re ".*UNAUTH.*password:"; send "password\r";' | grep cisco
echo "$ip,$model" >> output.csv
done < Check_SSH.csv
当我手动执行以下命令时,它会给出预期的模型名称作为输出。
命令:
expect -c 'spawn ssh username@'"$ip"' "show version | in cisco"; expect -re "The.*(yes/no)?"; send "yes\r"; expect -re ".*UNAUTH.*password:"; send "password\r";' | grep cisco
但是当它像上面那样放入脚本时它不会产生任何输出。
此外,大多数服务器上都配置了 MOTD(每日消息)和“主机的真实性...”将服务器添加到 [=14] 中的消息=], 所以我尝试在脚本中处理它们,但是当 MOTD 没有出现或者远程已经存在于 .ssh/known_hosts
.
非常感谢获得此脚本的任何帮助 运行。
预期输出:
IP,Model Name
8.8.8.8,C9407R
8.8.8.1,C9407R
8.8.8.2,C9407R
8.8.8.3,C9407R
首先,您缺少执行预期代码的 Command Substitution 语法:
model=$(expect -c ...)
# ....^^.............^
接下来,要可选地期望模式,您需要expect {patt1 action1 patt2 action2 ...}
形式:
expect -c '
spawn ssh username@'"$ip"' "show version | in cisco"
expect {
-re "The.*(yes/no)?" {send "yes\r"; exp_continue}
-re ".*UNAUTH.*password:" {send "password\r"; exp_continue}
eof
}
'
这样,expect 可以匹配任何 模式。 exp_continue
命令 "loops" 在同一 expect
命令中,因此您可以匹配多个命令。当 "show version ..." 命令完成后 ssh 连接关闭时,eof
模式匹配。
换行以提高可读性。
放在一起:
model=$(
expect -c '
spawn ssh username@'"$ip"' "show version | in cisco"
expect {
-re "The.*(yes/no)?" {send "yes\r"; exp_continue}
-re ".*UNAUTH.*password:" {send "password\r"; exp_continue}
eof
}
' | grep -i cisco
)
我感觉您在 grep
部分还需要做更多的事情,但是您没有显示 expect 命令的输出。
更新:
- 使用
spawn -noecho ssh ...
所以 expect 不会打印 spawn 命令。 - 然后,您将获得 ssh 需要为登录过程显示的任何输出,然后是 "show" 命令输出:
- 如果您只需要 1 行输出,您可能需要将
grep
更改为tail -n 1
。 - 否则,请显示您获得的输出,我们可以帮助您过滤掉噪音。
- 如果您只需要 1 行输出,您可能需要将
更新 2:滤除噪音
我假设正则表达式模式 cisco (.*) processor
是您需要匹配的:
model=$(
expect -c '
log_user 0
spawn ssh username@'"$ip"' "show version | in cisco"
expect {
-re "The.*(yes/no)?" {send "yes\r"; exp_continue}
-re ".*UNAUTH.*password:" {send "password\r"; exp_continue}
-re "cisco (.*) processor" {puts $expect_out(1,string)}
}
expect eof
'
)
log_user 0
关闭派生进程写入标准输出的能力。 Expect 仍然可以捕获它的输出。