30:Shell编程-下

30:Shell编程-下

  • 30:Shell编程-下
    • Shell项目-分发系统
      • expect介绍
      • 安装expect
      • 实现自动远程登录
      • 构建文件分发系统
      • 分发系统-批量执行命令
    • 扩展

Shell项目-分发系统

expect介绍

expect 是一个用来实现自动交互功能的软件,是基于tool command Language脚本语言的编程工具。

在现今的企业运维中, 自动化运维已经成为运维的主流趋势,
但是在很多情况下,执行系统命令或程序时,系统会以交互式的形式要求运维人员输入指定的字符串,之后才能继续执行命令。
例如为用户设置密码时,一般情况下就需要手工输入2次密码。

安装expect

# 可以使用yun安装expect软件
yum install -y expect

实现自动远程登录

# 实验需要两台主机
# 主机1:10.1.1.32   主机2:10.1.1.30

自动远程登录脚本

# 1.expect 脚本文件内容如下
 #!/usr/bin/expect
set host "10.1.1.30"     # 设置变量,目标主机的ip
set passwd "123456"      # 设置变量,目标主机的密码
spawn ssh root@$host     # 自动交互开始,在Expect自动交互程序执行的过程中,spawn命令是一开始就需要使用的命令
expect {                 # expect命令用于匹配交互信息,输入争正确的交互内容。
"yes/no" { send "yes\n";exp_cuntinue }  #匹配出现 "yes/no" 的行,{输入yes\n,\n就是换行符,} #exp_countinue  表示继续匹配,只要不是交互过程的最后一行都要在后后面加上这个命令
"assword:" { send "$passwd\n" }  #输入密码 $passwd\n 。匹配的字符串不加p是因为不清楚是大写还是小写
}
interact   #interact表示expect脚本结束了

# 注: 大括号的两边都需要有空格

测试脚本是否可用

# 先给脚本加上执行权限
chmod 755 1.expect

# 执行脚本
[root@shell ~]> ./1.expect 
spawn ssh root@10.1.1.30
root@10.1.1.30's password: 
Last login: Tue Jul 31 23:40:29 2018 from 10.1.1.170
[root@zabbix-server ~]# 
# 可以正常登陆到目标主机就算成功了

自动登陆后,执行命令后退出

# 2.expect  脚本文件的内容如下

#!/usr/bin/expect
set host "10.1.1.30"
set passwd "123456"
spawn ssh root@$host
expect {
"yes/no" { send "yes\n"; exp_continue}
"assword:" { send "$passwd\n"}
}
expect "]*"                     # 匹配字符串 ]*   *号代表通配任意字符
send "touch /tmp/ecpect.txt\r"  # 输入命令 touch /tmp/ecpect.txt 这里命令结尾的\r 与前面的\n效果类似
expect "]*"
send "echo "expect test"  > /tmp/ecpect.txt\r" # 输入命令 echo "expect test" >/tmp/ecpect.txt
expect "]*"
send "exit\r"                    # 输入命令 exit   退出目标主机

测试脚本效果

# 老规矩 加执行权限
[root@shell ~]> chmod 755 2.expect

# 执行脚本 后边的全是自动输入的
[root@shell ~]> ./2.expect 
spawn ssh root@10.1.1.30
root@10.1.1.30's password: 
Last login: Fri Aug  3 00:54:02 2018 from 10.1.1.32
[root@zabbix-server ~]# touch /tmp/expect.txt
[root@zabbix-server ~]# echo 'expect test' > /tmp/expect.txt
[root@zabbix-server ~]# [root@shell ~]> 最后退出了10.1.1.30 回到到了当前的主机 

# 再次登录10.1.1.30 查看文件是否创建OK
[root@shell ~]> ./1.expect 
spawn ssh [email protected]
[email protected]'s password: 
Last login: Fri Aug  3 01:10:51 2018 from 10.1.1.32
[root@zabbix-server ~]# cat /tmp/expect.txt 
expect test
# 文件内容没问题。

传递参数

# 3.expect 脚本文件内容如下
#!/usr/bin/expect
set user [lindex $argv 0]  #  调用第一个参数  给变量user   用户名
set host [lindex $argv 1]  # 调用第二个参数 给变量host     ip
set passwd "123456"
set cm [lindex $argv 2]    #调用第三个参数 给变量cm       需要执行的命令
spawn ssh $user@$host

