第二十章、shell编程(下)

20.27 分发系统介绍
20.28 expect脚本远程登录
20.29 expect脚本远程执行命令
20.30 expect脚本传递参数
20.31 expect脚本同步文件
20.32 expect脚本指定host和要同步的文件
20.33 构建文件分发系统
20.34 批量远程执行命令
20.35 扩展
 
 
20.27 分发系统介绍
shell项目---分发系统
功能:
  • 可以传输文件到大量机器;
  • 可以远程执行命令不需要输入密码;
 
 
20.28 expect脚本远程登录
 yum install -y expect      安装expect包
 
•  自动远程登录
cd  /usr/local/sbin/
vi 1.expect
#! /usr/bin/expect
#定义变量,远程登录机器的ip和密码
set host "192.168.233.129"
set passwd "1234"
#通过一种ssh方式登录机器
spawn ssh root@$host
#第一次远程ssh登录时会问是否建立连接,当遇到yes或no时,发送yes;遇到password时,发送$passwd(定义密码的变量值)
#\r表示回车
expect {
"yes/no" { send "yes\r"; exp_continue}
"password:" { send "$passwd\r" }
}
interact
#若没加interact,登录后会退出来,但expect命令还没结束
 
执行expect文件
chmod a+x 1.expect; ./1.expect
[root@xinlinux-03 sbin]# ./1.expect
spawn ssh [email protected]
[email protected]'s password:
Last login: Fri Oct 26 15:49:08 2018 from 192.168.233.150
[root@xinlinux-01 ~]#
 
 
退出远程机器的三种方式:
  • interact 表示停留在远程的机器上,不需要退出;
  • expect eof  表示暂停一段时间,再退出来
  • exit 表示直接退出
 
 
20.29 expect脚本远程执行命令
•  自动远程登录后,执行命令并退出
vi 2.expect
#!/usr/bin/expect
#定义user和password的变量
set user "root"
set passwd "1234"
#通过另一种ssh方式登录机器
spawn ssh [email protected]
expect {
"yes/no" { send "yes\r"; exp_continue}
"password:" { send "$passwd\r" }
}
#普通用户登录后是]$,root用户登陆后是]#,"]*"通配,不管是普通用户还是root用户,遇到"]*"就先后执行touch、echo、exit命令
expect "]*"
send "touch /tmp/12.txt\r"
expect "]*"
send "echo 1212 > /tmp/12.txt\r"
expect "]*"
send "exit\r"
 
执行expect文件
chmod a+x 2.expect; ./2.expect
[root@xinlinux-03 sbin]# ./2.expect
spawn ssh [email protected]
[email protected]'s password:
Last login: Fri Oct 26 15:50:55 2018 from 192.168.233.150
[root@xinlinux-01 ~]# touch /tmp/12.txt
[root@xinlinux-01 ~]# echo 1212 > /tmp/12.txt
[root@xinlinux-01 ~]# [root@xinlinux-03 sbin]#
 
检查是否实验成功
./1.expect
ls -l /tmp/12.txt
cat /tmp/12.txt
[root@xinlinux-03 sbin]# ./1.expect
spawn ssh [email protected]
[email protected]'s password:
Last login: Fri Oct 26 15:51:58 2018 from 192.168.233.150
[root@xinlinux-01 ~]# ls -l /tmp/12.txt
-rw-r--r-- 1 root root 5 10月 26 15:51 /tmp/12.txt
[root@xinlinux-01 ~]# cat /tmp/12.txt
1212
 
 
20.30 expect脚本传递参数
•  传递参数(就是设置内置变量)
vi 3.expect
#!/usr/bin/expect
#set定义内置变量和变量
#[lindex $argv 0]表示第一个参数,user是用户
set user [lindex $argv 0]
#[lindex $argv 1]表示第二个参数,host是ip地址
set host [lindex $argv 1]
set passwd "1234"
#[lindex $argv 2]表示第三个参数,cm表示的是命令
set cm [lindex $argv 2]
spawn ssh $user@$host
expect {
"yes/no" { send "yes\r"}
"password:" { send "$passwd\r" }
}
#$cm表示输入命令
expect "]*"
send "$cm\r"
#expect有默认超时时间(是10秒),可以设定超时时间,这里timeout是10秒
set timeout 10
expect "]*"
send "exit\r"
 
 
执行expect文件
chmod a+x 3.expect
./3.expect  root 192.168.233.129 ls
#登录机器执行ls命令(执行单条命令)
[root@xinlinux-03 sbin]# ./3.expect  root 192.168.233.129 ls
spawn ssh [email protected]
[email protected]'s password:
Last login: Fri Oct 26 16:06:36 2018 from 192.168.233.150
[root@xinlinux-01 ~]# ls
1  1.txt  2_heard.txt  2.txt  anaconda-ks.cfg  test  yum.log
[root@xinlinux-01 ~]# [root@xinlinux-03 sbin]#
 
