期望脚本错误
Error On Expect Script
发送新密码后,我一直收到此错误。它将更改密码,但不会执行脚本的其余部分。任何想法为什么它总是出错。我为不同的设备编写了一个非常相似的脚本并且它运行良好,但是该设备不需要更改密码后的东西。如果未完成其余操作,本设备将不会在重启后保存密码。通过 ssh 手动执行它工作得很好,所以它不是问题的 cmd,这是脚本的问题。
#!/usr/bin/expect
set timeout -1
#Edit for User
set user user
#Edit for Old Password
set old oldpassword
#Edit for New Password
set new newpassword
#get IP List from iplist.txt
set f [open "/iplist.txt"]
set data [read $f]
close $f
foreach line [split $data \n] {
if {$line eq {}} continue
spawn ssh $user@$line
expect "assword:"
send "$old\r"
sleep 10
send "passwd $user\r"
expect "assword:"
send "$new\r"
expect "assword:"
send "$new\r"
sleep 10
send "grep -v users.1.password= /tmp/system.cfg > /tmp/system.cfg.new\r"
sleep 10
send "echo users.1.password=`grep $user /etc/passwd | awk -F: '{print $2}'` >> /tmp/system.cfg.new\r"
sleep 10
send "cp /tmp/system.cfg.new /tmp/system.cfg\r"
sleep 10
send "save && reboot\r"
close
expect eof
}
如果设备不响应 ssh 或原始密码错误,完整的脚本会大很多,并带有故障保险。在我弄清楚这部分有什么问题之前,那个是行不通的。我只是将其精简以找出问题发生的位置。此行似乎也是问题所在,因为它确实在它之前的行上创建了 system.config.new:
send "echo users.1.password=`grep $user /etc/passwd | awk -F: '{print $2}'` >> /tmp/system.cfg.new\r"
它在 ssh 中是这样工作的:
send "echo users.1.password=`grep $user /etc/passwd | awk -F: '{print }'` >> /tmp/system.cfg.new\r"
但发送错误,因为 $2 可以按预期查看。有人告诉我,放置一个 \$2 会使它只对远程 shell 可见。任何帮助都会很棒。
最初它期望 "star" 而不是睡眠命令。我一直在这个脚本上尝试大量的东西,一旦我得到它 运行 就将它合并到我的完整脚本中。我使用睡眠的原因是因为 "star" 似乎与输出不匹配并且在第二次发送 $new/r 时失败。随着睡眠,它使它走得更远。不过我确实有一个更正。它实际上是为了发送 "save && reboot\r"。我最终将使用你在我的其他问题中提出的 $prompt 建议来代替 sleep 或 expect "star"。通过调试,这是它抛出错误的地方:
send: sending "save && reboot\r" to { exp4 }
expect: spawn id exp4 not open
while executing
"expect eof"
("foreach" body line 21)
invoked from within
"foreach line [split $data \n] {
if {$line eq {}} continue
spawn ssh $user@$line
expect "assword:"
send "$old\r"
sleep 3
send "passwd $user\r"
e..."
(file "./ubnt.sh" line 15)
"save && reboot\r" 会在保存设置后踢出 ssh 连接,但似乎没有那么远。 && 有问题吗,也许我需要 /&&.
交互而不是关闭并期待eof 是我将在完成后用完整脚本更新的答案。这是有效的 UBNT 密码更改脚本:
#!/usr/bin/expect
set timeout 30
#Edit for User
set user user
#Edit for Old Password
set old oldpassword
#Edit for New Password
set new newpassword
#get IP List from iplist.txt
set f [open "/iplist.txt"]
set data [read $f]
close $f
foreach line [split $data \n] {
if {$line eq {}} continue
spawn ssh $user@$line
expect {
"assword:" {
send "$old\r"
expect {
"assword:" {
close
continue
}}
expect {
"*" {
send "passwd $user\r"
expect "*assword:*"
send "$new\r"
expect "*assword:*"
send "$new\r"
expect "*"
send "grep -v users.1.password= /tmp/system.cfg > /tmp/system.cfg.new\r"
expect "*"
send "echo users.1.password=`grep $user /etc/passwd | awk -F: '{print $2}'` >> /tmp/system.cfg.new\r"
expect "*"
send "cp /tmp/system.cfg.new /tmp/system.cfg\r"
expect "*"
send "save && reboot\r"
interact
continue
}}}}
expect {
"*" {
close
continue
}}
expect eof
}
这是 Mikrotik 密码的脚本:
#!/usr/bin/expect
set timeout 30
#Edit for User
set user user
#Edit for Old Password
set old oldpassword
#Edit for New Password
set new newpassword
#get IP List from iplist.txt
set f [open "/iplist.txt"]
set data [read $f]
close $f
foreach line [split $data \n] {
if {$line eq {}} continue
spawn -noecho ssh -q -o "StrictHostKeyChecking=no" $user@$line
expect {
"assword:" {
send "$old\r"
expect {
"assword:" {
close
continue
}}
expect {
"*" {
send "user set $user password=$new\r"
expect ">"
send "quit\r"
close
continue
}}}}
expect {
"*" {
close
continue
}}
expect eof
}
Dinesh 提到我不应该在我的 expect 命令中使用 "star" 并说应该使用:
set prompt "#|%|>|\$ $"
并且:
expect -re $prompt
我可能会更改。如果无法通过 ssh 访问设备或者如果旧密码对设备不起作用,脚本也会移动到列表中的下一个 IP。我计划对两者进行的唯一其他更改是让它创建 3 个日志文件,列出成功的 ips、错误的密码 ips 和无法访问的 ips。这应该只是每次continue之前多一个命令而已,还没有研究如何输出变量到本地日志文件。
感谢您对此 Dinesh 的帮助。
发送新密码后,我一直收到此错误。它将更改密码,但不会执行脚本的其余部分。任何想法为什么它总是出错。我为不同的设备编写了一个非常相似的脚本并且它运行良好,但是该设备不需要更改密码后的东西。如果未完成其余操作,本设备将不会在重启后保存密码。通过 ssh 手动执行它工作得很好,所以它不是问题的 cmd,这是脚本的问题。
#!/usr/bin/expect
set timeout -1
#Edit for User
set user user
#Edit for Old Password
set old oldpassword
#Edit for New Password
set new newpassword
#get IP List from iplist.txt
set f [open "/iplist.txt"]
set data [read $f]
close $f
foreach line [split $data \n] {
if {$line eq {}} continue
spawn ssh $user@$line
expect "assword:"
send "$old\r"
sleep 10
send "passwd $user\r"
expect "assword:"
send "$new\r"
expect "assword:"
send "$new\r"
sleep 10
send "grep -v users.1.password= /tmp/system.cfg > /tmp/system.cfg.new\r"
sleep 10
send "echo users.1.password=`grep $user /etc/passwd | awk -F: '{print $2}'` >> /tmp/system.cfg.new\r"
sleep 10
send "cp /tmp/system.cfg.new /tmp/system.cfg\r"
sleep 10
send "save && reboot\r"
close
expect eof
}
如果设备不响应 ssh 或原始密码错误,完整的脚本会大很多,并带有故障保险。在我弄清楚这部分有什么问题之前,那个是行不通的。我只是将其精简以找出问题发生的位置。此行似乎也是问题所在,因为它确实在它之前的行上创建了 system.config.new:
send "echo users.1.password=`grep $user /etc/passwd | awk -F: '{print $2}'` >> /tmp/system.cfg.new\r"
它在 ssh 中是这样工作的:
send "echo users.1.password=`grep $user /etc/passwd | awk -F: '{print }'` >> /tmp/system.cfg.new\r"
但发送错误,因为 $2 可以按预期查看。有人告诉我,放置一个 \$2 会使它只对远程 shell 可见。任何帮助都会很棒。
最初它期望 "star" 而不是睡眠命令。我一直在这个脚本上尝试大量的东西,一旦我得到它 运行 就将它合并到我的完整脚本中。我使用睡眠的原因是因为 "star" 似乎与输出不匹配并且在第二次发送 $new/r 时失败。随着睡眠,它使它走得更远。不过我确实有一个更正。它实际上是为了发送 "save && reboot\r"。我最终将使用你在我的其他问题中提出的 $prompt 建议来代替 sleep 或 expect "star"。通过调试,这是它抛出错误的地方:
send: sending "save && reboot\r" to { exp4 }
expect: spawn id exp4 not open
while executing
"expect eof"
("foreach" body line 21)
invoked from within
"foreach line [split $data \n] {
if {$line eq {}} continue
spawn ssh $user@$line
expect "assword:"
send "$old\r"
sleep 3
send "passwd $user\r"
e..."
(file "./ubnt.sh" line 15)
"save && reboot\r" 会在保存设置后踢出 ssh 连接,但似乎没有那么远。 && 有问题吗,也许我需要 /&&.
交互而不是关闭并期待eof 是我将在完成后用完整脚本更新的答案。这是有效的 UBNT 密码更改脚本:
#!/usr/bin/expect
set timeout 30
#Edit for User
set user user
#Edit for Old Password
set old oldpassword
#Edit for New Password
set new newpassword
#get IP List from iplist.txt
set f [open "/iplist.txt"]
set data [read $f]
close $f
foreach line [split $data \n] {
if {$line eq {}} continue
spawn ssh $user@$line
expect {
"assword:" {
send "$old\r"
expect {
"assword:" {
close
continue
}}
expect {
"*" {
send "passwd $user\r"
expect "*assword:*"
send "$new\r"
expect "*assword:*"
send "$new\r"
expect "*"
send "grep -v users.1.password= /tmp/system.cfg > /tmp/system.cfg.new\r"
expect "*"
send "echo users.1.password=`grep $user /etc/passwd | awk -F: '{print $2}'` >> /tmp/system.cfg.new\r"
expect "*"
send "cp /tmp/system.cfg.new /tmp/system.cfg\r"
expect "*"
send "save && reboot\r"
interact
continue
}}}}
expect {
"*" {
close
continue
}}
expect eof
}
这是 Mikrotik 密码的脚本:
#!/usr/bin/expect
set timeout 30
#Edit for User
set user user
#Edit for Old Password
set old oldpassword
#Edit for New Password
set new newpassword
#get IP List from iplist.txt
set f [open "/iplist.txt"]
set data [read $f]
close $f
foreach line [split $data \n] {
if {$line eq {}} continue
spawn -noecho ssh -q -o "StrictHostKeyChecking=no" $user@$line
expect {
"assword:" {
send "$old\r"
expect {
"assword:" {
close
continue
}}
expect {
"*" {
send "user set $user password=$new\r"
expect ">"
send "quit\r"
close
continue
}}}}
expect {
"*" {
close
continue
}}
expect eof
}
Dinesh 提到我不应该在我的 expect 命令中使用 "star" 并说应该使用:
set prompt "#|%|>|\$ $"
并且:
expect -re $prompt
我可能会更改。如果无法通过 ssh 访问设备或者如果旧密码对设备不起作用,脚本也会移动到列表中的下一个 IP。我计划对两者进行的唯一其他更改是让它创建 3 个日志文件,列出成功的 ips、错误的密码 ips 和无法访问的 ips。这应该只是每次continue之前多一个命令而已,还没有研究如何输出变量到本地日志文件。
感谢您对此 Dinesh 的帮助。