文章目录
一、一、Here Document免交互
1.概述
使用I/O重定向的方式将命令列表提供给交互式程序
标准输入的一种替代品
2.格式
命令 <<标记 (EOF)
.....
.....
标记(EOF)
3.使用注意事项
标记可以使用任意合法字符(大写字符)
结尾的标记一定要顶格写,前面不能有任何字符
结尾的标记后面也不能有任何字符(包括空格)
开头标记前后的空格会被省略掉
4.使用标记免交互案例
1.通过read命令接收输入并打印
2.只能复制首行中的内容给i
3.变量替换
变量一定要先定义,在调用
4.变量设定
5.关闭变量替换功能
6.去除每行之间的Tab字符
7.多行注释信息
二、Expect工具
1.expect概述
Expect是建立在tcl基础上的一个工具,Expect是用来进行自动化控制和测试的工具。主要解决Shell脚本中不可交互的问题,
对于大规模的Linux运维很有帮助。
在Linux运维和开发中,我们经常需要远程登录服务器进行操作,在登录的过程是一个交互的过程,可能会需要输入yes/no password等信息
2.expect安装
- 系统一般不自带,需要自已安装
yum -y install expect #安装expect工具
3.expect基本命令
命令:
1. spawn:启动进程,并追踪指令
两个结束符:
expect脚本必须以interact或expect eof结束,执行自动化任务通常expect eof
expect eof是在等待结束标志。由spawn启动的命令在结束时会产生一个eof标记,expect eof就是在等待这个标记(等待执行结束)
interact:执行完成后保持交互状态,把控制权交给控制台
2. expect:expect的一个内部命令,判断上次输出结果里是否包含指定的字符串,如果有则立即返回,否则就等待超时时间后返回,只能捕捉有spawn启动的进程的输出(捕捉会话)
3. send:向进程自动发送字符串,末尾需要加\r,(自动发送指令)
内容命令:
set:指定超时时间,过期则继续执行后续指令
单位是:秒
timeout -1为永不超时
默认情况下,timeout是10秒
exp_continue
允许expect继续向下执行指令
send_user
回显命令,相当于echo
接收参数:
Expect脚本可以接收从bash传递的参数,可以使用[ Linux $argv n ]获得
n从o开始,分别表示第一个,第二个,第三个...参数
arg:参数
v:value
可以通过"set 变量名 [ Lindex $argv 0 ]"来调用
4.expect语法
1.单一分支语法
expect "password:" {send "123456\r";}
2.多分支模式语法
(1)
expect "aaa" {send "AAA\r"}
expect "aaa" {send "AAA\r"}
expect "aaa" {send "AAA\r"}
send命令不具备回车换行功能,所以需要自己添加\r 或 \n
(2)
expect {
"aaa" {send "AAA\r"}
"bbb" {send "BBB\r"}
"ccc" {send "CCC\r"}
}
'只要匹配了aaa 或bbb或ccc中的任何一个,执行相应的send语句后就会退出该expect语句'
expect {
"aaa" {send "AAA\r";exp_continue}
"bbb" {send "BBB\r";exp_continue}
"ccc" {send "CCC\r"}
}
exp_continue表示继续后面的匹配,如果匹配了aaa,执行完send语句后还会继续向下匹配bbb
捕捉内容要用双引号引起来
5.expect执行方式
1.直接执行
[$argv 0],代表位置变量$1
[$argv 1],代表位置变量$2
#!/usr/bin/expect 是Expect二进制文件的路径
[root@localhost~]#cat test.sh
#!/usr/bin/expect
set timeout 40 ##设置超时时间
log file test.log
log_user 1 ##展示日志信息,展示写1,不展示写0
set hostname [lindex $argv 0] ##变量定义
set password [lindex $argc 1]
spawn ssh root @$hostname ##追踪指令
expect { ##捕捉提示信息
"(yes/no)"
{send "yes\r";exp_continue}
"*password"
{send "$password\r"}
}
interact ##将权限转交控制台
注:只能用 ./ 来执行,因为不是bash环境了
2.嵌入执行
[root@localhost~]#cat b.sh
#!/bin/bash
hostname=$1
password=$2
expect<<-EOF
spawn ssh root@${hostname}
expect {
"(yes/no)"
{send "yes\r";exp_continue}
"*password"
{send "$password\r"}
}
expect "*]#"
send "exit\r"
expect eof
EOF 'Expect结束标志,EOF前后不能有空格'
6.项目实操
1.实现ssh自动登录
[root@localhost ~]# vim ssh.sh
#!/bin/bash
hostname=$1
password=$2
/usr/bin/expect<<-EOF
spawn ssh $hostname
expect {
"Connection refused" exit
"Name or service not known" exit
"to continue" {send "yes\r";exp_continue}
"password:" {send "$password\r"}
}
expect "*]#"
send "exit\r"
expect eof
EOF
首次登陆,运行脚本如下:
[root@localhost ~]# sh ssh.sh 192.168.100.110 123456
spawn ssh 192.168.100.110
The authenticity of host '192.168.100.110 (192.168.100.110)' can't be established.
ECDSA key fingerprint is SHA256:urjATAzpLLv0a25Tf02Ibw1bXMiMycqUJOijfkVsLoY.
ECDSA key fingerprint is MD5:ec:cd:62:72:ee:b6:c1:f7:f6:43:db:3a:04:ad:45:9a.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added '192.168.100.110' (ECDSA) to the list of known hosts.
root@192.168.100.110's password:
Last login: Tue Jul 28 02:02:30 2020
[root@client1 ~]# exit
登出
Connection to 192.168.100.110 closed.
正常登陆,运行脚本如下:
[root@localhost ~]# sh ssh.sh 192.168.100.110 123456
spawn ssh 192.168.100.110
root@192.168.100.110's password:
Last login: Tue Jul 28 02:04:14 2020 from 192.168.100.120
[root@client1 ~]# exit
登出
Connection to 192.168.100.110 closed.
2.实现FTP免密登录
正常流程:
[root@localhost ~]# ftp 192.168.7.54
Connected to 192.168.7.54 (192.168.7.54).
220 (vsFTPd 3.0.2)
Name (192.168.7.54:root): ftp
331 Please specify the password.
Password:
230 Login successful.
Remote system type is UNIX.
Using binary mode to transfer files.
ftp> cd pub
250 Directory successfully changed.
免密流程:
[root@localhost ~]# vim ftp.sh
#!/usr/bin/expect -f
set timeout 10
spawn ftp 20.0.0.10
expect "Name*"
send "ftp\r"
expect "Password:"
send "\r"
expect "ftp>*"
interact
expect eof