./3.expect  root 192.168.233.129  "ls;vmstat 1 1"
#登录机器执行ls、vmstat命令(执行多条命令)
 
#如果expect的终端结束expect,那远程登录的expect命令也会结束
 
 
20.31 expect脚本同步文件
• 自动同步文件
vi 4.expect
#!/usr/bin/expect
set passwd "1234"
#通过rsync方式登录同步文件
spawn rsync -av [email protected]:/tmp/12.txt /tmp/
expect {
"yes/no" { send "yes\r"}
"password:" { send "$passwd\r" }
}
#同步文件时设置time out是行不通的
expect eof
 
执行expect文件
chmod a+x 4.expect; ./4.expect
[root@xinlinux-03 sbin]# chmod a+x 4.expect; ./4.expect
spawn rsync -av [email protected]:/tmp/12.txt /tmp/
[email protected]'s password:
receiving incremental file list
12.txt
 
sent 43 bytes  received 97 bytes  280.00 bytes/sec
total size is 5  speedup is 0.04
 
 
20.32 expect脚本指定host和要同步的文件
• 指定host和要同步的文件(一次只能同步一个文件)
vi 5.expect
#!/usr/bin/expect
set passwd "1234"
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
##注意,file要写绝对路径
 
执行expect文件
chmod a+x 5.expect
./5.expect 192.168.233.129  "/tmp/12.txt"
[root@xinlinux-03 sbin]# ./5.expect 192.168.233.129  "/tmp/12.txt"
spawn rsync -av /tmp/12.txt [email protected]:/tmp/12.txt
[email protected]'s password:
sending incremental file list
 
sent 45 bytes  received 12 bytes  38.00 bytes/sec
total size is 5  speedup is 0.09
 
 
20.33 构建文件分发系统
• 需求背景
对于大公司而言,肯定时不时会有网站或者配置文件更新,而且使用的机器肯定也是好多台,少则几台,多则几十甚至上百台。所以,自动同步文件是至关重要的。
• 实现思路
首先要有一台模板机器,把要分发的文件准备好,然后只要使用expect脚本批量把需要同步的文件分发到目标机器即可。
• 核心命令
rsync -av --files-from=list.txt  /  root@host:/
#list.txt文件列表,将要同步的大量文件写入到这里面;
#list.txt的路径要用绝对路径
 
• 文件分发系统的实现
• rsync.expect 内容
vi  rsync.expect
#!/usr/bin/expect
set passwd "1234"
set host [lindex $argv 0]
set file [lindex $argv 1]
#如果不能保证同步机器上有相对应文件的路径,可在rsync处加上-R参数
spawn rsync -avR --files-from=$file / root@$host:/
expect {
"yes/no" { send "yes\r"}
"password:" { send "$passwd\r" }
}
expect eof
 
•创建文件列表文件file.list
#同步时要保证传输文件的路径在同步机器上有相同的路径,例如同步/tmp/12.txt,那同步机器上要有/tmp/目录
vi /tmp/file.list
例如:
/tmp/12.txt
/root/shell/1.sh
 
• ip.list内容(写远程同步机器ip)
vi /tmp/ip.list
192.168.233.129
192.168.233.132
......
#可用密钥认证,这样避免每台机器都要输入密码
 
 
• rsync.sh 内容
#将需要同步机器的ip进行分发同步文件
vi rsync.sh
#!/bin/bash
for ip in `cat ip.list`
do
    echo $ip
    ./rsync.expect $ip /tmp/file.list
done
 
•开始执行分发文件
chmod a+x  rsync.expect
sh   rsync.sh
 
 
 
20.34 批量远程执行命令
使用场景:同步完完文件后可能需要重启一些服务
 
