Shell之免交互的實(shí)現(xiàn)
前言
免交互就是實(shí)現(xiàn)一個(gè)功能時(shí),不需要連續(xù)從鍵盤輸入信息,通過腳本或命令自動完成一些動作。
一、Here Document
1.Here Document概述
使用 I/O 重定向的方式將命令列表提供給交互式程序或命令,比如 ftp、cat或read命令。
HereDocument是標(biāo)準(zhǔn)輸入的一種替代品,可以幫助腳本開發(fā)人員不必使用臨時(shí)文件來構(gòu)建輸入信息,而是直接就地生產(chǎn)出一個(gè)文件并用作命令的標(biāo)準(zhǔn)輸入。
2.基本語法格式
命令 <<標(biāo)記
……
……
標(biāo)記#特殊字符“<<”在標(biāo)記和命令之前,這樣做的目的是將命令塊的輸出重定向到程序和命令的stdin。
#標(biāo)記的選擇要確保不會出現(xiàn)在其他地方,避免出現(xiàn)混淆;兩個(gè)標(biāo)記之間的內(nèi)容被當(dāng)做是一個(gè)文件并用作“命令”的標(biāo)準(zhǔn)輸入。
#另外Here Document也可以與非交互式程序和命令一起使用
四點(diǎn)注意事項(xiàng):
- 標(biāo)記可以使用任意的合法字符;
- 結(jié)尾的標(biāo)記一定要頂格寫,前面不能有任何字符;
- 結(jié)尾的標(biāo)記后面也不能有任何字符(包括空格);
- 開頭的標(biāo)記前后的空格會被省略
[root@c7-1 ~]# cat <<EOF ? //直接把輸入的從命令行輸出 > hello world > EOF hello world [root@c7-1 ~]# cat > name <<EOF ? //輸入保存到文件 > liuchun > zhougang > EOF [root@c7-1 ~]# cat name liuchun zhougang [root@c7-1 ~]# cat >> name <<EOF ? ?//追加輸入保存到文件 > liufei > EOF [root@c7-1 ~]# cat name? liuchun zhougang liufei
例:創(chuàng)建yum源
[root@c7-1 ~]# cat > test.repo <<EOF > [test] > name=test > baseurl=file:///mnt > enabled=1 > gpgcheck=0 > EOF 另外寫法1 cat <<EOF > local.repo 另外寫法2 tee test1.txt <<EOF
3.Here Documen免交互
3.1 通過 read 命令接收輸入并打印,輸入值是兩個(gè) EOF 標(biāo)記之間的部分,也就是“10”,這將作為變量 a 的值
[root@c7-1 ~]# read a <<EOF > 10 > EOF [root@c7-1 ~]# echo $a 10
3.2 通過 passwd 給用戶設(shè)置密碼
[root@c7-1 ~]# passwd zhangsan <<EOF > 123456 > 123456 > EOF 更改用戶 zhangsan 的密碼 。 新的 密碼:無效的密碼: 密碼少于 8 個(gè)字符 重新輸入新的 密碼:passwd:所有的身份驗(yàn)證令牌已經(jīng)成功更新。
4.變量設(shè)定(支持變量替換)
4.1 在寫入文件時(shí)要先將變量替換成實(shí)際值,在結(jié)合 cat 命令完成寫入
例1:
[root@localhost ~]# aa=$(cat <<EOF ? ?//變量替換 > $a > EOF > ) echo $aa
例2:
#!/bin/bash? doc_file="123.txt"? i="123" cat > $doc_file << EOF? Welcome to ?$i? EOF this is $i? cat 123.txt
4.2 整體賦值給一個(gè)變量,然后通過 echo 命令將變量值打印出來
#!/bin/bash ivar="Great! Beautyful!" myvar=$(cat <<EOF #將Here Document 整體賦值給變量 This is Line 1. That are Sun,Moon and Stars. $ivar #輸出時(shí)會進(jìn)行變量替換 EOF ) echo $myvar
5.格式控制
5.1 關(guān)閉變量替換的功能
[root@c7-1 ~]# aa=$(cat <<'EOF' ? ?//關(guān)閉變量替換 對標(biāo)記加單引號,即可關(guān)閉變量替換 20 $a EOF ) echo $aa #!/bin/bash cat <<'EOF'?? ??? ?//對標(biāo)記加單引號,即可關(guān)閉變量替換 This is Line 1. $kkk? EOF
5.2 去掉每行之前的 TAB 字符
在第一行的標(biāo)記前面加‘-’,這個(gè)表示要抑制各行首 TAB 的作用。
[root@c7-1 ~]# vim dome3.sh ? ?//寫一個(gè)腳本測試抑制tab鍵輸出 #!/bin/bash cat <<EOF ? ? ? ? hello world EOF cat <<-EOF?? ??? ??? ??? ?//加 - 去除tab ? ? ? ? hello world EOF [root@c7-1 ~]# bash tab.sh? ?? ?hello world hello world
6.多行注釋
Bash 的默認(rèn)注釋是“#”,該注釋方法只支持單行注釋,在 Shell 腳本的工作中,“#”右側(cè)的任何字符串,bash 都會將其忽略。Here Document 的引入解決了多行注釋的問題。
: 代表什么都不做的空命令。中間標(biāo)記區(qū)域的內(nèi)容不會被執(zhí)行,會被bash 忽略掉,因此可達(dá)到批量注釋的效果。
#!/bin/bash : <<-EOF //多行注釋 以 :開頭的Here Document標(biāo)記內(nèi)容不會被執(zhí)行 the second comment. test line. EOF echo "dashiji"
二、Expect
1.Expect概述
建立在tcl語言基礎(chǔ)上的一個(gè)工具,常被用于進(jìn)行自動化控制和測試,解決shell腳本中交互相關(guān)的問題
2.expect的基本安裝
expect是一個(gè)程序,所以他也是需要提前安裝才可以使用的
[root@c7-1 expect]# rpm -q expect [root@c7-1 expect]# rpm -q tcl [root@c7-1 expect]# yum install expect -y //安裝expect時(shí)會把tcl作為依賴包安裝
3.基本命令
(1)腳本解釋器
expect腳本中首先引入文件,表明使用的是哪一個(gè)shell #!/usr/bin/expect
(2)spawn
spawn后面通常跟一個(gè)Linux執(zhí)行命令,表示開啟一個(gè)會話、啟動進(jìn)程,并跟蹤后續(xù)交互信息。
例如:
spawn passwd root
(3)expect
判斷上次輸出結(jié)果中是否包含指定的字符串,如果有則立即返回,否則就等待超時(shí)時(shí)間后返回;
只能捕捉由spawn啟動的進(jìn)程的輸出;
用于接收命令執(zhí)行后的輸出,然后和期望的字符串匹配
(4)send向進(jìn)程發(fā)送字符串,用于模擬用戶的輸入;該命令不能自動回車換行,一般要加 \r (回車) 或者 \n
方式一: ?? ?expect "密碼"{ send "abc123\r" }?? ??? ?//同一行send部分要有{} 方式二: ?? ?expect "密碼" ?? ?send "abc123\r"?? ??? ??? ??? ??? ??? ?//換行send部分不需要有{} 方式三: ?? ?expect支持多個(gè)分支 ?? ?expect?? ??? ?//只要匹配了其中一個(gè)情況,執(zhí)行相應(yīng)的send語句后退出該expect語句 ?? ?"密碼1"{ send "abc123\r" } ?? ?"密碼2"{ send "123456\r" } ?? ?"密碼3"{ send "123123\r" }
(5)結(jié)束符
expect eof
表示交互結(jié)束,等待執(zhí)行結(jié)束,退回到原用戶,與spawn對應(yīng)。
比如切換到root用戶,expect腳本默認(rèn)的是等待10s,當(dāng)執(zhí)行完命令后,默認(rèn)停留10s后,自動切回了原用戶
interact
執(zhí)行完成后保持交互狀態(tài),把控制權(quán)交給控制臺,會停留在目標(biāo)終端而不會退回到原終端,這個(gè)時(shí)候就可以手工操作了,interact后的命令不起作用,比如interact后添加exit,并不會退出root用戶。而如果沒有interact則登錄完成后會退出,而不是留在遠(yuǎn)程終端上。
注意:expect eof 與 interact 只能二選一。
(6)set
expect 默認(rèn)的超時(shí)時(shí)間是10秒,通過 set命令可以設(shè)置會話超時(shí)時(shí)間,若不限制超時(shí)時(shí)間則應(yīng)設(shè)置為-1。
例:
set timeout 30
(7)exp_continue
附加于某個(gè)expect判斷項(xiàng)之后,可以使該項(xiàng)被匹配后,還能繼續(xù)匹配該expect-判斷語句內(nèi)的其他項(xiàng)。exp_continue類似于控制語句中的continue 語句。表示允許expect繼續(xù)向下執(zhí)行指令。
例如:下例將判斷交互輸出中是否存在yes/no 或*password。如果匹配 yes/no 則輸出 yes并再次執(zhí)行判斷;
如果匹配*password則輸出abc123并結(jié)束該段expect語句。
expect{ ?? ?"(yes/no)" ?? ?{ send "yes\r";exp_continue;} ?? ?"*password" ?? ?{ set timeout 300;send "abc123\r";} } #注意:使用exp continue時(shí),如果跟蹤像passwd這樣的輸入密碼后就結(jié)束進(jìn)程的命令,expect{}外不要再加上expect eof #因?yàn)閟pawn進(jìn)程結(jié)束后會默認(rèn)向expect發(fā)送eof,會導(dǎo)致后面的expect eof執(zhí)行報(bào)錯(cuò) #注:表示允許用戶進(jìn)行交互操作,一直保持回話連接
(8)send user
send user 表示回顯命令,相當(dāng)于echo
(9)接收參數(shù)
expect腳本可以接受從bash命令行傳遞的參數(shù),使用[lindex $argvn]獲得。
其中n從o開始,分別表示第一個(gè),第二個(gè),第三個(gè)..參數(shù)。例:
set hostname [ lindex $argy 0 ]
相當(dāng)于hostname=$1
set password [ lindex $argy 1 ]
相當(dāng)于password=$2
4.用expect編寫腳本
4.1 ssh無交互登錄到遠(yuǎn)程服務(wù)器
[root@c7-1 expect]# vim dome1.sh? #!/usr/bin/expect?? ??? ??? ??? ?//這里需要用expect自己的解釋器,注意不要寫成bash否則無法識別 spawn ssh root@192.168.3.100?? ?//開啟一個(gè)程序,這個(gè)程序是ssh遠(yuǎn)程登錄?? ??? ??? ? expect {?? ??? ??? ??? ??? ??? ?//捕獲內(nèi)容,當(dāng)出現(xiàn)password的時(shí)候,就會向程序發(fā)送密碼,默認(rèn)是不換行的,所以需要\r回車換行,多個(gè)條件需要花括號括起來,注意格式問題! ? ? ? ? "password" ? ? ? ? { send "123\r"; }?? ??? ? } interact
4.2 如果想要在對方服務(wù)器上進(jìn)行一下操作后再退出可執(zhí)行以下腳本
[root@c7-1 ~]# vim expect.sh #!/usr/bin/expect spawn ssh root@192.168.3.100 expect { ? ? ? ? "password:" ? ? ? ? { send "123456\r"; } } expect "#" ? ? ? //當(dāng)捕獲到#的時(shí)候 send "ls\r" ? ?//執(zhí)行l(wèi)s命令 send "ifconfig ens33\r" ? //執(zhí)行ifconfig ens33命令 send "exit\r" ? //執(zhí)行完exit退出登陸 expect eof ? ?//不需要進(jìn)行交互了,意味著結(jié)束expect程序,如果不寫的話不會執(zhí)行操作直接退出;如果不寫,寫interact也無法在對方機(jī)器上執(zhí)行命令,eof可以替換
4.3 定義和引用變量
用set關(guān)鍵字定義變量,變量名和變量的值中間用空格分開,其他用法與shell腳本一致
#!/usr/bin/expect set user root set ip 192.168.3.100 set pass 123456 #引用位置變量 #!/usr/bin/expect set user root set ip [lindex $argv 0] ? ?//設(shè)置第一個(gè)位置變量為ip set pass [lindex $argv 1] ? //設(shè)置第二個(gè)位置變量為登陸密碼 spawn ssh $user@$ip expect { ? ? ? ? "password:" ? ? ? ? { send "$pass\r"; } } expect "#" send "ls\r" send "ifconfig ens33\r" send "exit\r" expect eof [root@c7-1 ~]# ./expect sh 192.168.3.100 123456 ? //執(zhí)行時(shí)需要加位置變量 #####還可以定義其他參數(shù),例如超時(shí)時(shí)間,日志等 #超時(shí)時(shí)間 set timeout 20 ? //登陸超時(shí)多少秒退出 #開啟日志文件 log_file test.log ? //日志記錄操作 #顯示信息 log_user 1 ? //1為屏幕輸出信息,0為不輸出
4.4 在shell腳本中調(diào)用expect
#!/bin/bash username=$1 useradd $username /usr/bin/expect <<-EOF spawn passwd $username expect { ?? ??? ?"新的 密碼" ? ? //注意:獲取的內(nèi)容和發(fā)送的內(nèi)容不能在同一行否則執(zhí)行不成功 ?? ??? ?{send "123456\r";exp_continue} ?? ??? ? ?? ??? ?"重新輸入新的 密碼" ?? ??? ?{send "123456\r";} } EOF 驗(yàn)證結(jié)果: [root@c7-1 ~]# ./user.sh wangwu spawn passwd wangwu 更改用戶 wangwu 的密碼 。 新的 密碼: 無效的密碼: 密碼少于 8 個(gè)字符 重新輸入新的 密碼: passwd:所有的身份驗(yàn)證令牌已經(jīng)成功更新。
總結(jié)
借助 expect 處理交互的命令,可以將交互過程如 ssh 登錄,ftp 登錄等寫在一個(gè)腳本上,使之自動化完成。
適用于需要對多臺服務(wù)器執(zhí)行相同操作的環(huán)境中,可以大大提高系統(tǒng)管理人員的工作效率,使用它,你甚至可以僅僅執(zhí)行一個(gè)腳本來完成分布式應(yīng)用系統(tǒng)的搭建與維護(hù)。
到此這篇關(guān)于Shell之免交互的實(shí)現(xiàn)的文章就介紹到這了,更多相關(guān)Shell 免交互內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
shell編程之實(shí)現(xiàn)windows回收站功能分享
這篇文章主要介紹了使用trash命令替代linux rm命令實(shí)現(xiàn)windows回收站的功能,需要的朋友可以參考下2014-03-03Shell expr命令進(jìn)行整數(shù)計(jì)算的實(shí)現(xiàn)
這篇文章主要介紹了Shell expr命令進(jìn)行整數(shù)計(jì)算的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2021-03-03linux?shell中Grep命令查找多個(gè)字符串(grep同時(shí)匹配多個(gè)關(guān)鍵字或任意關(guān)鍵字)
grep是一種強(qiáng)大的文本搜索工具,它能使用正則表達(dá)式搜索文本,并把匹配的行打印出來,下面這篇文章主要給大家介紹了關(guān)于linux?shell中Grep命令查找多個(gè)字符串(grep同時(shí)匹配多個(gè)關(guān)鍵字或任意關(guān)鍵字)的相關(guān)資料,需要的朋友可以參考下2022-08-08通過實(shí)例深入理解linux shell數(shù)組
本文為大家介紹linxu shell中數(shù)組的相關(guān)知識,并舉了很多例子供參考,包括數(shù)組的復(fù)制,計(jì)算,刪除,替換等,是學(xué)習(xí)shell 數(shù)組的不可多得的好文章2013-02-02Linux?du命令實(shí)現(xiàn)根據(jù)文件或者文件夾大小排序輸出
Linux是一個(gè)強(qiáng)大的操作系統(tǒng),廣泛用于服務(wù)器和個(gè)人計(jì)算機(jī),本文主要來和大家聊聊如何利用du命令實(shí)現(xiàn)根據(jù)文件或者文件夾大小排序輸出,感興趣的可以了解下2023-09-09Linux下shell腳本監(jiān)控Tomcat的狀態(tài)并實(shí)現(xiàn)自動啟動的步驟
這篇文章主要介紹了Linux下shell腳本監(jiān)控Tomcat的狀態(tài)并實(shí)現(xiàn)自動啟動的步驟,本文給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友參考下吧2019-12-12