功能:
-
能够传输文件到大量机器;
-
能够远程执行命令不须要输入密码;
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 root@192.168.233.129
root@192.168.233.129's password:
Last login: Fri Oct 26 15:49:08 2018 from 192.168.233.150
[root@xinlinux-01 ~]#
退出远程机器的三种方式:
20.29 expect脚本远程执行命令
• 自动远程登陆后,执行命令并退出
vi 2.expect
#!/usr/bin/expect
#定义user和password的变量
set user "root"
set passwd "1234"
#经过另外一种ssh方式登陆机器
spawn ssh $user@192.168.233.129
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 root@192.168.233.129
root@192.168.233.129'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 root@192.168.233.129
root@192.168.233.129'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 root@192.168.233.129
root@192.168.233.129'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 root@192.168.233.129:/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 root@192.168.233.129:/tmp/12.txt /tmp/
root@192.168.233.129'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 root@192.168.233.129:/tmp/12.txt
root@192.168.233.129'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 扩展
20.35课堂笔记
1、shell中的变量
$#,表示参数个数
2、if判断
判断表达式格式:
一、比较字符时,只能用等于号,不能用-eq;例如:
a='abc' ; if [ $a == "abc" ];then echo ok;fi
二、比较数字时,要用-eq,若是用等号去比较,则会把数字当作字符串去比较;例如:
a=10;if [ $a -eq 10 ];then echo ok;fi
三、写多个条件时,条件之间要用-o隔开
[ $a -eq 10 -o $b -lt 10 ]
或者使用|| 或&&时,多个条件之间要用多个中括号[ ]括起来
[ $a -eq 10 ] || [ $b -lt 10 ]
四、
if [ #a -gt 10 ] 能够写成
if((a>10))
3、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
4、for循环
#for循环是以空格做为分隔符,所以文件名或内容中有空格的要注意,能够改用while循环
#若是要for循环文件内容(内容含有空格),应该用
cat tmp.txt |while read lne;do echo $line;done
5、while循环
#while ture 和while:都是表示死循环