Here Document and expect free interactive explanation and experiment

Shell's free interaction

1. Here Document is free of interaction

Use I/O redirection to provide the command list to the interactive program, a substitute for standard input

(1) Grammar format and examples

命令  <<标记
...				#标记之间是传入内容
...
标记
注意事项:
标记可以使用任意合法字符(通常为EOF)
结尾的标记一定要顶格写,前面不能有任何字符
结尾的标记后面也不能有任何字符(包括空格)
开头标记前后的空格会被省略掉

Example 1: Realize the statistics of the number of rows without interaction, put the content to be counted between the mark "EOF", and directly pass the content to wc -l for statistics

wc -l <<EOF
>Line1
>Line2
>EOF

Insert picture description here

Example 2: Use the read command to receive input and print. The input value is the part between two EOF tags as the value of variable i

read i <<EOF
>Hi
>EOF
>echo $i

Insert picture description here

Example 3: Set a password for the user through passwd

passwd lisi <<EOF
>abc1234 			#这两行是输入的密码和确认密码
>abc1234
>EOF

Insert picture description here

Example 4: Support variable substitution

#!/bin/bash
file="EOF1.txt"
i="school"
cat > $file <<EOF
I am going to $i
EOF

Insert picture description here
Insert picture description here

Example 5: Assign a value to a variable as a whole

#!/bin/bash
var="Great! I am going to school!"
myvar=$(cat <<EOF			 
This is Line 1.
Today is Monday.
$var
EOF
)

echo $myvar

Insert picture description here
Insert picture description here

Turn off the function of variable substitution

#!/bin/bash
var="Great! I am going to school!"
myvar=$(cat <<'EOF'			#对标记加单引号,即可关闭变量替换			 
This is Line 1.
Today is Monday.
$var
EOF
)

echo $myvar

Insert picture description here

Remove the TAB character before each line

#!/bin/bash
var="Great! I am going to school!"
myvar=$(cat <<-'EOF'			#对标记前加“-”,即可抑制各行首TAB	 
	This is Line 1.
 Today is Monday.
$var
EOF
)

echo $myvar

Insert picture description here
Insert picture description here
Insert picture description here

Multi-line comments

The default comment of Bash is "#", this comment method only supports single-line comments: The introduction of Here Document solves the problem of multi-line comments.
":" represents an empty command that does nothing. The content of the middle mark area will not be executed and will be ignored by bash, so the effect of batch comments can be achieved.

#!/bin/bash
var="Great! I am going to school!"
: <<-EOF                         #多行注释,“:”开头的 Here Document 标记内容不会被执行
        This is Line 1.
 Today is Monday.
$var
EOF
echo "abcd"

Two, Expect

A tool built on the basis of the tcl language, often used for automated control and testing, to solve interactive problems in shell scripts

Need to be installed separately:

rpm -q expect
rpm -q tcl
yum install -y expect

(1) Basic commands

1)脚本解释器
expect 脚本中首先引入文件,表明使用的是哪一个 shell。
#!/usr/bin/expect
2)spawn
spawn 后面通常跟一个命令,表示开启一个会话、启动进程,并跟踪后续交互信息。
例:spawn passwd root
3expect
判断上次输出结果中是否包含指定的字符串,如果有则立即返回,否则就等待超时时间后返回;只能捕捉由spawn启动的进程的输出;用于接收命令执行后的输出,然后和期望的字符串匹配
4)send
向进程发送字符串,用于模拟用户的输入;该命令不能自动回车换行,一般要加\r(回车)或者\n
case1="密码"
respond="abc1234"

expect "$case1" {
    
    send "$respond1\r"}		#同一行send部分要有{
    
    }

expect "$case1"	
send "$response1\r"							#换行send部分不需要有{
    
    }

expect					#只要匹配了其中一个情况,执行相应的send语句后退出该expect语句
{
    
    
"$case1" {
    
    send "$response1\r"}
"$case2" {
    
    send "$response2\r"}
"$case3" {
    
    send "$response3\r"}
5)结束符
expect eof
表示交互结束,等待执行结束,退回到原用户,与spawn对应
比如切换到root用户,expect脚本默认的是等待10s,当执行完命令后,默认停留10s后,自动切回了原用户

