網站首頁 編程語言 正文
前言
免交互就是實現一個功能時,不需要連續從鍵盤輸入信息,通過腳本或命令自動完成一些動作。
一、Here Document
1.Here Document概述
使用 I/O 重定向的方式將命令列表提供給交互式程序或命令,比如 ftp、cat或read命令。
HereDocument是標準輸入的一種替代品,可以幫助腳本開發人員不必使用臨時文件來構建輸入信息,而是直接就地生產出一個文件并用作命令的標準輸入。
2.基本語法格式
命令 <<標記
……
……
標記#特殊字符“<<”在標記和命令之前,這樣做的目的是將命令塊的輸出重定向到程序和命令的stdin。
#標記的選擇要確保不會出現在其他地方,避免出現混淆;兩個標記之間的內容被當做是一個文件并用作“命令”的標準輸入。
#另外Here Document也可以與非交互式程序和命令一起使用
四點注意事項:
- 標記可以使用任意的合法字符;
- 結尾的標記一定要頂格寫,前面不能有任何字符;
- 結尾的標記后面也不能有任何字符(包括空格);
- 開頭的標記前后的空格會被省略
[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
例:創建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 命令接收輸入并打印,輸入值是兩個 EOF 標記之間的部分,也就是“10”,這將作為變量 a 的值
[root@c7-1 ~]# read a <<EOF
> 10
> EOF
[root@c7-1 ~]# echo $a
10
3.2 通過 passwd 給用戶設置密碼
[root@c7-1 ~]# passwd zhangsan <<EOF
> 123456
> 123456
> EOF
更改用戶 zhangsan 的密碼 。
新的 密碼:無效的密碼: 密碼少于 8 個字符
重新輸入新的 密碼:passwd:所有的身份驗證令牌已經成功更新。
4.變量設定(支持變量替換)
4.1 在寫入文件時要先將變量替換成實際值,在結合 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 整體賦值給一個變量,然后通過 echo 命令將變量值打印出來
#!/bin/bash
ivar="Great! Beautyful!"
myvar=$(cat <<EOF #將Here Document 整體賦值給變量
This is Line 1.
That are Sun,Moon and Stars.
$ivar #輸出時會進行變量替換
EOF
)
echo $myvar
5.格式控制
5.1 關閉變量替換的功能
[root@c7-1 ~]# aa=$(cat <<'EOF' ? ?//關閉變量替換 對標記加單引號,即可關閉變量替換
20
$a
EOF
)
echo $aa
#!/bin/bash
cat <<'EOF'?? ??? ?//對標記加單引號,即可關閉變量替換
This is Line 1.
$kkk?
EOF
5.2 去掉每行之前的 TAB 字符
在第一行的標記前面加‘-’,這個表示要抑制各行首 TAB 的作用。
[root@c7-1 ~]# vim dome3.sh ? ?//寫一個腳本測試抑制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 的默認注釋是“#”,該注釋方法只支持單行注釋,在 Shell 腳本的工作中,“#”右側的任何字符串,bash 都會將其忽略。Here Document 的引入解決了多行注釋的問題。
: 代表什么都不做的空命令。中間標記區域的內容不會被執行,會被bash 忽略掉,因此可達到批量注釋的效果。
#!/bin/bash
: <<-EOF //多行注釋 以 :開頭的Here Document標記內容不會被執行
the second comment.
test line.
EOF
echo "dashiji"
二、Expect
1.Expect概述
建立在tcl語言基礎上的一個工具,常被用于進行自動化控制和測試,解決shell腳本中交互相關的問題
2.expect的基本安裝
expect是一個程序,所以他也是需要提前安裝才可以使用的
[root@c7-1 expect]# rpm -q expect
[root@c7-1 expect]# rpm -q tcl
[root@c7-1 expect]# yum install expect -y //安裝expect時會把tcl作為依賴包安裝
3.基本命令
(1)腳本解釋器
expect腳本中首先引入文件,表明使用的是哪一個shell
#!/usr/bin/expect
(2)spawn
spawn后面通常跟一個Linux執行命令,表示開啟一個會話、啟動進程,并跟蹤后續交互信息。
例如:
spawn passwd root
(3)expect
判斷上次輸出結果中是否包含指定的字符串,如果有則立即返回,否則就等待超時時間后返回;
只能捕捉由spawn啟動的進程的輸出;
用于接收命令執行后的輸出,然后和期望的字符串匹配
(4)send向進程發送字符串,用于模擬用戶的輸入;該命令不能自動回車換行,一般要加 \r (回車) 或者 \n
方式一:
?? ?expect "密碼"{ send "abc123\r" }?? ??? ?//同一行send部分要有{}
方式二:
?? ?expect "密碼"
?? ?send "abc123\r"?? ??? ??? ??? ??? ??? ?//換行send部分不需要有{}
方式三:
?? ?expect支持多個分支
?? ?expect?? ??? ?//只要匹配了其中一個情況,執行相應的send語句后退出該expect語句
?? ?"密碼1"{ send "abc123\r" }
?? ?"密碼2"{ send "123456\r" }
?? ?"密碼3"{ send "123123\r" }
(5)結束符
expect eof
表示交互結束,等待執行結束,退回到原用戶,與spawn對應。
比如切換到root用戶,expect腳本默認的是等待10s,當執行完命令后,默認停留10s后,自動切回了原用戶
interact
執行完成后保持交互狀態,把控制權交給控制臺,會停留在目標終端而不會退回到原終端,這個時候就可以手工操作了,interact后的命令不起作用,比如interact后添加exit,并不會退出root用戶。而如果沒有interact則登錄完成后會退出,而不是留在遠程終端上。
注意:expect eof 與 interact 只能二選一。
(6)set
expect 默認的超時時間是10秒,通過 set命令可以設置會話超時時間,若不限制超時時間則應設置為-1。
例:?
set timeout 30
(7)exp_continue
附加于某個expect判斷項之后,可以使該項被匹配后,還能繼續匹配該expect-判斷語句內的其他項。exp_continue類似于控制語句中的continue 語句。表示允許expect繼續向下執行指令。
例如:下例將判斷交互輸出中是否存在yes/no 或*password。如果匹配 yes/no 則輸出 yes并再次執行判斷;
如果匹配*password則輸出abc123并結束該段expect語句。
expect{
?? ?"(yes/no)"
?? ?{ send "yes\r";exp_continue;}
?? ?"*password"
?? ?{ set timeout 300;send "abc123\r";}
}
#注意:使用exp continue時,如果跟蹤像passwd這樣的輸入密碼后就結束進程的命令,expect{}外不要再加上expect eof
#因為spawn進程結束后會默認向expect發送eof,會導致后面的expect eof執行報錯
#注:表示允許用戶進行交互操作,一直保持回話連接
(8)send user
send user 表示回顯命令,相當于echo
(9)接收參數
expect腳本可以接受從bash命令行傳遞的參數,使用[lindex $argvn]獲得。
其中n從o開始,分別表示第一個,第二個,第三個..參數。例:
set hostname [ lindex $argy 0 ]
相當于hostname=$1
set password [ lindex $argy 1 ]
相當于password=$2
4.用expect編寫腳本
4.1 ssh無交互登錄到遠程服務器
[root@c7-1 expect]# vim dome1.sh?
#!/usr/bin/expect?? ??? ??? ??? ?//這里需要用expect自己的解釋器,注意不要寫成bash否則無法識別
spawn ssh root@192.168.3.100?? ?//開啟一個程序,這個程序是ssh遠程登錄?? ??? ??? ?
expect {?? ??? ??? ??? ??? ??? ?//捕獲內容,當出現password的時候,就會向程序發送密碼,默認是不換行的,所以需要\r回車換行,多個條件需要花括號括起來,注意格式問題!
? ? ? ? "password"
? ? ? ? { send "123\r"; }?? ??? ?
}
interact
4.2 如果想要在對方服務器上進行一下操作后再退出可執行以下腳本
[root@c7-1 ~]# vim expect.sh
#!/usr/bin/expect
spawn ssh root@192.168.3.100
expect {
? ? ? ? "password:"
? ? ? ? { send "123456\r"; }
}
expect "#" ? ? ? //當捕獲到#的時候
send "ls\r" ? ?//執行ls命令
send "ifconfig ens33\r" ? //執行ifconfig ens33命令
send "exit\r" ? //執行完exit退出登陸
expect eof ? ?//不需要進行交互了,意味著結束expect程序,如果不寫的話不會執行操作直接退出;如果不寫,寫interact也無法在對方機器上執行命令,eof可以替換
4.3 定義和引用變量
用set關鍵字定義變量,變量名和變量的值中間用空格分開,其他用法與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] ? ?//設置第一個位置變量為ip
set pass [lindex $argv 1] ? //設置第二個位置變量為登陸密碼
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 ? //執行時需要加位置變量
#####還可以定義其他參數,例如超時時間,日志等
#超時時間
set timeout 20 ? //登陸超時多少秒退出
#開啟日志文件
log_file test.log ? //日志記錄操作
#顯示信息
log_user 1 ? //1為屏幕輸出信息,0為不輸出
4.4 在shell腳本中調用expect
#!/bin/bash
username=$1
useradd $username
/usr/bin/expect <<-EOF
spawn passwd $username
expect {
?? ??? ?"新的 密碼" ? ? //注意:獲取的內容和發送的內容不能在同一行否則執行不成功
?? ??? ?{send "123456\r";exp_continue}
?? ??? ?
?? ??? ?"重新輸入新的 密碼"
?? ??? ?{send "123456\r";}
}
EOF
驗證結果:
[root@c7-1 ~]# ./user.sh wangwu
spawn passwd wangwu
更改用戶 wangwu 的密碼 。
新的 密碼:
無效的密碼: 密碼少于 8 個字符
重新輸入新的 密碼:
passwd:所有的身份驗證令牌已經成功更新。
總結
借助 expect 處理交互的命令,可以將交互過程如 ssh 登錄,ftp 登錄等寫在一個腳本上,使之自動化完成。
適用于需要對多臺服務器執行相同操作的環境中,可以大大提高系統管理人員的工作效率,使用它,你甚至可以僅僅執行一個腳本來完成分布式應用系統的搭建與維護。
原文鏈接:https://blog.csdn.net/weixin_59410846/article/details/120309017
相關推薦
- 2022-12-09 PyTorch中關于tensor.repeat()的使用_python
- 2022-08-26 利用Python實現自動化監控文件夾完成服務部署_python
- 2023-07-24 navigator里包含tabBar內容時失效
- 2022-05-13 hiveserver2 連接報:root is not allowed to impersonate
- 2022-02-28 docker安裝17.03.0版本報錯 ->軟件包 docker-ce-selinux 已經被 do
- 2022-08-26 詳解WPF雙滑塊控件的使用和強制捕獲鼠標事件焦點_C#教程
- 2024-03-05 layui彈出層的表單驗證(form表單自帶的驗證不執行)
- 2022-05-27 Python?內置函數sorted()的用法_python
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支