使用 Expect 的自动化登录

Expect 的基础知识

Expect 是由 Don Libes 基于 Tcl 语言开发的,并被广泛应用于交互式操作和自动化测试的场景之中,它尤其适用于需要对多台服务器执行相同操作的环境中,可以大幅度得提高系统管理人员的工作效率。目前,大部分 Unix/Linux 系统安装有 expect. 万一系统中没有,可以从 http://expect.nist.gov/ 下载相应的包安装。

Expect 作为基于 Tcl 的高级语言,增加了一些特殊的语法。传统意义上的 Expect 是以 Tcl 扩展包的形式出现的,任何 Tcl 语言编写的应用程序都可以加载 Expect 功能;此外,Expect 已经以模块的方式移植到了 Perl 和 Python 语言中,因此用户同样可以在 Perl 和 Python 脚本中利用 Expect 强大的交互功能。

Send,expect 和 spwan 是 Expect 语言最基本的命令。其中,send 命令会发送字符串给指定进程process); expect 命令会等待接受该进程返回的结果并且会根据返回的字符串来决定下一步的操作;而 spwan 命令可以发起一个进程的运行。

send 命令接收一个字符串做为参数并发送给指定的进程;从

send “Hello world”

这行代码中,send 会送出字符串“Hello world”( 不带引号 )。如果 Expect 早已经开始与某一个程序进行交互,那么这个字符串将被发送给该程序;而在通常情况下,这个字符串会被送到标准输出设备。

expect 命令则等待一个响应,通常是来自于 Expect 正在与之交互的进程,或者来自于标准输入设备;它会等待一个指定的字符串或者满足给定的正则表达式的任何字符串。我们可以创建一个名为 response.exp 的文件,来看 Expect 是如何处理的,其内容如下:

#!expect – f

expect “hi\n”

send “hello there\n”

然后在 shell 下面运行 ”expect response.exp”,它会等待来自标准输入设备的响应,直到用户输入 hi 并回车,它才会发送”hello there”到标准输出设备,并回车。然后结束 expect 脚本的运行。但是,如果用户没有输入 hi 并回车,那么 expect 会继续等待”hi\n”;输入其他的字符并不会影响到 expect 的工作。通常情况下,expect 会一直等会输入,直到最终超时退出。此外, expect 还支持使用正则表达式来预防 expect 匹配到未预想到的输入数据。

spawn 命令会调用另一个程序。它的第一个参数是要启动程序的名字;剩余的参数则会被传递给该程序做为参数。比如

spawn ftp linux.ibm.com">ftp.linux.ibm.com

命令会衍生出一个 ftp 进程,并且将 ftp.linux.ibm.com 做为参数传递给这个 ftp 进程。

用户通过 spawn,send 和 expect 这三个基本命令,就可以编写一段 Expect 程序来实现自动化工作。

Expect 脚本实现

本节将利用基于用户口令的安全认证方式,并使用 Expect 来实现 SSHD 服务器的自动化登录过程,并在登录的会话中实现命令在 SSHD 服务器端的执行。本文使用的具体实验环境如下:用户使用的 SSH 客户端机器:操作系统均为 RHELS5.3, IP 地址为 192.168.0.3, Expect 版本为 version 5.43.0;远程的 SSHD 服务器:操作系统均为 RHELS5.3,IP 地址为 192.168.0.4,用户名 / 密码为 root/123456。

清单1.登录 SSHD 服务器的自动化脚本

#!/usr/bin/expect

# 设置超时时间为 60 秒

set timeout  60

# 设置要登录的主机 IP 地址

set host 192.168.0.4

# 设置以什么名字的用户登录

set name root

# 设置用户名的登录密码

set password 123456

#spawn 一个 ssh 登录进程

spawn  ssh $host -l $name

# 等待响应,第一次登录往往会提示是否永久保存 RSA 到本机的 know hosts 列表中;等到回答后,在提示输出密码;之后就直接提示输入密码

expect {

"(yes/no)?" {

send "yes\n"

expect "assword:"

send "$pasword\n"

}

"assword:" {

send "$password\n"

}

}

expect "#"

# 下面测试是否登录到 $host

send "uname\n"

expect "Linux"

send_user  "Now you can do some operation on this terminal\n"

# 这里使用了 interact 命令,使执行完程序后,用户可以在 $host 终端进行交互操作。

Interact

如果要运行该脚本,可以参考如下的操作,假设 expect 脚本的文件名为 t1.expect。另外,在运行该脚本之前,需要将 t1.expect 文件设置成可执行的模式 ;

清单2.运行自动化登录脚本的操作步骤

[root@redhat ~]chmod a+x t1.expect

[root@redhat ~]./t1.expect

spawn ssh 192.168.0.4 -l root

root@192.168.0.4's password:

Last login: Fri Jun 12 15:36:01 2009 from 192.168.0.3

Red Hat Enterprise Linux Server release 5.1 (Tikanga)

[root@c96m3h4ms01 ~]# uname

Linux

Now you can do some operation on this terminal

[root@c96m3h4ms01 ~]#

基于 SSH 交换 Key 自动化登录

SSH 证书简介

SSH 证书使用一对密钥 : 私钥private key)和公钥 (public key)。公钥public key)对数据进行加密而且只能用于加密,私钥private key)只能对所匹配的公钥public key)加密过的数据进行解密。私钥private key)只保存你独有的一些秘密信息。SSH 客户端用其向 SSHD 服务器证明自已的身份。公钥是公开的,可以随便将其放入 SSHD 服务器上自已的帐号中 , 在认证时,进行私钥和公钥协商,如果匹配,那么身份就得以证明,认证就成功。

目前所有的 OpenSSH 版本都应该既能使用 RSA 密钥又能使用 DSA 密钥。RSA 密钥和 DSA 密钥的生成命令和使用方法相同,本文仅介绍 RSA。

如果采用 SSH 密钥认证的方式实现自动化登录,用户可以参考下面的章节。

生成密钥对

ssh-keygen 程序生成的 RSA 密钥的文件名默认为 id_rsa 和 id_rsa.pub,用户也可以将其更改为别的名称。下面”清单 3. 生成密钥对”的操作过程将采用系统的默认值。

清单3. 生成密钥对

[root@redhat ~]# ssh-keygen -t rsa

Generating public/private rsa key pair.

Enter file in which to save the key (/root/.ssh/id_rsa):

Created directory '/root/.ssh'.

Enter passphrase (empty for no passphrase):  <--- 可以不输入密码

Enter same passphrase again:   <--- 可以不输入密码

Your identification has been saved in /root/.ssh/id_rsa.

Your public key has been saved in /root/.ssh/id_rsa.pub.

The key fingerprint is:

4b:70:20:de:89:92:a9:fe:21:a4:9b:7c:6b:65:ae:e0 root@redhat

[root@redhat ~]# ls -al .ssh

total 20

drwx------  2 root root 4096 May 10 02:51 .

drwxr-x--- 11 root root 4096 May 10 02:51 ..

-rw-------  1 root root 1675 May 10 02:51 id_rsa

-rw-r--r--  1 root root  397 May 10 02:51 id_rsa.pub

如果 ssh 目录不存在,程序为自动创建本地 SSH 目录 ~/.ssh,并将所生成的密钥分成两个文件存储,私钥为 id_rsa,公钥为 id_rsa.pub。


相关内容