Tcl expect脚本中的while循环问题
我编写了一个expect脚本,其工作原理如下:Tcl expect脚本中的while循环问题,tcl,Tcl,我编写了一个expect脚本,其工作原理如下: ssh到服务器1 从server1 ssh到另一台服务器server2 从server2到server3,然后sudo进入用户并运行命令 在脚本中,我从名为hostnames.out和commands.out的两个文件中读取要执行的主机名和命令。我使用while循环遍历hostnames.out中的每个条目,并从commands.out文件中运行命令 我在hostnames.out中使用一个条目测试了我的脚本,它可以正常工作,但是当我添加多行时,它
据我所知,主要问题是不同主机上的子进程链很复杂,没有得到正确清理。不一致的缩进使代码更难阅读,这使问题更加复杂 关键是,您希望server1和server2上的ssh会话只通过ssh连接到链中的下一个服务器,server3上的ssh会话只执行sudo。最简单的修复方法是使用
exec-ssh
而不是ssh
和exec-sudo
而不是sudo
。然后,在最内层执行exit
将导致所有这些中间程序也终止,并且将触发expect eof
spawn -noecho ssh $ssh1_usr@$ssh1
expect {
"*route*" { puts "login failed"; exit 1 }
"timed out" { puts "login failed timed out"; exit 1 }
"*password:" { send "$ssh1_pwd\r"; exp_continue }
-re $prompt { send "whoami\r" }
}
expect -re $prompt {
send "exec ssh $ods_usr@$ods\r"
}
expect {
"password:" { send "$ods_pwd\r"; exp_continue }
-re $prompt { send "whoami\r" }
}
expect -re $prompt {
send "exec ssh $serv1_usr@$serv1\r"
}
expect {
"password:" { send "$serv1_pwd\r"; exp_continue }
-re $prompt { send "whoami\r" }
}
# You seem to be missing the sudo here?
foreach a [split $file_data "\n"] {
expect -re $prompt
send "$a"
}
expect -re $prompt
send "exit\r"
expect eof
close; ### TERMINATE THE SPAWN. IMPORTANT!
您还遇到了一个问题,即您在使用[list$file\u data]
时,本应使用[split$file\u data”\n]
将其按行拆分
对于每一组凭证,都需要循环上面的代码。这一部分最容易写成这样的内容(考虑到您确实没有足够的数据行需要流处理):
我单独建议在所有中间服务器上设置SSH公钥,并使用
-A
选项进行SSH。这可以在不影响安全性的情况下大大简化身份验证/授权部分。您是否收到任何错误消息?不,我在hostnames.out文件中添加第二行时没有收到任何错误消息。另外请注意,您可以将要执行的命令传递给ssh,如sshuser1@serv1sshuser2@serv2sudo yourcommand
。现在你只需要处理密码的事情。
server1 user password server2 user password server3 user password
#!/usr/bin/expect
#####################################################
# script to automate manual works - remote 2 #
# Gopinath #
#####################################################
#Variable declaration:
#Setting variable "prompt" for multiple prompts:
set prompt {[]$#%]\s*$}
#Reading commands list from file:
set fp1 [open "commands_list_2.out" "r"]
set file_data [read $fp1]
close $fp1
# read the hosts file one line at a time
# There should be no new line at the end of the hostnames.out file
set fp [open "hostnames_2.out" "r"]
while { [gets $fp data] >= 0 } {
set ssh1 [lindex $data 0]
set ssh1_usr [lindex $data 1]
set ssh1_pwd [lindex $data 2]
set ods [lindex $data 3]
set ods_usr [lindex $data 4]
set ods_pwd [lindex $data 5]
set serv1 [lindex $data 6]
set serv1_usr [lindex $data 7]
set serv1_pwd [lindex $data 8]
puts $ssh1
puts $ssh1_usr
puts $ssh1_pwd
puts $ods
puts $ods_usr
puts $ods_pwd
puts $serv1
puts $serv1_usr
puts $serv1_pwd
spawn -noecho ssh $ssh1_usr@$ssh1
expect {
"*password:" { send "$ssh1_pwd\r"}
"*route*" { puts "login failed"; exit 1 }
"timed out" { puts "login failed timed out"; exit 1 }
}
expect {
-re $prompt { send "whoami\r"}
}
expect -re $prompt {
send "ssh $ods_usr@$ods\r" }
expect {
"password:" { send "$ods_pwd\r" }
}
}
expect {
-re $prompt { send "whoami\r"}
}
expect -re $prompt {
send "ssh $serv1_usr@$serv1\r" }
expect {
"password:" { send "$serv1_pwd\r" }
}
expect -re $prompt
foreach a [list $file_data] {
send "$a"
expect -re prompt
}
expect -re prompt {
send "exit\r"
}
expect eof
close $fp
`
spawn -noecho ssh $ssh1_usr@$ssh1
expect {
"*route*" { puts "login failed"; exit 1 }
"timed out" { puts "login failed timed out"; exit 1 }
"*password:" { send "$ssh1_pwd\r"; exp_continue }
-re $prompt { send "whoami\r" }
}
expect -re $prompt {
send "exec ssh $ods_usr@$ods\r"
}
expect {
"password:" { send "$ods_pwd\r"; exp_continue }
-re $prompt { send "whoami\r" }
}
expect -re $prompt {
send "exec ssh $serv1_usr@$serv1\r"
}
expect {
"password:" { send "$serv1_pwd\r"; exp_continue }
-re $prompt { send "whoami\r" }
}
# You seem to be missing the sudo here?
foreach a [split $file_data "\n"] {
expect -re $prompt
send "$a"
}
expect -re $prompt
send "exit\r"
expect eof
close; ### TERMINATE THE SPAWN. IMPORTANT!
set fp [open "hostnames_2.out" "r"]
set hostnamedata [split [read $fp] "\n"]
close $fp
foreach line $hostnamedata {
lassign $line ssh1 ssh1_usr ssh1_pwd ods ods_usr ods_pwd serv1 serv1_usr serv1_pwd
# The code from above goes here
}