Linux系统 Here Document和Expect免交互

Here Document

Here Document 是 Shell 中的一种特殊的重定向方式,用来将输入重定向到一个交互式 Shell 脚本或程序。
使用I/O重定向的方式将命令序列提供给交互式程序
标准输入的一种替代品

语法格式

命令 <<EOF(标记)


EOF(标记)

注: I/O I in O out 将命令列表提供给交互程序 上面 …指的是交互的内容
标记可以为任意合法字符
开头标记前面的空格会被自动省略
结尾的标记一定要顶着最前面,不能有任何字符,包括空格
结尾的标记后面也不能有任何字符,包括空格(这个很难查到的)
标记必须大写

示例演示

简单演示

可以看到就算我写了两行,使用 echo 时也只出现了一行,赋值只赋值了第一行

[root@1centos ~]# read i<<EOF
> Hello world
> Jerry
> This is CentOS7
> EOF
[root@1centos ~]# echo $i
Hello world
[root@1centos ~]# 

变量设定

上面的变量赋值,只能赋值一行,那这种方法可以赋值多行,但是复制后在同一行

[root@1centos mianjiaohu]# vim bian.sh
sheding=$(cat <<EOF
This is CSDN.
This is my blog.
I am Ora_G
EOF
)

查看变量

[root@1centos mianjiaohu]# source bian.sh 
[root@1centos mianjiaohu]# echo $sheding
This is CSDN. This is my blog. I am Ora_G

替换变量

[root@1centos mianjiaohu]# vim tihuan.sh
#!/bin/bash
TXT='wenben.txt'
nei="CSDN"
cat > $TXT <<EOF
This is $nei .com
https://blog.csdn.net/Ora_G
EOF

打开 wenben.txt ,查看命令是否成功

[root@1centos mianjiaohu]# source tihuan.sh 
[root@1centos mianjiaohu]# cat wenben.txt 
This is CSDN .com
https://blog.csdn.net/Ora_G
[root@1centos mianjiaohu]# 

不使用替换变量

如下###注解

[root@1centos mianjiaohu]# vim guanbi.sh 
#!/bin/bash
TXT='wenben.txt'
nei="CSDN"
cat > $TXT <<'EOF'         ###在这边标记两侧加上单引号 ‘ ’,表示关闭替换变量
This is $nei .com
https://blog.csdn.net/Ora_G
EOF

打开 wenben.txt 查看
可以看到 $nei 已经被识别成普通字符串了

[root@1centos mianjiaohu]# cat wenben.txt 
This is $nei .com
https://blog.csdn.net/Ora_G
[root@1centos mianjiaohu]# 

去除TAB制表符空格

先做一个普通的

[root@1centos mianjiaohu]# vim TAB.sh
#!/bin/bash
cat << EOF
        This is CSDN.
        here!
EOF

查看

[root@1centos mianjiaohu]# vim TAB.sh
[root@1centos mianjiaohu]# source TAB.sh 
	This is CSDN.
	here!

在 标记 前面加上 -

[root@1centos mianjiaohu]# vim TAB.sh
#!/bin/bash
cat <<-EOF
        This is CSDN.
        here!
EOF

再查看,之前的制表符空栏已经没了

[root@1centos mianjiaohu]# source TAB.sh 
This is CSDN.
here!

多行注释

语法格式
:<< 标记
注释1
注释2

标记

注释的内容在输出中不显示

[root@1centos mianjiaohu]# vim TAB.sh 
#!/bin/bash
:<<KFC
下面的命令为去掉TAB制表符
KFC
cat <<-EOF
        This is CSDN.
        here!
EOF

[root@1centos mianjiaohu]# source TAB.sh 
This is CSDN.
here!

Expect

expect是一个自动化交互套件,主要应用于执行命令和程序时,系统以交互形式要求输入指定字符串,实现交互通信。
常用于进行自动化控制和测试
解决shell脚本中交互相关的问题

安装expect

[root@1centos mianjiaohu]# yum -y install expect
Running transaction
  正在安装    : expect-5.45-14.el7_1.x86_64                                 1/1 
  验证中      : expect-5.45-14.el7_1.x86_64                                 1/1 

已安装:
  expect.x86_64 0:5.45-14.el7_1                                                 

完毕!

基本流程命令

spawn:启动进程,并跟踪后续交互信息
send:向进程发送字符串,用于模拟用户的输入
该命令不能自动回车换行,一般要加、r(回车)
expect
expect的一个内部命令,判断上次输出结果里是否包含指定的字符串,如果有则立即返回,否则就等待超时时间后返回
只能捕捉有spawn启动的进程的输出
interact:执行完成后保持交互状态,把控制权交给控制台

基本内容命令

Timeout:指定超时时间,过期则继续执行后续指令
单位是:秒
timeout -1为永不超时
默认情况下,timeout是10秒
exp_continue
允许expect继续向下执行指令
send_user
回显命令,相当于echo