expect {
"yes/no" { send "yes\r"}
"password:" { send "$passwd\r" }
}
expect "]*"
send "$cm\r"
expect "]*"
send "exit\r"

测试脚本效果

# 加执行权限
[root@shell ~]> chmod 755 3.expect 

# 执行脚本,带上参数,第一个参数是登录目标主机的用户, 第二个参数是目标主机的ip 第三个参数是需要执行的命令
[root@shell ~]> ./3.expect root 10.1.1.30 "echo 'parameter test' >> /tmp/expect.txt"
spawn ssh root@10.1.1.30
root@10.1.1.30's password: 
Last login: Fri Aug  3 01:13:59 2018 from 10.1.1.32
[root@zabbix-server ~]# echo 'parameter test' >> /tmp/expect.txt
[root@zabbix-server ~]# [root@shell ~]> 

#再次执行脚本  执行的命令是查看目标主机下 /tmp/expect.txt 的文件内容
[root@zabbix-server ~]# [root@shell ~]> ./3.expect root 10.1.1.30 "cat /tmp/expect.txt"
spawn ssh [email protected]
[email protected]'s password: 
Last login: Fri Aug  3 01:27:07 2018 from 10.1.1.32
[root@zabbix-server ~]# cat /tmp/expect.txt
expect test
parameter test

自动同步文件

# 4.expect 脚本文件内容
#!/usr/bin/expect
set passwd "123456"
spawn rsync -av root@10.1.1.30:/tmp/expect.txt /tmp/  #核心命令
expect {
"yes/no" { send "yes\r"}
"password:" { send "$passwd\r" }
}
expect eof    
# 当一个命令需要一定时间才能执行完的情况下,脚本最后需要加expect eof命令, 可以等待命令执行完毕才会结束脚本
# 还有在send执行的shell命令的下一行添加一个超时时间  timeout , 
# 例如: timeout 5 为5秒超时。 -1为永不超时

测试脚本效果

[root@shell ~]> chmod 755 4.expect
[root@shell ~]> ./4.expect 
spawn rsync -av root@10.1.1.30:/tmp/expect.txt /tmp/
root@10.1.1.30's password: 
receiving incremental file list
expect.txt

sent 43 bytes  received 123 bytes  110.67 bytes/sec
total size is 27  speedup is 0.16

# 查单本地的/tmp目录下是否有expect.txt文件
[root@shell ~]> cat /tmp/expect.txt 
expect test
parameter test
# 同步成功

指定目标主机和需要同步的文件, 将文件同步到目标主机上,此方式只能同步一个文件或者目录

# 5.expect 脚本文件内容
#!/usr/bin/expect
set passwd "123456"
set host [lindex $argv 0]   #第一个参数指定目标主机的ip
set file [lindex $argv 1]   #第二个参数指定要同步的文件或目录, 必须要使用绝对路径。
spawn rsync -av $file root@$host:$file
expect {
"yes/no" { send "yes\r"}
"password:" { send "$passwd\r" }
}
expect eof

测试脚本效果

# 创建一个目录,然后在目录下创建一个文件 用户测试
[root@shell ~]> mkdir testdir
[root@shell ~]> touch testdir/testfile.txt

# 执行脚本
[root@shell ~]> chmod 755 5.expect
[root@shell ~]> ./5.expect 10.1.1.30 /root/testdir/   #参数使用刚才创建目录的绝对路径 
spawn rsync -av /root/testdir/ root@10.1.1.30:/root/testdir/
root@10.1.1.30's password: 
sending incremental file list
created directory /root/testdir
./
testfile.txt

sent 113 bytes  received 74 bytes  374.00 bytes/sec
total size is 0  speedup is 0.00

# 检查10.1.1.30 的/root 目录下是否有同步过去的文件
[root@zabbix-server ~]> tree /root/
/root/
├── anaconda-ks.cfg
└── testdir
    └── testfile.txt

1 directory, 2 files
# 同步成功

构建文件分发系统

需求背景:

对于大公司而言,肯定时不时会有网站或者配置文件更新,而且使用的机器肯定也是好多台,少则几台,多则几十甚至上百台。所以,自动同步文件是至关重要的。

实现思路 首先要有一台模板机器,把要分发的文件准备好,

然后只要使用expect脚本批量把需要同步的文件分发到目标机器即可。

核心命令: rsync -av –files-from=list.txt / root@host:/

定义用于同步文件的expect脚本

