本節所講內容:
- 23.1 expect實現無交互登錄
- 23.2 正則表達式
- 23.3 sed流編輯器
- 23.4 cut命令
- 23.5 實戰-bash腳本語法檢查和查看詳細的執行過程
23.1 expect實現無交互登錄
expect ([ɪkˈspekt] 期待 )是從它發展出來的。如果你想要寫一個能夠自動處理輸入輸出的腳本(如向用戶提問並且驗證密碼)又不想面對C或者Perl,那麼expect是你的最好的選擇。它可以用來做一些linux下無法做到交互的一些命令操作
23.1.1 安裝和使用expect
[root@xuegod63 ~]# yum -y install expect
使用expect創建腳本的方法
1)定義腳本執行的shell
#!/usr/bin/expect
這裏定義的是expect可執行文件的鏈接路徑(或真實路徑),功能類似於bash等shell功能
2)set timeout 30
設置超時時間,單位是秒,如果設爲timeout -1 意爲永不超時
3)spawn
spawn 是進入expect環境後才能執行的內部命令,如果沒有裝expect或者直接在默認的SHELL下執行是找不到spawn命令的。不能直接在默認的shell環境中進行執行主要功能,它主要的功能是給ssh運行進程加個殼,用來傳遞交互指令。
4)expect
這裏的expect同樣是expect的內部命令
主要功能:判斷輸出結果是否包含某項字符串,沒有則立即返回,否則就等待一段時間後返回,等待時間通過timeout進行設置
5)send
執行交互動作,將交互要執行的動作進行輸入給交互指令
命令字符串結尾要加上"\r",如果出現異常等待的狀態可以進行覈查
6)exp_continue
繼續執行接下來的交互操作
7)interact
執行完後保持交互狀態,把控制權交給控制檯;如果不加這一項,交互完成會自動退出
8)$argv
expect 腳本可以接受從bash傳遞過來的參數,可以使用 [lindex $argv n]獲得,n從0開始,分別表示第一個,第二個,第三個……參數
例1:免密碼通過SSH登錄服務器(瞭解) 這裏不是用密鑰
注:運行腳本時,要把#號後面的註釋刪除,不然無法運行
[root@xuegod63 ~]# cat ssh.exp
#!/usr/bin/expect
set ipaddr "192.168.1.63"
set name "root"
set passwd "123456"
set timeout 30 #設置超時時間,單位是秒;expect超時等待的時間。默認timeout爲10s。
spawn ssh $name@$ipaddr # spawn是進入expect環境後纔可以執行的expect內部命令,如果沒有裝expect或者直接在shell下執行是找不到spawn命令的。這個就好比cd是shell的內建命令,離開shell,就無法執行cd一樣。 它主要的功能是給ssh運行進程加個殼,用來傳遞交互指令。
expect {
"yes/no" { send "yes\r";exp_continue }
"password" { send "$passwd\r" } #執行交互動作,與手工輸入密碼的動作等效。
}
expect "#" #判斷上次輸出結果裏是否包含“password:”的字符串,如果有則立即返回,向下執行;否則就一直等待,直到超時時間到
send "touch /root/xuegod1011.txt\r"
send "ls /etc > /root/xuegod1011.txt\r"
send "mkdir /tmp/xuegod1011\r"
send "exit\r"
expect eof #執行完成上述命令後,退出Expect,把控制權交給控制檯,變回手工操作
[root@xuegod63 ~]# expect ssh.exp #開始執行
例2:對服務器批量管理(瞭解一下)
[root@xuegod63 ~]# cat ip_pass.txt #這裏寫上要執行的IP地址和root用戶密碼
192.168.1.63 123456
192.168.1.63 123456
192.168.1.63 123456
[root@xuegod63 ~]# cat ssh2.exp #編寫要執行的操作
#!/usr/bin/expect
set ipaddr [lindex $argv 0]
set passwd [lindex $argv 1]
set timeout 30
spawn ssh root@$ipaddr
expect {
"yes/no" { send "yes\r";exp_continue }
"password" { send "$passwd\r" }
}
expect "#"
send "touch /root/xuegod1011.txt\r"
send "ls /etc > /root/xuegod1011.txt\r"
send "mkdir /tmp/xuegod1011\r"
send "exit\r"
expect eof
[root@xuegod63 ~]# cat login.sh #開始執行
#!/bin/bash
echo
for ip in `awk '{print $1}' /root/ip_pass.txt`
do
pass=`grep $ip /root/ip_pass.txt|awk '{print $2}'`
expect /root/ssh.exp $ip $pass
done
Linux架構師高薪入口:
1.學神IT教育官方網站: http://xuegod.ke.qq.com
2.10年行業資深老鳥MK:QQ2659153446
3.加入Linux技術交流QQ羣:722287089,即可獲得以下福利:
①定期分享免費學習資料與視頻(工具+筆記+拓展實戰)
②10年行業資深老鳥在線答疑:技能+實戰+項目分享+高薪就業
③有機會免費領取Linux雲計算集羣架構師4冊書籍
23.2 正則表達式的使用
正則表達式,又稱規則表達式。(英語:Regular Expression [ˈreɡjulə] 規則的 [ iksˈpreʃən] 表達 ),在代碼中常簡寫爲regex、regexp或RE),計算機科學的一個概念。正則表達式通常被用來檢索、替換那些符合某個模式(規則)的文本。
正則表達式不只有一種,而且LINUX中不同的程序可能會使用不同的正則表達式,如:
工具:grep sed awk
LINUX中常用的有兩種正則表達式引擎
基礎正則表達式:BRE
擴展正則表達式: ERE
23.2.1 Shell正則表達式的組成
基礎正則表達式
特別字符 描述
$ 匹配輸入字符串的結尾位置。要匹配 $ 字符本身,請使用 \$
( ) 標記一個子表達式的開始和結束位置。要匹配這些字符,請使用 \( 和 \)
* 匹配前面的子表達式零次或多次。要匹配 * 字符,請使用 \*
+ 匹配前面的子表達式一次或多次。要匹配 + 字符,請使用 \+
. 匹配除換行符 \n 之外的任何單字符。要匹配 . ,請使用 \.
[ 標記一箇中括號表達式的開始。要匹配 [,請使用 \[
? 匹配前面的子表達式零次或一次,或指明一個非貪婪限定符。要匹配 ? 字符,請使用 \?
\ 將下一個字符標記爲或特殊字符、或原義字符、或向後引用、或八進制轉義符。例如, 'n' 匹配字符 'n'。'\n' 匹配換行符。序列 '\\' 匹配 "\",而 '\(' 則匹配 "("
^ 匹配輸入字符串的開始位置,除非在方括號表達式中使用,此時它表示不接受該字符集合。要匹配 ^ 字符本身,請使用 \^
{ 標記限定符表達式的開始。要匹配 {,請使用 \{
| 指明兩項之間的一個選擇。要匹配 |,請使用 \| 如: Y | y
定位符
^ 匹配輸入字符串開始的位置
$ 匹配輸入字符串結尾的位置
非打印字符
\n 匹配一個換行符
\r 匹配一個回車符
\t 匹配一個製表符
例:統計/etc/ssh/sshd_config文件中除去空行和#號開頭的行的行數
[root@xuegod63 ~]# grep -v "^$\|^#" /etc/ssh/sshd_config #使用基礎正則表達式
[root@xuegod63 ~]# grep -E -v "^$|^#" /etc/ssh/sshd_config #擴展正則表達式
[root@xuegod63 ~]# egrep -v "^$|^#" /etc/ssh/sshd_config #擴展正則表達式
例2:點字符
[root@xuegod63 ~]# grep .ot /etc/passwd #查找passwd文件包括.ot 的字符
root:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/root:/sbin/nologin
setroubleshoot:x:993:990::/var/lib/setroubleshoot:/sbin/nologin
23.3 sed流編輯器
23.3.1 sed strem editor 流編輯器
-
sed編輯器是一行一行的處理文件內容的。正在處理的內容存放在模式空間(緩衝區)內,處理完成後按照選項的規定進行輸出或文件的修改。
-
接着處理下一行,這樣不斷重複,直到文件末尾。文件內容並沒有改變,除非你使用重定向存儲輸出。Sed主要用來自動編輯一個或多個文件;簡化對文件的反覆操作;
sed也是支持正則表達式的,如果要使用擴展正則加參數-r
sed的執行過程:
1、 一次讀取一行數據
2、 根據我們提供的規則來匹配相關的數據,比如查找root。
3、 按照命令修改數據流中的數據,比如替換
4、 將結果進行輸出
5、 重複上面四步
23.3.2 如何使用
語法格式:sed [options] ‘[commands]’ filename
例1:
[root@xuegod63 ~]# echo "this is aplle" | sed 's/aplle/dog/'
this is dog
[root@xuegod63 ~]# echo "this is aplle" > a.txt
[root@xuegod63 ~]# sed 's/apple/dog/' a.txt
this is aplle
[root@xuegod63 ~]# cat a.txt #發現並沒有修改文件
this is aplle
23.3.3 sed選項|參數
options:
-a 在當前行下面插入文件
-n 讀取下一個輸入行,用下一個命令處理新的行而不是用第一個命令
-e 執行多個sed指令
-f 運行腳本
-i 編輯文件內容 ***
-i.bak 編輯的同時創造.bak的備份
-r 使用擴展的正則表達式
命令:
i 在當前行上面插入文件
c 把選定的行改爲新的指定的文本
p 打印 ***
d 刪除 ***
r/R 讀取文件/一行
w 另存
s 查找
y 替換
h 拷貝模板塊的內容到內存中的緩衝區。
H 追加模板塊的內容到內存中的緩衝區。
g 獲得內存緩衝區的內容,並替代當前模板塊中的文本。
G 獲得內存緩衝區的內容,並追加到當前模板塊文本的後面
D 刪除\n之前的內容
P 打印\n之前的內容
替換標記:
數字:表明新文本將替換第幾處模式匹配的地方
g:表示新文本將會替換所有匹配的文本
\1:子串匹配標記,前面搜索可以用元字符集\(..\),
&:保留搜索到的字符用來替換其它字符
sed匹配字符集
^ 匹配行開始,如:/^sed/匹配所有以sed開頭的行。
$ 匹配行結束,如:/sed$/匹配所有以sed結尾的行。
. 匹配一個非換行符的任意字符,如:/s.d/匹配s後接一個任意字符,最後是d。
* 匹配0個或多個字符,如:/*sed/匹配所有模板是一個或多個空格後緊跟sed的行。
例1:s 只替換第一個匹配到的字符,將passwd中的root用戶替換成xuegod
[root@xuegod63 ~]# sed 's/root/xuegod/' /etc/passwd
xuegod:x:0:0:root:/root:/bin/bash #發現只替換了第一個匹配的root,後面的沒有替換
bin:x:1:1:bin:/bin:/sbin/nologin
例2:全面替換標記g
[root@xuegod63 ~]# sed 's/root/xuegod/g' /etc/passwd |more
xuegod:x:0:0:xuegod:/xuegod:/bin/bash #全部替換了
例2: 將sed中默認的/ 定界符改成#號
[root@xuegod63 ~]# sed 's#/bin/bash#/sbin/nologin#' /etc/passwd | more
root:x:0:0:root:/root:/sbin/nologin
bin:x:1:1:bin:/bin:/sbin/nologin
以/來做定界符:
[root@xuegod63 ~]# sed 's/\/bin\/bash/\/sbin\/nologin/' /etc/passwd
(2)按行查找替換
寫法如下:
用數字表示行範圍;$表示行尾
用文本模式配置來過濾
例1:單行替換,將第2行中bin替換成xuegod
[root@xuegod63 ~]# sed '2s/bin/xuegod/' /etc/passwd | more
root:x:0:0:root:/root:/bin/bash
xuegod:x:1:1:bin:/bin:/sbin/nologin
例2:多行替換,如果涉及到多行處理,用逗號表示行間隔。 將第3行到最行尾中bin替換成xuegod
[root@xuegod63 ~]# sed '2,$s/bin/xuegod/' /etc/passwd | more
root:x:0:0:root:/root:/bin/bash
xuegod:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sxuegod:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sxuegod/nologin
(3)d 刪除第2行到第4行的內容
[root@xuegod63 ~]# cat /etc/hosts
127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4
::1 localhost localhost.localdomain localhost6 localhost6.localdomain6
192.168.1.63 xuegod63.cn
192.168.1.64 xuegod64.cn
192.168.1.62 xuegod62.cn
[root@xuegod63 ~]# sed '2,4d' /etc/hosts
127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4
192.168.1.62 xuegod62.cn
[root@xuegod63 ~]# sed '/192.168/d' /etc/hosts #將包括192.168的行刪除
127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4
::1 localhost localhost.localdomain localhost6 localhost6.localdomain6
(4)添加行
命令i(insert插入),在當前行前面插入一行 i\
命令a(append附加),在當前行後面添加一行 a\
例1:插入
[root@xuegod63 ~]# echo "hello world" | sed 'i\ xuegod '
xuegod
hello world
例2:追加
[root@xuegod63 ~]# echo "hello world"|sed 'a\xuegod'
hello world
xuegod
例3:在文件最後追加內容
[root@xuegod63 ~]# sed '$a\192.168.1.65 xuegod65.cn' /etc/hosts
127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4
::1 localhost localhost.localdomain localhost6 localhost6.localdomain6
192.168.1.63 xuegod63.cn
192.168.1.64 xuegod64.cn
192.168.1.62 xuegod62.cn
192.168.1.65 xuegod65.cn
例4:在文件中第2行之後,開始追加內容
[root@xuegod63 ~]# sed '2a\192.168.1.65 xuegod65.cn' /etc/hosts
127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4
::1 localhost localhost.localdomain localhost6 localhost6.localdomain6
192.168.1.65 xuegod65.cn
192.168.1.63 xuegod63.cn
192.168.1.64 xuegod64.cn
192.168.1.62 xuegod62.cn
例5:在文件中第2行到第4行之後分別追加內容
[root@xuegod63 ~]# sed '2,4a\hello world' word1.txt
[root@xuegod63 ~]# sed '2,4a\192.168.1.65 xuegod65.cn' /etc/hosts
127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4
::1 localhost localhost.localdomain localhost6 localhost6.localdomain6
192.168.1.65 xuegod65.cn
192.168.1.63 xuegod63.cn
192.168.1.65 xuegod65.cn
192.168.1.64 xuegod64.cn
192.168.1.65 xuegod65.cn
192.168.1.62 xuegod62.cn
*(5)修改行命令c (change) c*
例1:將第4行內容改成192.168.1.65 xuegod65.cn
[root@xuegod63 ~]# cat /etc/hosts
127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4
::1 localhost localhost.localdomain localhost6 localhost6.localdomain6
192.168.1.63 xuegod63.cn
192.168.1.64 xuegod64.cn
192.168.1.62 xuegod62.cn
[root@xuegod63 ~]# sed '4c\192.168.1.65 xuegod65.cn' /etc/hosts
例2:將第2行到最後全部修改成192.168.1.65 xuegod65.cn
[root@xuegod63 ~]# sed '2,$c\192.168.1.65 xuegod65.cn' /etc/hosts
127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4
192.168.1.65 xuegod65.cn
例3:將包括192.168.1.64行的內容修改成192.168.1.65
[root@xuegod63 ~]# sed '/192.168.1.64/c\192.168.1.65' /etc/hosts
127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4
::1 localhost localhost.localdomain localhost6 localhost6.localdomain6
192.168.1.63 xuegod63.cn
192.168.1.65
192.168.1.62 xuegod62.cn
(6)打印,直接輸入文件中的內容
例1:輸入第2行內容
[root@xuegod63 ~]# sed -n '2p' /etc/hosts
::1 localhost localhost.localdomain localhost6 localhost6.localdomain6
(7)將修改或過濾出來的內容保存到另一個文件中
例2:將passwd中的包括root字樣的行保存到 c.txt 中
[root@xuegod63 ~]# sed -n '/root/w c.txt' /etc/passwd
[root@xuegod63 ~]# cat c.txt
root:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/root:/sbin/nologin
(8)-i 對原文件修改,保存( 必會 ) 使用場景: 替換或修改服務器配置文件
[root@xuegod63 ~]# cp /etc/passwd /opt/
[root@xuegod63 ~]# sed -i 's/root/xuegod/' /etc/passwd
[root@xuegod63 ~]# head -n 1 /etc/passwd
xuegod:x:0:0:root:/root:/bin/bash
修改IP地址爲192.168.1.65
[root@xuegod63 ~]# sed -i 's/IPADDR=192.168.1.63/IPADDR=192.168.1.65/' /etc/sysconfig/network-scripts/ifcfg-ens33
Linux架構師高薪入口:
1.學神IT教育官方網站: http://xuegod.ke.qq.com
2.10年行業資深老鳥MK:QQ2659153446
3.加入Linux技術交流QQ羣:722287089,即可獲得以下福利:
①定期分享免費學習資料與視頻(工具+筆記+拓展實戰)
②10年行業資深老鳥在線答疑:技能+實戰+項目分享+高薪就業
③有機會免費領取Linux雲計算集羣架構師4冊書籍
微信公衆號:
MK老師微信號:
23.4 cut命令
23.4.1 cut常用參數
cut命令用來顯示行中的指定部分,刪除文件中指定字段。
- 說明:該命令有兩項功能,其一是用來顯示文件的內容,它依次讀取由參數file所指明的文件,將它們的內容輸出到標準輸出上;其二是連接兩個或多個文件,如cut
fl f2 > f3將把文件fl和fn的內容合併起來,然後通過輸出重定向符“>”的作用,將它們放入文件f3中。
語法: cut(選項)(參數)
選項
-b:僅顯示行中指定範圍的字節數;
-c:僅顯示行中指定範圍的字符;
-d:指定字段的分隔符,默認的字段分隔符爲“TAB”;
-f:顯示指定字段的內容;
例1:輸出系統中所有用戶名
使用 -f 選項提取指定字段,使用 -d 選項指定字段分隔符,這裏以:冒號做分隔
[root@xuegod63 ~]# cut -f1 -d ":" /etc/passwd
23.4.2 cut命令可以將一串字符作爲列來顯示,字符字段的記法:
N-:從第N個字節、字符、字段到結尾;
N-M:從第N個字節、字符、字段到第M個(包括M在內)字節、字符、字段;
-M:從第1個字節、字符、字段到第M個(包括M在內)字節、字符、字段。
上面是記法,結合下面選項將摸個範圍的字節、字符指定爲字段:
-b 表示字節;
-c 表示字符;
-f 表示定義字段。
示例
例1:打印第1個到第3個字符:
[root@xuegod63 ~]# cut -c1-3 /etc/passwd
例2:打印前2個字符:
[root@xuegod63 ~]# cut -c-2 /etc/passwd
例3:打印從第5個字符開始到結尾:
[root@xuegod63 ~]# cut -c5- /etc/passwd
Linux架構師高薪入口:
1.學神IT教育官方網站: http://xuegod.ke.qq.com
2.10年行業資深老鳥MK:QQ2659153446
3.加入Linux技術交流QQ羣:722287089,即可獲得以下福利:
①定期分享免費學習資料與視頻(工具+筆記+拓展實戰)
②10年行業資深老鳥在線答疑:技能+實戰+項目分享+高薪就業
③有機會免費領取Linux雲計算集羣架構師4冊書籍
23.5 實戰-bash腳本語法檢查和查看詳細的執行過程
檢查語法是否有錯:
bash -v test.bash #查看bash是否存在語法錯誤
bash -x test.bash #查看bash詳細的執行過程
[root@xuegod63 ~]# cat a.sh
# Script to show debug of shell
#
tot=`expr $1 + $2`
secho $tot #這裏故意寫錯
[root@xuegod63 ~]# bash -v a.sh
# Script to show debug of shell
#
tot=`expr $1 + $2`
expr: 語法錯誤 #語法哪錯了? 運行時沒有給參數
secho $tot #這裏故意寫錯
a.sh:行4: secho: 未找到命令
[root@xuegod63 ~]# sed -i 's/secho/echo/' a.sh #修改正確後
[root@xuegod63 ~]# bash -x a.sh 2 3 #查看詳細執行過程。 注:這個腳本是真正執行一遍,不是預執行
++ expr 2 + 3
+ tot=5
+ echo 5
**例2:查看九九乘法表shell腳本運行過程**
[root@xuegod63 ~]# cat 99.sh
for i in `seq 9`
do
for j in `seq $i`
do
echo -n "$i*$j= `echo $(($i*$j))` "
done
echo " "
done
root@xuegod63 ~]# bash -x 99.sh
Linux架構師高薪入口:
1.學神IT教育官方網站: http://xuegod.ke.qq.com
2.10年行業資深老鳥MK:QQ2659153446
3.加入Linux技術交流QQ羣:722287089,即可獲得以下福利:
①定期分享免費學習資料與視頻(工具+筆記+拓展實戰)
②10年行業資深老鳥在線答疑:技能+實戰+項目分享+高薪就業
③有機會免費領取Linux雲計算集羣架構師4冊書籍
微信公衆號:
MK老師微信號:
總結:
- 23.1 expect實現無交互登錄
- 23.2 正則表達式
- 23.3 sed流編輯器
- 23.4 cut命令
- 23.5 實戰-bash腳本語法檢查和查看詳細的執行過程