期望用于检查 ssh 连接以获取 ips 列表的脚本

Expect script for checking ssh connection for a list of ips

任何人都可以帮助我创建一个 expect 脚本来在服务器列表上执行 SSH 并检查它是否正常。我不需要交互,不需要在每个服务器上触发任何命令,我只想做一个ssh然后出来,用一个return代码来说明它是否成功。

Expect 在这里很重要,因为我没有设置无密码连接的选项。也有可能在其中一些服务器上设置了无密码连接。

我试过类似的方法:

#!/usr/local/bin/expect
set timeout 10
set ip [lindex $argv 0]
set user [lindex $argv 1]
set password [lindex $argv 2]
set prompt "(>|%|\\\$|#|]|) $"
spawn ssh "$user\@$ip"
expect "Password:"
send "$password\r"
send "echo hello\r"
expect "hello"
send "exit\r"

但这会卡在第一台服务器上,之后什么都不做。

谢谢, 皮尤什

一个普遍的想法可能是有一个程序来生成 ssh 并关闭连接,这将维护范围的本地连接,这样全局 spawn_id 就不会受到任何影响。

#!/usr/bin/expect
proc isHostAlive {host user pwd} {
 # We escaped the `$` symbol with backslash to match literal '$'
 # Commonly used prompt types
 set prompt "#|%|>|\$"
 set timeout 60
 spawn ssh $user@$host
 expect {
    timeout  {return FAIL}
    "(yes/no)" {send "yes\r";exp_continue}
    "password:" {send "$pwd\r";exp_continue}
    -re $prompt 
 }
 set msg "Hello World"
 send "echo $msg\r"
 expect { 
    timeout {return FAIL}
    "\r\n$msg"
 }
 send "exit\r"
 expect {
    timeout {return FAIL}
    eof
 }
 return PASS
}

# Lists to maintain the each host's information 
set serverList {server1 server2 server3}
set userList {user1 user2 user3}
set pwdList {pwd1 pwd2 pwd3}

# Looping through all the servers and checking it's availability
foreach server $serverList user $userList pwd $pwdList { 
    puts "\n==>Status of $server : [isHostAlive $server $user $pwd]\n"
}

使用exp_continue,即使任何主机没有密码,我们也可以处理。基本上 exp_continue 会导致 expect 再次变为 运行。因此,在提到的短语中,无论哪个出现,都会被处理。即如果 expect 看到 (yes/no),它会发送 yes,如果 expect 看到 password,它会发送密码值等等。然后expect会继续等待整套短语再次出现。

之所以加上yes/no是因为假设主机的RSA指纹需要保存。

成功登录后,我正在回显Hello World并期待回显消息。如果您注意到了,我在 expect 语句中使用了 \r\n$msg。为什么我们需要 \r\n 这里?

原因如下。每当我们发送 expect 也会看到的命令时,它也会尝试与之匹配。如果匹配,它将照此进行。

回显命令输出示例

dinesh@dinesh-VirtualBox:~/Whosebug$ echo Hello World
Hello World
dinesh@dinesh-VirtualBox:~/Whosebug$ 

我们想要的字符串在send命令中已经存在。因此,为了确保匹配的期望字符串仅来自实际的回显响应,我添加了 \r\n 这将帮助我们匹配必要的内容。

然后在 proc 的最后,我发送 exit 命令将关闭 ssh 连接并匹配使用相同的 eof(文件结尾)。在各种失败情况下,该过程将 return FAIL.