Expect脚本SSH自动化:实现无密码登录与远程命令执行教程
Expect 脚本是一个强大的 Linux/Unix 自动化工具。在我的日常工作中,我需要管理大量的 Unix 服务器,包括工作环境和个人托管服务器。这导致我需要记住大量的 SSH 用户名、密码,以及随后的 SU 用户名和密码。当服务器数量众多时,管理这些信息变得相当混乱。因此,我萌生了编写一个能够自动登录服务器的脚本的想法。当我最初着手解决这个问题时,我遇到了一个难题:如何输入 SSH 密码?因为普通的 Unix Shell 在接收到登录提示时,无法发送密码。后来我了解到 Expect 脚本可以自动化与需要终端交互的程序进行互动。
Expect 脚本简介
Expect 脚本非常易学,正如其名称所示,它通过解析命令的输出结果,并在匹配到指定的正则表达式时,执行相应的指令。
Expect 脚本 SSH 示例
以下是我为实现自动登录 SSH 服务器、切换到超级用户并运行一个简单命令而编写的脚本:sshsudologin.expect。
#!/usr/bin/expect
# 用法: sshsudologin.expect <主机> <SSH 用户> <SSH 密码> <SU 用户> <SU 密码>
set timeout 60
spawn ssh [lindex $argv 1]@[lindex $argv 0]
expect "yes/no" {
send "yes\r"
expect "*?assword" { send "[lindex $argv 2]\r" }
} "*?assword" { send "[lindex $argv 2]\r" }
expect "# " { send "su - [lindex $argv 3]\r" }
expect ": " { send "[lindex $argv 4]\r" }
expect "# " { send "ls -ltr\r" }
interact
关于 Expect 脚本的重要注意事项
- 请注意脚本的第一行,它指定了使用
expect作为解释器。 - Expect 脚本的默认超时时间是 10 秒,所以我将超时时间设置为 60 秒,以避免在登录提示出现较慢时发生超时问题。
- 请注意
expect命令后面跟着的正则表达式,以及随后应该发送的响应。第一个yes/no选项是为了确保如果远程服务器的密钥尚未导入,脚本不会失败。 - 其他的
expect正则表达式可能因服务器而异。对于我的服务器,提示符以“#”结尾,但对于其他一些服务器,它可能以“$”结尾,因此您可能需要相应地进行编辑。唯一需要检查的是expect命令的正则表达式是否匹配,这样它才能发送相应的命令或密码。 - 最后一个
expect命令仅仅表示一旦我们登录到服务器之后,我们也可以发送其他命令。
当我使用正确的参数运行上述 Expect 脚本时,这是输出结果:
scdev@Pankajs-MacBook-Pro:~$/Users/scdev/scripts/sshloginsudo.expect 'scdev.com' 'scdev' 'ssh_pwd' 'su_user' 'su_pwd'
spawn ssh scdev@scdev.com
scdev@scdev.com's password:
Last login: Sun Jun 9 19:54:17 2013 from c-67-161-57-160.hsd1.ca.comcast.net
scdev@journal [~]# su - su_user
Password:
su_user@journal [~]# ls -ltr
total 708
...
关于 Expect 脚本的额外提示
- 由于所有信息都作为参数传递,Expect 脚本可以重复使用。因此,最好为每个参数创建别名,以便快速登录并节省输入所有参数的时间。例如,别名
journal="/Users/scdev/scripts/sshloginsudo.expect 'scdev.com' 'scdev' 'ssh_pwd' 'su_user' 'su_pwd'"。 - 最好使用单引号传递参数,因为大多数情况下密码包含特殊字符,如果没有引用,可能会导致意想不到的结果。
注意:上述脚本已在 Mac OS 和 Linux 系统上进行了测试。参考:SourceForge 页面。