功能:
-
能夠傳輸文件到大量機器;
-
能夠遠程執行命令不須要輸入密碼;
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:都是表示死循環