其他命令

$argv参数数组
Expect脚本可以接受从bash传递的参数,可以使用[lindex $argc n]获得,n从0开始,分别表示第一个,第二个,第三个…参数
类似于shell的位置变量,只是第一位为 0

arg:参数
v:value
Expect脚本的结尾
expect脚本必须以interact或expect eof结束,执行自动化任务通常expect eof就够了
expect eof是在等待结束标志。由spawn启动的命令在结束时会产生一个eof标记,expect eof就是在等待这个标记
log_file 输出日志文件
log_user 展示日志文件 1表示展示 0表示不展示

语法

send这个命令,不是执行了就自动帮我们回车的,所以要在后面加上 \n 或者 \r

单分支语法

expect “password:” {send “mima\n”;}

多分支语法

第一种
expect “aaa” {send “AAA\n";}
expect “bbb” {send “BBB\n”;}
expect “ccc” {send “CCC\n”}

第二种
expect {
“aaa” {send “AAA\n”;}
“bbb” {send “BBB\n”;}
“ccc” {send “CCC\n”}
}

加上 exp_continue 后,匹配到了字符不会退出语句,会执行下一行匹配

expect {
“aaa” {send “AAA\n”;exp_continue}
“bbb” {send “BBB\n”;exp_continue}
“ccc” {send “CCC\n”}
}

来吧!展示!

直接执行

[root@1centos mianjiaohu]# vim zhijie.sh 
#!/usr/bin/expect                ###expect位置
set timeout 120                 ###超时时间两分钟
log_file rizhi.log                 ###日志文件名
log_user 1                          ###展示日志文件
set IP [lindex $argv 0]
set pw [lindex $argv 1]
spawn ssh g@$IP 
expect {
"(yes/no)" {send "yes\n";exp_continue}        ###首次登录时会弹出是否登录的选项
"*password*" {send "$pw\n"}
}
interact                     ###转交控制

执行

[root@1centos mianjiaohu]# chmod +x zhijie.sh     ###增加执行权限
[root@1centos mianjiaohu]# ./zhijie.sh 20.0.0.132 123123
spawn ssh [email protected]
[email protected]'s password: 
Last login: Tue Jul 28 11:29:55 2020 from 20.0.0.139
[g@localhost ~]$ pwd
/home/g
[g@localhost ~]$ 

嵌套执行

[root@1centos mianjiaohu]# vim qiantao.sh 
#!/bin/bash
IP=$1
pw=$2
/usr/bin/expect<<-EOF
 set timeout 120
 spawn ssh root@$IP
 expect {
  "*password" {send "${pw}\n";}
}
expect "*]#" 
send "exit\n"
expect eof
EOF
[root@1centos mianjiaohu]# chmod +x qiantao.sh 
[root@1centos mianjiaohu]# ./qiantao.sh 20.0.0.135 123123
spawn ssh [email protected]
[email protected]'s password: 
Last login: Tue Jul 28 13:17:53 2020 from 20.0.0.139
[root@localhost ~]# exit
登出
Connection to 20.0.0.135 closed.
[root@1centos mianjiaohu]# 

实例演示

使用位置变量创建用户并设置密码

[root@1centos mianjiaohu]# vim yonghu.sh
#!/bin/bash
yh=$1
pw=$2
useradd $yh
/usr/bin/expect<<-EOF
spawn passwd $yh
expect "*新的 密码*" 
send "$pw\n"
expect "*密码*"
send "$pw\n"
expect eof;
EOF


[root@1centos mianjiaohu]# ./yonghu.sh chenj 123123
spawn passwd chenj
更改用户 chenj 的密码 。
新的 密码:
无效的密码: 密码少于 8 个字符
重新输入新的 密码:
passwd:所有的身份验证令牌已经成功更新。

考虑各种结果完成ssh登录

[root@1centos mianjiaohu]# vim wzssh.sh
#!/usr/bin/expect
set timeout 120
set IP [lindex $argv 0]
set pw [lindex $argv 1]
spawn ssh root@$IP
expect {
 "Connetion refused" exit
 "Name or service not Known" exit
 "(yes/no)" {send "yes\n";exp_continue}
 "*password:" {send "$pw\n"}
}
interact

登录试试

[root@1centos mianjiaohu]# chmod +x wzssh.sh 
[root@1centos mianjiaohu]# ./wzssh.sh 20.0.0.135 123123
spawn ssh [email protected]
[email protected]'s password: 
Last login: Tue Jul 28 19:02:43 2020 from 20.0.0.139
[root@localhost ~]# pwd
/root
[root@localhost ~]# who
root     :0           2020-07-28 13:01 (:0)
root     pts/0        2020-07-28 13:01 (:0)
root     pts/1        2020-07-28 19:03 (20.0.0.139)

猜你喜欢

转载自blog.csdn.net/Ora_G/article/details/107627756