interact
执行完成后保持交互状态,把控制权交给控制台,会停留在目标终端而不会退回到原终端,这个时候就可以手工操作了,interact后的命令不起作用,比如interact后添加exit,并不会退出root用户。而如果没有interact则登录完成后会退出,而不是留在远程终端上。
使用interact会保持在终端而不会退回到原终端,比如切换到root用户,会一直在root用户状态下;比如ssh到另一服务器,会一直在目标服务器终端,而不会切回的原服务器。

注意:expect eof 与 interact 只能二选一。
6set
expect 默认的超时时间是 10 秒,通过 set 命令可以设置会话超时时间, 若不限制超时时间则应设置为-1。
例:set timeout 30
7)exp_continue
exp_continue 附加于某个 expect 判断项之后,可以使该项被匹配后,还能继续匹配该 expect 判断语句内的其他项。exp_continue 类似于控制语句中的 continue 语句。
例如:下例将判断交互输出中是否存在 yes/no 或 *assword。如果匹配 yes/no 则输出 yes 并再次执行判断;如果匹配 *assword 则输出 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 $argv n]获得。其中n从0开始,分别表示第一个,第二个,第三个....参数。
例:
set hostname [lindex $argv 0]   	相当于 hostname=$1
set password [lindex $argv 1]		相当于 password=$2

expect直接执行,需要使用expect命令去执行脚本

(Two), example 1: parameter input

#!/usr/bin/expect

#设置超时时间
set timeout 60

#参数传入
set username [lindex $argv 0]
set password [lindex $argv 1]
#追踪命令
spawn su $username
#免交互执行,捕捉信息并匹配
expect "密码" send "Spassword\r" 

expect "*]#" send user "ok" . 

#把控制权交给控制台 

interact

 #expect eof

(B), Example 2: Embedded execution mode

Embedded execution mode, integrate the expect process into the Shell to facilitate execution and processing

Create user and set password

#! /bin/bash
user=$1
password=$2
#非交互命令放在expect外面
useradd $user
#开始免交换执行
/usr/bin/expect <<-EOF
#expect开始标志
spawn passwd $user
#开启-一个进程跟踪passwd命令,expect只能捕捉该进程信息
expect "新的*"
send "$ {password}\r" .
expect "重新*"
send "$ {password} \r"
expect eof
EOF

(Three), example 3: realize ssh automatic login

#! /usr/bin/ expect
set timeout 5
set hostname [l index $argv 0 ]
set password [l index $argv 1]
spawn ssh $hostname
expect {
    
    
"Connection refused" exit
#连接失败情况,比如对方ssh服务关闭
"Name or service not known" exit
#找不到服务器,比如输入的IP地址不正确
" (yes/no)" {
    
    send "yes\r" ;exp_ continue}
"password:" {
    
    send "$password\r"}
interact
exit
#interact后的命令不起作用

Embedded:

#!bin/bash
user=$1
passwd=$2
/usr/bin/expect <<EOF
spawn ssh $1
expect "(yes/no)" {
    
    send "yes\r"}
expect "password" {
    
    send "$2\r"}
expect eof
EOF

Insert picture description here
Insert picture description here

(Four), create disk without interaction

#!/bin/bash
disk=$1
/usr/bin/expect <<-EOF
spawn fdisk $disk
expect "命令" {
    
    send "n\r"}
expect "Select" {
    
    send "\r"}
expect "分区" {
    
    send "\r"}
expect "起始" {
    
    send "\r"}
expect "Last" {
    
    send "\r"}
expect "命令(输入 m 获取帮助):" {
    
    send "w\r"}
expect eof
EOF
partprobe
mkfs.xfs $disk -f &> /dev/null
if [ $? -eq 0 ]
then
echo -e "\033[31m 磁盘格式化完成 \033[0m"
mkdir $disk.1
mount $disk $disk.1
df -h
else
echo "请检查脚本,有问题"
fi

Guess you like

Origin blog.csdn.net/weixin_51573771/article/details/111866559