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 扩展
shell多线程
http://blog.lishiming.net/?p=448
给你提供一本电子书链接:
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:都是表示死循环