• exe.expect 内容
vi exe.expect
#!/usr/bin/expect
#host作为第一个参数
set host [lindex $argv 0]
set passwd "1234"
#执行的命令作为第二个参数
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 内容(执行同步机器的执行命令)
vi exe.sh
#!/bin/bash
for ip in `cat /tmp/ip.list`
do
    echo $ip
    ./exe.expect $ip "hostname"
done
 
•开始执行
chmod a+x exe.expect
sh exe.sh
 
 
20.35 扩展
 
给你提供一本电子书链接: http://pan.baidu.com/s/1mg49Taw  密码:yk4b
 
 
20.35课堂笔记
一、shell中的变量
$#,表示参数个数
 
 
二、if判断
判断表达式格式:
1、比较字符时,只能用等于号,不能用-eq;例如: a='abc' ;  if [ $a == "abc" ];then echo ok;fi
 
2、比较数字时,要用-eq,如果用等号去比较,则会把数字当做字符串去比较;例如: a=10;if [ $a -eq 10 ];then echo ok;fi
 
3、写多个条件时,条件之间要用-o隔开    [ $a -eq 10 -o $b -lt  10 ]
或者使用|| 或&&时,多个条件之间要用多个中括号[ ]括起来      [ $a -eq 10 ] || [ $b -lt  10 ]
 
4、 if [ #a -gt 10 ]  可以写成  if((a>10))
 
 
三、select用法
#一般与case一起用
select也是循环的一种,它比较适合 用在用户选择的情况下
比如,我们有一个这样的需求,运行脚本后,让用户去选择数字,选择1,会运行w命令,选择2运行top命令,选择3运行free命令,选择4退出。脚本这样实现:
#!/bin/bash
echo "Please chose a number, 1: run w, 2: run top, 3: run free, 4: quit"
echo
select command in w top free quit
do
    case $command in
    w)
        w
       ;;
    top)
        top
        ;;
     free)
         free
         ;;
     quit)
        exit
         ;;
    *)
        echo "Please input a number:(1-4)."
         ;;
     esac
 done
执行结果如下:
sh select.sh
Please chose a number, 1: run w, 2: run top, 3: run free, 4: quit
 
1) w
2) top
3) free
4) quit
#? 1
16:03:40 up 32 days,  2:42,  1 user,  load average: 0.01, 0.08, 0.08
USER     TTY      FROM              LOGIN@   IDLE   JCPU   PCPU WHAT
root     pts/0    61.135.172.68    15:33    0.00s  0.02s  0.00s sh select.sh
 
#? 3
             total       used       free     shared    buffers     cached
Mem:       1020328     943736      76592          0      86840     263624
-/+ buffers/cache:     593272     427056
Swap:      2097144      44196    2052948
#?
 
我们发现,select会默认把序号对应的命令列出来,每次输入一个数字,则会执行相应的命令,命令执行完后并不会退出脚本。它还会继续让我们再次输如序号。序号前面的提示符,我们也是可以修改的,利用变量PS3即可,再次修改脚本如下:
 #!/bin/bash
 PS3="Please select a number: "
 echo "Please chose a number, 1: run w, 2: run top, 3: run free, 4: quit"
 echo
 select command in w top free quit
 do
     case $command in
     w)
         w
         ;;
     top)
        top
         ;;
     free)
         free
         ;;
     quit)
         exit
         ;;
     *)
         echo "Please input a number:(1-4)."
     esac
 done
如果想要脚本每次输入一个序号后就自动退出,则需要再次更改脚本如下:
 #!/bin/bash
 PS3="Please select a number: "
 echo "Please chose a number, 1: run w, 2: run top, 3: run free, 4: quit"
 echo
 select command in w top free quit
 do
     case $command in
    w)
         w;exit
         ;;
     top)
         top;exit
         ;;
     free)
         free;exit
         ;;
     quit)
         exit
         ;;
    *)
         echo "Please input a number:(1-4).";exit
     esac
 done
 
 
四、for循环
#for循环是以空格作为分隔符,因此文件名或内容中有空格的要注意,可以改用while循环
 
#如果要for循环文件内容(内容含有空格),应该用 cat tmp.txt  |while read lne;do  echo  $line;done
 
 
五、while循环
#while ture 和while:都是表示死循环
 

猜你喜欢

转载自www.cnblogs.com/Lucky-LGX/p/9859965.html