# rsync.expect 脚本文件内容
#!/usr/bin/expect
set passwd "123456"
set host [lindex $argv 0]
set file [lindex $argv 1]
spawn rsync -avR --files-from=$file / root@$host:/    # R选项可以在目标主机中不存在同步的目录时自动创建相关目录 
expect {
"yes/no" { send "yes\r"}
"password:" { send "$passwd\r" }
}
expect eof

创建一个存放文件路径的列表文件

# files.list 文件的内容如下:
/root/111/111.txt
/data/wwwroot/222.txt
/tmp/2333.txt

创建列表文件中的相关文件,用于实验

[root@shell ~]> mkdir /root/111
[root@shell ~]> mkdir /data/wwwroot/ -p
[root@shell ~]> touch `cat files.list`

创建一个主机IP列表文件

# ips.list文件内容如下,这里我就用一台主机来做实验了,这个文件中可以放多个主机的IP
10.1.1.30

创建一个循环同步的shell脚本

# rsync.sh 脚本文件内容如下:
#!/bin/bash
for ip in `cat ips.list`
do
    echo $ip
    ./rsync.expect $ip files.list
done

测试脚本效果

# 给脚本文件执行权限
[root@shell ~]> chmod 755 rsync.sh rsync.expect

# 执行脚本 rsync.sh
[root@shell ~]> ./rsync.sh 
10.1.1.30
spawn rsync -av --files-from=./files.list / [email protected]:/
root@10.1.1.30's password: 
building file list ... done
data/
data/wwwroot/
data/wwwroot/222.txt
root/
root/111/
root/111/111.txt
tmp/
tmp/2333.txt

sent 344 bytes  received 88 bytes  864.00 bytes/sec
total size is 0  speedup is 0.00

# 查看10.1.1.30主机上是否有刚才同步过去的文件
[root@zabbix-server ~]> ls -dl /data/wwwroot/222.txt /root/111/111.txt  /tmp/2333.txt 
-rw-r--r--. 1 root root 0 8月   3 11:47 /data/wwwroot/222.txt
-rw-r--r--. 1 root root 0 8月   3 11:47 /root/111/111.txt
-rw-r--r--. 1 root root 0 8月   3 11:47 /tmp/2333.txt
# 同步成功

注:这个文件分发系统有一个弊端,所有同步的主机都需要使用相同的密码, 而且有泄露密码的风险。

但是也可以使用密钥认证登录的方式来解决这个问题。

分发系统-批量执行命令

思路:创建一个执行指定命令的expect脚本, 然后使用一个shell脚本来循环执行这个expect脚本

创建 exe.expect 脚本文件,内容如下

#!/usr/bin/expect
set host [lindex $argv 0]
set passwd "123456"
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 脚本文件,内容如下, 这里又用到了之前的 ips.list 主机列表文件

#!/bin/bash
for ip in `cat ip.list`  # 遍历主机IP列表
do
    echo $ip
    ./exe.expect $ip "w;free -m;df -h"  执行exe.expect脚本, 指定主机ip 和需要执行的命令 
done

测试脚本效果

[root@shell ~]> ./exe.sh 
10.1.1.30
spawn ssh root@10.1.1.30
root@10.1.1.30's password: 
Last login: Fri Aug  3 10:16:16 2018 from 10.1.1.128
[root@zabbix-server ~]# w;free -h;df -h
 12:27:53 up  2:36,  3 users,  load average: 0.00, 0.01, 0.05
USER     TTY      FROM             LOGIN@   IDLE   JCPU   PCPU WHAT
root     tty1                      09:52    1:58m  0.05s  0.05s -bash
root     pts/0    10.1.1.1         10:03    2:33   0.05s  0.05s -bash
root     pts/1    10.1.1.128       12:27    0.00s  0.03s  0.02s w
              total        used        free      shared  buff/cache   available
Mem:           976M        138M        437M        6.8M        400M        646M
Swap:          2.0G          0B        2.0G
文件系统                 容量  已用  可用 已用% 挂载点
/dev/mapper/centos-root   27G  1.1G   26G    4% /
devtmpfs                 478M     0  478M    0% /dev
tmpfs                    489M     0  489M    0% /dev/shm
tmpfs                    489M  6.8M  482M    2% /run
tmpfs                    489M     0  489M    0% /sys/fs/cgroup
/dev/sda1               1014M  125M  890M   13% /boot
tmpfs                     98M     0   98M    0% /run/user/0


# 执行成功

扩展

shell多线程

你可能感兴趣的:(Linux基础)