Here Document
使用I/O重定向的方式将命令列表提供给交互式程序,是标准输入的一种替代
语法格式
命令 <<标记
...
...
标记
注意事项
- 标记可以使用任意合法字符,但首尾要一致
- 结尾的标记一定要顶格写,前面不能有任意字符
- 结尾的标记后面也不能有任何字符(包括空格)
- 开头标记的前后的空格会被省略掉
实现简单的免交互
通过read命令接收输入并打印
[root@localhost ~]# vim do.sh
#!/bin/bash
#
read i <<EOF ##这个EOF是可以换的比如DEF
Hi
hello
EOF
echo $i
[root@localhost ~]# ./do.sh ##执行脚本的时候最好用这种方式
Hi
发现只有第一行被打印了,因为一次交互只对应一行;
设置用户密码
[root@localhost ~]# vim do01.sh
#!/bin/bash
#
passwd tom <<DEF
123456
123456
DEF
[root@localhost ~]# chmod +x do01.sh
[root@localhost ~]# ./do01.sh
更改用户 tom 的密码 。
新的 密码:无效的密码: 密码少于 8 个字符
重新输入新的 密码:passwd:所有的身份验证令牌已经成功更新。
变量的设定
变量替换
生成一个指定内容的文件
[root@localhost ~]# vim do02.sh
#!/bin/bash
#
filename="none.txt"
dearname="衣羊"
cat > $filename <<EOF
I miss $dearname .
EOF
[root@localhost ~]# ./do02.sh
[root@localhost ~]# cat none.txt
I miss 衣羊 .
变量一定要先定义,再调用,不然是会报错的
变量的设定
实现多行内容的赋值
[root@localhost ~]# vim do03.sh
#!/bin/bash
#
name=njit
myvar=$(cat <<EOF
my school is
$name
EOF
)
echo $myvar
[root@localhost ~]# ./do03.sh
my school is njit
关闭变量的替换功能
[root@localhost ~]# ./do04.sh
please use the $name
[root@localhost ~]# vim do04.sh
#!/bin/bash
#
cat <<'EOF' ##使用单引号将前面的标记引起来,关闭变量替换
please use the $name
EOF
去除每行之前的TAB字符
[root@localhost ~]# vim do05.sh
#!/bin/bash
#
cat <<-'EOF' ###-表示抑制行首的TAB
pelease remove
$kgc
EOF
[root@localhost ~]# ./do05.sh
pelease remove
$kgc
实现多行注释
通过Here Document方式使Bash支持多行注释
语法格式
: <<DO
第一行注释
第二行注释
....
DO
多行注释,注释内容不会被执行
[root@localhost ~]# vim do06.sh
#!/bin/bash
: <<DO
echo "hi"
echo "classmates"
DO
cat <<EOF
please sit down
EOF
[root@localhost ~]# ./do06.sh
please sit down
Expect
Expect是建立在tcl之上的一个工具,用于进行自动化控制和测试,解决shell脚本中交互相关的问题
安装
yum -y install expect
基本命令
spawn
- 用于启动进程,并跟踪后续交互信息,用来引导命令的
expect
- 用来捕捉由命令产生的交互信息,和期望的字符串进行匹配,如果有则立即返回,否则就等待超时时间后返回
- 只能捕捉由spawn启动的进程的输出
send
- 向进程发送字符串,用于模拟用户的输入
- 改命令不能自动回车换行,一般要加\r表示回车
结束符
- expect eof 等待执行结束,执行自动化任务时通常使用expect
- interact 执行完成后保持交互状态,把控制权交给控制台
set
- 设置超时时间,过期则继续执行后续命令
- 单位是秒
- timeout -1表示永不超时
- 默认情况下,timeout是10秒
exp_continue
- 允许expect继续向下执行命令
send_user
- 回显命令,相当于echo
接收参数
- Expect脚本可以接受从bash传递的参数
- 可以使用[lindex $argv n]获得
- n从0开始,分别表示第一个,第二个…参数
为了方便可以set filename [lindex $argv 1],之后便可以调用变量filename来表示第一个参数
Expect语法
- 单一分支语法
expect “password:” {send “123456\r”;}
- 多分支模式语法
expect “aaa” {send “AAA\r”;exp_continue} ##若是没有continue,一旦匹配上就不往下匹配了,会退出expect程序
expect “bbb” {send “BBB\r”}
Expect的执行方式
- 直接执行
远程登录
[root@localhost expect]# vim expect05.sh
#!/usr/bin/expect ###expect的路径
#
set timeout 10
log_file log.log
log_user 1
set hostname [lindex $argv 0]
set password [lindex $argv 1]
spawn ssh root@$hostname
expect {
"connecting (yes/no)"
{send "yes\r";exp_continue}
"password"
{send "${password}\r";}
}
interact
[root@localhost expect]# ./expect05.sh 20.0.0.61 123456
spawn ssh root@20.0.0.61
root@20.0.0.61's password:
Last login: Tue Jul 28 11:04:03 2020 from 20.0.0.100
[root@evil ~]#
- 嵌入式执行
远程登录后自动登出
[root@localhost expect]# !vim
vim expect07.sh
#!/bin/bash ###
#
hostname=$1
password=$2
/usr/bin/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
[root@localhost expect]# ./expect07.sh 20.0.0.61 123456
spawn ssh root@20.0.0.61
root@20.0.0.61's password:
Last login: Tue Jul 28 11:06:44 2020 from 20.0.0.100
[root@evil ~]# exit
登出
Connection to 20.0.0.61 closed.
案例
例1:创建用户并设置密码
[root@localhost expect]# vim expect08.sh
#!/bin/bash
#
username=$1
password=$2
useradd $1
/usr/bin/expect<<-EOF
spawn passwd $1
expect {
"新的 密码"
{send "$2\r";exp_continue}
"重新输入新的 密码"
{send "$2\r";}
}
EOF
[root@localhost expect]# ./expect08.sh wxy 123456
spawn passwd wxy
更改用户 wxy 的密码 。
新的 密码:
无效的密码: 密码少于 8 个字符
重新输入新的 密码:
passwd:所有的身份验证令牌已经成功更新。
例2:完成SSH登录过程
[root@localhost expect]# vim expect09.sh
#!/usr/bin/expect
#
set timeout 5
set hostname [lindex $argv 0]
set password [lindex $argv 1]
spawn ssh $hostname
expect {
"Connection refused" exit ##拒绝登录
"Name or server not known" exit ##
"to continue" {send "yes\r";exp_continue} ##正常登录
"password" {send "${password}\r";}
}
interact
exit
[root@localhost expect]# ./expect09.sh 20.0.0.61 123456
spawn ssh 20.0.0.61
root@20.0.0.61's password:
Last login: Tue Jul 28 11:44:11 2020 from 20.0.0.100
[root@evil ~]#
例3:FTP登录
[root@localhost expect]# vim expect10.sh
#!/usr/bin/expect
#
set timeout 10
spawn ftp 20.0.0.61
expect "Name*"
send "ftp\r"
expect "Password:"
send "\r"
expect "ftp>"
interact
expect eof
[root@localhost expect]# ./expect10.sh
spawn ftp 20.0.0.61
Connected to 20.0.0.61 (20.0.0.61).
220 (vsFTPd 3.0.2)
Name (20.0.0.61:root): ftp
331 Please specify the password.
Password:
230 Login successful.
Remote system type is UNIX.
Using binary mode to transfer files.
ftp>
记得安装vsftp,启动服务,关闭防火墙