20.27 分发系统介绍
20.28 expect脚本远程登录
20.29 expect脚本远程执行命令
20.30 expect脚本传递参数
20.31 expect脚本同步文件
20.32 expect脚本指定host和要同步的文件
20.33 构建文件分发系统
20.34 批量远程执行命令
扩展:
shell多线程 http://blog.lishiming.net/?p=448
给你提供一本电子书 链接:http://pan.baidu.com/s/1mg49Taw 密码:yk4b
shell习题做一下 http://www.apelearn.com/study_v2/chapter15.html#shll
一、分发系统介绍
如今一些比较大的企业,大都使用了负载均衡,而有时因为一些程序要更改,或者有些bug要修改,快速更新代码等,如果仅是几台server的话,很简单,把已经改好的程序拷过去,或者rsync远程推送,再或者网上NFS共享一下就可以了;但如果有几十台几百台,那样的方法会太繁琐,此时就可以用expect来批量实现分发任务。
-
expect:一个实现自动交互功能的软件套件,基于Tcl的一种脚本语言,具有简单的语法;
-
功 能 :实现自动登录远程机器,并自动执行命令;和shell脚本结合,可以实现完全自动化;
-
注 意:若是使用不带密码的密钥验证同样可以实现自动登录和自动远程执行命令。但当不能使用密钥验证的时候,我们就没有办法了。所以,这时只知道对方机器的账号和密码可以通过expect脚本实现登录和远程命令。
二、expect脚本远程登录
001上进入/usr/local/sbin/,创建一个expect脚本,如果带有注释写入脚本会报错
#! /usr/bin/expect set host "192.168.183.33" #设置连接主机,定义变量host set passwd "qwertyuiop" #设置密码,定义变量passwd spawn ssh root@$host #执行命令 expect { "yes/no" { send "yes\r"; exp_continue} #假如第一次登陆,需要yse,然后回车,继续执行 "password:" { send "$passwd\r" } #输入密码 } interact #结束执行
代码解释: #! /usr/bin/expect 这一行告诉操作系统脚本里的代码使用那一个shell来执行。
-
在expect下 定义变量,用 set,比如 定义变量a为1 :set a 1
-
expect 使用expect语句进行交互
-
\r表示回车
-
exp_continue 表示继续 \r 表示换行 interact 继续停留在这台机器,不退出。
-
interact表示继续交互,会继续停留在远程的机器上不退出,如果使用expect eof,会在远程机器上暂停1-2秒在退出
上面脚本中的yes或no,即表示下面操作
如果登陆过就不在提示输入yes或no,需要在vim /root/.ssh/known_hosts删除对应机器的ip就会在远程登陆时出现提示
或者 > /root/.ssh/known_hosts //清空
给脚本执行权限: chmod a+x 1.expect
./1.expect 执行脚本后,即可自动连接到002
不清空known_hosts下次连接则不提示yes或no
三、 expect脚本远程执行命令
自动远程登录后,执行命令并退出,给执行权限chmod a+x 2.expect
#!/usr/bin/expect set user "root" 设置用户为 root set passwd "qwertyuiop" root的密码 spawn ssh $user@192.168.183.33 连接远程机器002 expect { expect脚本内容 "yes/no" { send "yes\r"; exp_continue} "password:" { send "$passwd\r" } } expect "]*" 遇到右侧方括号执行下面命令,root用户时是'#',普通用户是'$',此处用'*',不做区分 send "touch /tmp/12.txt\r" 在/tmp下创建12.txt;回车 expect "]*" 上一语句执行完,遇到右侧方括号,执行下面 send "echo 1212 > /tmp/12.txt\r" 把1212写入12.txt,回车 expect "]*" send "exit\r" 输入exit,退出,回到001机器
执行脚本,到002查看,文件和内容都执行,创建时间也没问题
四、expect脚本传递参数
expect脚本传递过来的参数可以使用[lindex $argv n]获得,n从0开始,分别表示第一个,第二个,第三个….参数
#!/usr/bin/expect set user [lindex $argv 0] 第一个参数 set host [lindex $argv 1] 第二个参数 set passwd "qwertyuiop" set cm [lindex $argv 2] 第三参数 spawn ssh $user@$host expect { "yes/no" { send "yes\r"} "password:" { send "$passwd\r" } } expect "]*" send "$cm\r" expect "]*" send "exit\r"
给予可执行权限,并定义参数后执行脚本
chmod a+x 3.expect ./3.expect root 192.168.183.33 "ls"
参数中可以定义多个命令:如执行pwd、w、ls -l、vmstat 1等,命令之间用分号隔开
./3.expect root 192.168.183.33 "pwd;w;ls -l;vmstat 1"
也可以都使用参数代替,但是执行的时候要定义对应参数后执行脚本
五、expect脚本同步文件
在一台机器上把文件同步到多台机器上;核心命令,就是用的rsync服务
#!/usr/bin/expect set passwd "qwertyuiop" spawn rsync -av root@192.168.183.33:/tmp/12.txt /tmp/ expect { "yes/no" { send "yes\r"} "password:" { send $passwd\r} } expect eof
expect eof 语句解释:
-
spawn执行的命令结果,会被expect捕捉到。因为spawn会启动一个进程,只有这个进程的相关信息才会被捕捉到,主要包括:标准输入的提示信息,eof和timeout。
-
在这里eof是必须去匹配的,在spawn进程结束后会向expect发送eof,如果expect没有匹配,那么会立即退出远程登录,即操作失败。
chmod a+x 4.expect
同步完成
六、expect脚本指定host和要同步的文件
set timeout 定义超时时间(单位为 秒) -1 为永远不超时 这里要同步的文件,必要要写绝对路径
此脚本只能同步单个文件
#!/usr/bin/expect set passwd "qwertyuiop" set host [lindex $argv 0] set file [lindex $argv 1] spawn rsync -av $file root@$host:$file expect { "yes/no" { send "yes\r"} "password:" { send "$passwd\r" } } expect eof
chmod a+x 5.expect
七、构建文件分发系统
需求背景
对于大公司而言,肯定时不时会有网站或者配置文件更新,而且使用的机器肯定也是好多台,少则几台,多则几十甚至上百台。所以,自动同步文件是至关重要的。
实现思路
首先要有一台模板机器,把要分发的文件准备好,然后只要使用expect脚本批量把需要同步的文件分发到目标机器即可。
核心命令
rsync -av --files-from=list.txt / root@host:/
使用rsync 的 --files-from参数,可以实现调用文件里面的列表,进行多个文件远程传输,进而实现文件分发文件分发系统的实现。
编写rsync.expect 脚本, chmod a+x rsync.expect
#!/usr/bin/expect set passwd "jiangbin" set host [lindex $argv 0] set file [lindex $argv 1] spawn rsync -avR --files-from=$file / root@$host:/ # 上传文件的列表是$file,需要在list当中去定义; --file-from指定文件列表路径 -R表示同步时会把不存在的目录进行创建 expect { "yes/no" { send "yes\r"} "password:" { send "$passwd\r" } } expect eof
创建file.list 需要同步的文件列表
/tmp/file.list
因为实现分发系统,是因为需要分发的机器数量过大,所以,定义好了 list 文件列表以后, 还需要配置 ip 的列表文件
几台机器的密码要相同,如果设置了秘钥,可以把输入密码的步骤省略
/tmp/ip.list 把本地的数据同步到列表中的两台机器上
创建一个rsync的shell脚本,脚本的目的:遍历所有的server和list中的文件可以同步到每台服务器。
#!/bin/bash for ip in `cat /tmp/ip.list` do echo $ip ./rsync.expect $ip /tmp/file.list done
此时查看下发数据的两台机器,已经有了下发的数据,并且会把两台机器上不存在的目录进行创建,新创建目录中的文件也会下发
八、批量远程执行命令
当同步完代码后有可能需要批量地重启服务,因此还需要批量远程执行命令,类似于自动化。 这里是用expect编写执行命令的脚本并用shell脚本来批量调用它。
创建exe.expect,chmod a+x exe.expect
#!/usr/bin/expect set host [lindex $argv 0] set passwd "jiangbin" set cm [lindex $argv 1] spawn ssh root@$host expect { "yes/no" { send "yes\r"} "password:" { send "$passwd\r" } } expect "]*" send "$cm\r" expect "]*" send "exit\r"
再新建exe.sh的shell脚本,用来调用exe.expect脚本
#!/bin/bash for ip in `cat /tmp/ip.list` do ./exe.expect $ip "ls" 调用exe.expect脚本,此处只执行ls命令,可以写成"w;free -m;ls /tmp"执行多个命令 done