当前的任务是检查多个路由器的密码并更改它,以防任何密码仍设置为默认值,即(例如)登录名:ABC,密码:ABC。
我为此编写了一个期望脚本,但遇到了一些问题。
这是代码:
#!/usr/bin/expect -f
spawn telnet 10.15.160.69 #using a test IP, later it will read IP's from a list.
expect {
"Login: " {
send "ABC\r"
exp_continue
}
"Password: " {
send "ABC\r"
exp_continue
}
"> " {
send "passwd\r"
expect "Username: "
send "ABC\r"
expect "Password: "
send "ABC\r"
expect "New Password: "
send "n3wp@ss\r"
expect "Confirm New Password: "
send "n3wp@ss\r"
expect "> "
send "save\r"
}
}
现在,路由器有一个特殊的行为,即在 3 次密码尝试后不会注销,而是不断提示输入登录名和密码,直到提供正确的凭据或Ctrl+D
按下 (EOF)。
请看下面:
Trying 10.15.160.69...
Connected to 10.15.160.69.
Escape character is '^]'.
BCM96816 Broadband Router
Login:
Password:
Login incorrect. Try again.
Login:
Password:
Login incorrect. Try again.
Login:
Password:
Authorization failed after trying 3 times!!!.
Login: Password:
Login incorrect. Try again.
Login:
Password:
Login incorrect. Try again.
Login:
Password:
Authorization failed after trying 3 times!!!.
Login:
Password:
Login incorrect. Try again.
在脚本中发送 aneof
会导致其完全退出。
Expect 脚本是从 bash 脚本调用的:
#!/bin/bash
for host in $(cat ipnmap.txt);do
echo "${host}";
/usr/bin/expect passchange1.sh $host
done
我意识到可以使用 Expect 来实现相同的功能,但我更喜欢在 bash 中完成它。
所需要的是,一旦路由器第二次请求凭据,脚本就应该移动到下一个 IP,因为如果第一次不成功,则意味着路由器没有默认密码,这就是我们要执行的操作。如果需要,我们可以移至下一个 IP/路由器(仅当路由器具有默认用户名/密码时才需要更改密码)。
我将非常感谢为解决此问题提供的任何指导。谢谢
答案1
您可以简单地将登录的每个部分分散到单独的匹配项中,而不是将所有内容都放在单个expect
语句中,特别是当您知道将得到什么序列时,因此您不需要一次处理许多可能的回复。例如:
#!/usr/bin/expect
proc abort { } { send_user "Timeout!" ; exit 2 }
set address [lindex $argv 0]
spawn telnet $address
expect timeout abort "Login: "
set timeout 5
send "ABC\r"
expect timeout abort "Password: "
send "ABC\r"
expect timeout abort "Login incorrect" exit "> "
send "passwd\r"
expect timeout abort "Username: "
send "ABC\r"
expect timeout abort "Password: "
send "ABC\r"
expect timeout abort "New Password: "
send "n3wp@ss\r"
expect timeout abort "Confirm New Password: "
send "n3wp@ss\r"
expect timeout abort "> "
send "save\r"
expect timeout abort "> "
send "quit\r"
expect timeout abort eof
该脚本创建一个函数abort
,该函数将打印一条消息,并在调用时以返回码 2 退出。它将变量设置address
为传递给脚本的第一个参数。它启动 telnet 命令,然后执行expect
登录提示或超时(默认超时为 10 秒。我们稍后将其设置为 5 秒。)。timeout
是一个特殊的关键字而不是模式。 Expect 命令的格式为模式命令 模式命令...。最后的命令可以省略,意味着移至脚本中的下一行。这与多行等效:
expect {
timeout abort
"Login incorrect" exit
"> "
}
如果没有看到登录提示,超时将调用我们的 abort 并退出,并且在您的 bash 脚本中您可以测试此失败。
如果出现提示,我们将发送用户 ID,然后发送密码。如果我们收到“登录不正确”,我们将退出(退出代码 0),因为这意味着密码不是默认密码,否则我们将设法登录并看到提示>
并继续配置。最后可能会有一些有用的命令,例如quit
您可以发送以彻底关闭连接并expect eof
等待关闭。