1、expect同步文件: 自动同步文件; 一台机器向一台机器同步文件:
1:在一台机器上,把文件同步到其他机器上;并添加执行权限:
[root@localhost_01 sbin]# vim 4.expect
[root@localhost_01 sbin]# cat 4.expect
#!/usr/bin/expect
set passwd "nihao123!"
spawn rsync -av -e "ssh -p 56888" root@192.168.149.129:/tmp/12.txt /tmp/
expect {
"yes/no" { send "yes\r"}
"password:" { send $passwd\r}
}
expect eof
[root@localhost_01 sbin]# chmod a+x 4.expect
2:执行这个脚本: ./4.expect 并查看同步后的文件内容:
[root@localhost_01 sbin]# ./4.expect
spawn rsync -av -e ssh -p 56888 root@192.168.149.129:/tmp/12.txt /tmp/
root@192.168.149.129's password:
receiving incremental file list
12.txt
sent 43 bytes received 96 bytes 278.00 bytes/sec
total size is 5 speedup is 0.04
[root@localhost_01 sbin]# ls /tmp/12.txt
/tmp/12.txt
[root@localhost_01 sbin]# ll /tmp/12.txt
-rw-r--r-- 1 root root 5 Oct 4 06:04 /tmp/12.txt
注释:expect eof表示只有spawn执行命令的结果才会被expect捕捉到,因为spawn会启动一个进程,只有这个进程相关信息才会被捕捉到,注意包括标准输入的提示信息,eof 和timeout:
如下测试,注释掉expect eof,则还没来得及传输了,就退出来了(仅仅到输入密码的那里)
[root@localhost_01 sbin]# vim 4.expect
#!/usr/bin/expect
set passwd "nihao123!"
spawn rsync -av -e "ssh -p 56888" root@192.168.149.129:/tmp/12.txt /tmp/
expect {
"yes/no" { send "yes\r"}
"password:" { send $passwd\r}
}
#expect eof #注释掉:
[root@localhost_01 sbin]# rm -fr /tmp/12.txt
[root@localhost_01 sbin]# ./4.expect
spawn rsync -av -e ssh -p 56888 root@192.168.149.129:/tmp/12.txt /tmp/
root@192.168.149.129's password: [root@localhost_01 sbin]#
2、expect指定host和要同步的文件:
[root@localhost_01 sbin]# vim 5.expect
[root@localhost_01 sbin]# cat 5.expect
#!/usr/bin/expect
set passwd "nihao123!"
set host [lindex $argv 0]
set file [lindex $argv 1]
spawn rsync -av -e "ssh -p 56888" $file root@$host:$file
expect {
"yes/no" { send "yes\r"}
"password:" { send "$passwd\r"}
}
expect eof
[root@localhost_01 sbin]# chmod a+x 5.expect
注释:用变量定义的文件所在目录要写绝对路径才可:
如:同步本机目录/tmp/12.txt到远端主机192.168.149.129的/tmp/目录下:
[root@localhost_01 sbin]# ./5.expect 192.168.149.129 "/tmp/12.txt"
spawn rsync -av -e ssh -p 56888 /tmp/12.txt root@192.168.149.129:/tmp/12.txt
root@192.168.149.129's password:
sending incremental file list
12.txt
sent 100 bytes received 35 bytes 90.00 bytes/sec
total size is 9 speedup is 0.07
注释:因为同步rsync需要借助ssh的端口,如果是默认的22端口或者自定义的,那如果有多台机器的ssh的端口各不相同,那是否可以把port当成一个参数来传递:如下:
[root@localhost_01 sbin]# vim 5.expect
#!/usr/bin/expect
set passwd "nihao123!"
set port [lindex $argv 0]
set host [lindex $argv 1]
set file [lindex $argv 2]
spawn rsync -av -e "ssh -p $port" $file root@$host:$file
expect {
"yes/no" { send "yes\r"}
"password:" { send "$passwd\r"}
}
expect eof
[root@localhost_01 sbin]# ./5.expect 56888 192.168.149.129 "/tmp/12.txt"
spawn rsync -av -e ssh -p 56888 /tmp/12.txt root@192.168.149.129:/tmp/12.txt
root@192.168.149.129's password:
sending incremental file list
sent 44 bytes received 12 bytes 37.33 bytes/sec
total size is 9 speedup is 0.16
2、构建文件分发系统;
一台机器向多台机器同步文件:
需求背景:对于大公司而言,肯定会时不时有网站或者配置文件更新,而且使用的机器也是好多台,少则几台,多则上百台,所以自动同步文件是很重要的:
实现思路:首先需要有一台模板机器,提前把要分发的文件准备好,然后只要使用expect脚本批量把需要同步的文件分发到目标机器即可:
核心命令:rsync -av --filep-from=list.txt / root@host:/
注释:使用rsync 的 --files参数,可以实现调用文件里面的列表(列表里的路径需要绝对路径),进行多个文件远程传输,进而实现文件分发:
1:创建rsync.expect的脚本内容:
[root@localhost_01 sbin]# vim rsync.expect
[root@localhost_01 sbin]# cat rsync.expect
#!/usr/bin/expect
set passwd "nihao123!"
set host [lindex $argv 0]
set file [lindex $argv 1]
spawn rsync -avR -e "ssh -p 56888" --files-from=$file / root@$host:/
#这个地方定义了原目录和目标目录以跟目录开始
expect {
"yes/no" { send "yes\r"}
"password:" { send "$passwd\r" }
}
expect eof
[root@localhost_01 sbin]# chmod a+x rsync.expect
注释:文件路径放在/tmp/flie.list:同步的路径,我们要把要同步的文件路径放在/tmp/list.txt里面,这个时候需要保证对方机器上也要有个这个路径(文件有没有无所谓),如果没有路径,则需要使用rsync -avR创建路径:
注释:IP列表 /tmp/ip.list:实现分发系统,远程同步的机器数量大,还需要定义一个IP列表 /tmp/ip.txt;
创建同步文件的列表和创建分发系统的IP地址列表:
注释:同步前提是分发系统的密码需要都一样才可以,但是这也容易造成系统不安全(expect脚本泄露),不过可以也使用秘钥验证(rsync验证),省略掉密码的哪一步;
2:创建同步文件列表(写绝对路径):/tmp/file.list
[root@localhost_01 sbin]# vim /tmp/flie.list
/tmp/12.txt
/root/shell/test.sh
/root/111/222/111.txt
3:创建IP地址列表: /tmp/ip.list
[root@localhost_01 sbin]# vim /tmp/ip.list
192.168.149.129
192.168.149.131
4:创建rsync.sh脚本: 并给予执行权限:
[root@localhost_01 sbin]# vim rsync.sh
#!/bin/bash
for ip in `cat /tmp/ip.list`
do
echo $ip
./rsync.expect $ip /tmp/file.list
done
[root@localhost_01 sbin]# chmod a+x rsync.sh
5:执行rsync.sh脚本: ./rsync.sh
[root@localhost_01 sbin]# sh rsync.sh
192.168.149.129
spawn rsync -avR -e ssh -p 56888 --files-from=/tmp/file.list / root@192.168.149.129:/
root@192.168.149.129's password:
building file list ... done
root/
root/111/
root/111/222/
root/111/222/111.txt
root/shell/
root/shell/test.sh
tmp/
sent 415 bytes received 69 bytes 322.67 bytes/sec
total size is 118 speedup is 0.24
192.168.149.131
spawn rsync -avR -e ssh -p 56888 --files-from=/tmp/file.list / root@192.168.149.131:/
root@192.168.149.131's password:
building file list ... done
root/
root/111/
root/111/222/
root/111/222/111.txt
root/shell/
root/shell/test.sh
tmp/
tmp/12.txt
sent 467 bytes received 88 bytes 1,110.00 bytes/sec
total size is 118 speedup is 0.21
注释:这个shell脚本的目的,就是遍历一下IP列表中的IP地址;
注释:重要的是expect脚本要加上执行权限,并且两端都要安装rsync服务:
注释:分发系统还有一个重要的关键是,确保同步的机器的密码以及端口号(因为rsync要以来sshd的端口)一致,否则将不能实现同步;所以这就存在一个弊端,一旦脚本暴露,将会让别人知道如何登陆你机器;当然也有对应的解决办法,那就是使用密钥认证,这样的话,自然在命令行业省去“输入密码< password:" { send "$passwd\r" } >''”和“定义密码< set passwd "123123a" >”的命令了;
2、批量远程执行命令; 有时候远端机器操作完后,需要远程重启,或者重启服务等,则使用这个方法;
1: 创建exe.expcet脚本: 并给执行权限;
[root@localhost_01 sbin]# vim exe.expect
#!/usr/bin/expect
set port [lindex $argv 0]
set host [lindex $argv 1]
set cm [lindex $argv 2]
set passwd "nihao123!"
spawn ssh $port root@$host
expect {
"yes/no" { send "yes\r"}
"password:" { send "$passwd\r" }
}
expect "]*"
send "$cm\r"
expect "]*"
send "exit\r"
[root@localhost_01 sbin]# chmod a+x exe.expect
2:创建exe.sh执行脚本:
#!/bin/bash
for ip in `cat ip.list`
do
echo $ip
./exe.expect $port -p56888 $ip "hostname"
done
3:执行脚本: sh exe.sh
[root@localhost_01 sbin]# sh exe.sh
192.168.149.129
spawn ssh -p56888 root@192.168.149.129
root@192.168.149.129's password:
Last login: Thu Oct 4 07:12:29 2018 from 192.168.149.130
[root@localhost_02 ~]# hostname
localhost_02
[root@localhost_02 ~]# 192.168.149.131
spawn ssh -p56888 root@192.168.149.131
root@192.168.149.131's password:
Last login: Thu Oct 4 20:19:06 2018 from 192.168.149.135
[root@localhost_03 ~]# hostname
localhost_03
来源:oschina
链接:https://my.oschina.net/u/3711371/blog/2222868