Here Document使用I/O重定向的方式將命令列表提供給交互式程序或命令,好比ftp、cat或read命令。
Here Document是標準輸入的一種替代品,能夠幫助腳本開發人員沒必要使用臨時文件來構建輸入信息,而是直接就地產生出一個「文件」並用做「命令」的標準輸入。
Here Document也能夠與非交互式程序和命令一塊兒使用。python
命令 <<標記
... 內容 #標記之間是傳入內容 ... 標記
免交互方式實現對行數的統計,將要統計的內筒置於標記「EOF」之間,直接將內容傳給「wc -l」來進行統計linux
[root@localhost ~]# wc -l <<EOF
> ABC > 123 > EOF 2
經過read命令接收輸入並打印,輸入值是兩個EOF標記之間的部分,做爲變量i的值。nginx
[root@localhost ~]# wc -l <<EOF
> ABC > 123 > EOF 2 [root@localhost ~]# read i <<EOF > ABC > 123 > 321 > eof > EOF [root@localhost ~]# echo $i ABC
因爲每一行的輸入都有回車(換行符)的存在,所以Here Document只能賦值一個變量。sql
修改密碼的方法有:shell
[root@localhost ~]# useradd zhangsan [root@localhost ~]# passwd zhangsan 更改用戶 zhangsan 的密碼 。 新的 密碼: 從新輸入新的 密碼: passwd:全部的身份驗證令牌已經成功更新。
[root@localhost ~]# echo 123456 | passwd --stdin zhangsan 更改用戶 zhangsan 的密碼 。 passwd:全部的身份驗證令牌已經成功更新。
固然,也可經過Here Document免交互進行修改apache
[root@localhost ~]# passwd zhangsan <<EOF > 123456 > 123456 > EOF 更改用戶 zhangsan 的密碼 。 新的 密碼:無效的密碼: 密碼少於 8 個字符 從新輸入新的 密碼:passwd:全部的身份驗證令牌已經成功更新。
[root@localhost ~]# cat > test.txt <<EOF > ABC > 123 > EOF [root@localhost ~]# cat test.txt ABC 123
注:「cat >"操做也可以使用」tee「命令代替vim
[root@localhost ~]# tee test.txt <<EOF > 321 > CBA > EOF 321 CBA [root@localhost ~]# cat test.txt 321 CBA
在寫入文件時會將變量替換成實際值,再結合cat/tee命令完成寫入ruby
[root@localhost ~]# vim test.sh #!/bin/bash file="eat.txt" i="food" tee $file <<EOF i want to eat $i EOF [root@localhost ~]# ./test.sh i want to eat food
總體賦值給變量,而後經過echo命令將變量值打印出來bash
[root@localhost ~]# cat test1.sh #!/bin/bash var="I want to play a game!" myvar=$(cat <<EOF Today is Sunday. $var EOF ) echo "$myvar" [root@localhost ~]# ./test1.sh Today is Sunday. I want to play a game!
關閉變量替換的功能,按照字符本來的樣子輸出,不作任何修改或替換服務器
[root@localhost ~]# cat test1.sh #!/bin/bash var="I want to play a game!" myvar=$(cat <<'EOF' #對標記加單引號,便可關閉變量替換 Today is Sunday. $var EOF ) echo "$myvar" [root@localhost ~]# ./test1.sh Today is Sunday. $var
[root@localhost ~]# cat test1.sh #!/bin/bash var="I want to play a game!" myvar=$(cat <<-EOF #在標記前加「-」,便可抑制各首行「TAB」 Today is Sunday. #"TAB" $var #空格 EOF ) echo "$myvar" [root@localhost ~]# ./test1.sh Today is Sunday. I want to play a game! #對空格無效
Bash的默認註釋是「#」,該註釋方法只支持單行註釋;Here Document的引入解決了多行註釋的問題。
「:」表明什麼都不作的空命令。中間標記區域的內容不會被執行,會被bash
忽略掉,所以可達到批量註釋的效果。
[root@localhost ~]# cat test1.sh #!/bin/bash var="I want to play a game!" : <<EOF #多行註釋,「:」開頭的Here Document標記內容不會被執行 echo ABC Today is Sunday. echo $var EOF echo "123" [root@localhost ~]# ./test1.sh 123
Expect是創建在tcl語言基礎上的一個工具,常被用於進行自動化控制和測試,解決shell腳本中交互相關的問題。
Expect腳本中首先引入文件,代表使用的是哪個Shell。
#!/usr/bin/expect
spawn後面一般跟一個Linux執行命令,表示開啓一個會話、啓動進程,並跟蹤後續交互信息。
例如:
spwan passwd root
判斷上次輸出結果結果中是否包含指定的字符串,若是有則當即返回,不然就等待超時時間後返回;
只能捕捉由spawn啓動的進程的輸出;
用於接收命令執行後的輸出,而後和指望的字符串匹配。
向進程發送字符串,用於模擬用戶的輸入;該命令不能自動回車換行,所以需手動寫入「\r」或者「\n」
例如:
方式一:
expect "密碼" {send "123456\r"} #同行send部分須要有{}
方式二:
expect "密碼" send "123456\r" #換行send部分不須要有{}
方式三:
expect支持多個分支,只要匹配了其中一個狀況,執行相應的send語句後退出該expect
語句
expect {
"密碼" {send "123456\r"} "password" {send "123456\r"} }
expect eof
表示交互結束,等待執行結束,退回到原用戶,與spawn對應。
好比切換到root用戶,expect腳本默認的是等待10s,當執行完命令後,默認停留10s後,自動切回了原用戶。
interact
執行完成後保持交互狀態,把控制權交給控制檯,若經過ssh創建了遠程鏈接,interact會停留在目標終端而不會退回到原終端,這個時候就能夠手工操做了,interact後的命令不起做用,好比interact後面添加exit,並不會退出root用戶或終端鏈接。而若是沒有interact則登陸完成後會退出,而不是留在遠程終端上。
使用interact會保持在終端而不會退回到原終端,好比切換到root用戶,會一直保持在root用戶狀態下;好比ssh到另外一服務器,會一直在目標服務器終端,而不會切回原服務器。
注:expext eof 與 interact 只能二選一使用。
expect默認的超時時間是10秒,經過set命令能夠設置會話超時時間,若不限制超時時間則應設置爲-1.
例如:
set timeout 30
exp_continue附加於某個expect判斷項以後,可使該項被匹配後,還能繼續匹配該expect判斷語句內的其餘項。exp_continue相似於控制語句中的"continue"語句,表示容許expect繼續向下執行指令。
例如:
判斷交互輸出中是否存在(yes/no)或者*password。若是匹配(yes/no)則輸出yes並再次執行判斷;若是匹配*password則設置超時時間300秒並在輸出123456後結束改短expect。
expect { "(yes/no)" {send "yes\r";exp_contiinue} "*password" {set timeout 300; send "123456\r";} }
send_user表示回顯命令,至關於echo的做用。
expect腳本能夠接受從bash命令行傳遞的參數,使用[lindex $argv n]得到。其中n從0開始,分別表示第一個,第二個,第三個參數,以此類推。
例如:
修改密碼
[root@localhost ~]# cat test2.sh #!/usr/bin/expect #設置位置參數傳入 #設置第一個位置參數,至關於username=$1 set username [lindex $argv 0] #設置第二個位置參數,至關於password=$2 set password [lindex $argv 1] #開啓命令追蹤進程 spawn passwd $username #開啓面交互執行,捕捉信息並匹配 expect "新的 密碼" send "${password}\r" expect "從新輸入新的 密碼" send "${password}\r" #結束免交互 expect eof [root@localhost ~]# vim test2.sh [root@localhost ~]# ./test2.sh zhangsan 123456 spawn passwd zhangsan 更改用戶 zhangsan 的密碼 。 新的 密碼: 無效的密碼: 密碼少於 8 個字符 從新輸入新的 密碼: passwd:全部的身份驗證令牌已經成功更新。
expect直接執行,須要使用expect命令去執行腳本
例如:
su切換用戶
[zhangsan@localhost ~]$ cat test3.sh #!/usr/bin/expect #設置超時時間 set timeout 5 #參數傳入 set username [lindex $argv 0] set password [lindex $argv 1] #開啓追蹤命令 spawn su $username #免交互執行,捕捉信息並匹配 expect "密碼" send "$password\r" expect "*]#" send_user "ok" #把控制權交給控制檯 interact [zhangsan@localhost ~]$ ./test3.sh root 123456 spawn su root 密碼: [root@localhost zhangsan]# ok
嵌入執行模式,將expect過程融入Shell當中,方便執行和處理。
建立用戶並設置密碼
[root@localhost ~]# cat test4.sh #!/bin/bash username=$1 password=$2 #非交互命令放在外面 useradd $username #開始免交互執行 /usr/bin/expect <<EOF spawn passwd $username expect "新的*" send "${password}\r" expect "從新*" send "${password}\r" expect eof EOF [root@localhost ~]# ./test4.sh lisi 123456 useradd:用戶「lisi」已存在 spawn passwd lisi 更改用戶 lisi 的密碼 。 新的 密碼: 無效的密碼: 密碼少於 8 個字符 從新輸入新的 密碼: passwd:全部的身份驗證令牌已經成功更新。
免交互自動建立磁盤分區
[root@localhost ~]# cat fdisk.sh #!/usr/bin/expect set dev [lindex $argv 0] spawn fdisk $dev expect "命令" {send "n\n"} expect "Select" {send "p\n"} expect "命令" {send "q\n";exit;exp_continue} expect "分區號" {send "\n"} expect "起始 扇區" {send "\n"} expect "Last" {send "\n"} expect "命令" {send "wq\n"} expect eof [root@localhost ~]# [root@localhost ~]# [root@localhost ~]# ./fdisk.sh /dev/sdb spawn fdisk /dev/sdb 歡迎使用 fdisk (util-linux 2.23.2)。 更改將停留在內存中,直到您決定將更改寫入磁盤。 使用寫入命令前請三思。 命令(輸入 m 獲取幫助):n Partition type: p primary (0 primary, 0 extended, 4 free) e extended Select (default p): p 分區號 (1-4,默認 1): 起始 扇區 (2048-10485759,默認爲 2048): 將使用默認值 2048 Last 扇區, +扇區 or +size{K,M,G} (2048-10485759,默認爲 10485759): 將使用默認值 10485759 分區 1 已設置爲 Linux 類型,大小設爲 5 GiB 命令(輸入 m 獲取幫助):wq The partition table has been altered! Calling ioctl() to re-read partition table. 正在同步磁盤。