一、Here Document免交互
1.1 Here Document概述
-
使用I/O重定向的方式将命令列表提供给交互式程序或命令,比如ftp、passwd、sudo、ssh、cat或read命令。
-
是标准输入的一种替代品,可以帮助脚本开发人员不必使用临时文件来构建输入信息,而是直接就地生产出一个"文件"并用作"命令"的标准输入。
-
Here Document也可以与非交互式程序和命令一起使用。
命令 <<标记 (此处标记的前后面可以有空格)
...
内容 #标记之间是传入内容
...
标记 #结尾的标记字符要和开头的标记字符,保持相同的大小写,并且结尾标记必须要顶格写
注意事项:
- 表示可以使用任意的合法字符(通用的字符是EOF表示end of file)
- 结尾的标记是一定要顶格写,前面不能有任何字符(包括空格)
- 结尾的标记后面也不能有任何字符(包括空格)
- 开头标记前后空格会被省略掉
二、应用示例
1 直接把输入的内容从命令行输出
[root@localhost /home]#cat <<EOF
> hello
> moto
> EOF
hello
moto
2 输入保存到文件中
[root@localhost /home]#cat >name<<EOF
> zhangsan
> lisi
> wangwu
> EOF
[root@localhost /home]#cat name
zhangsan
lisi
wangwu
3 追加输入保存到文件
[root@localhost /home]#cat >>name<<EOF
> xiaoming
> EOF
[root@localhost /home]#cat name
zhangsan
lisi
wangwu
xiaoming
4 对行数进行统计
[root@localhost /home]#wc -l <<EOF
> test1
> test2
> test3
> EOF
3
5 给变量赋值
#通过read 命令接收输入并打印,输入值是两个EOF标记之间的部分,作为变量 a 的值
[root@localhost /home]#read a <<EOF
> 8
> EOF
[root@localhost /home]#echo $a
8
6 免交互设置密码
[root@localhost /home]#useradd laowang
[root@localhost /home]#passwd laowang <<EOF
> 123456
> 123456
> EOF
更改用户 laowang 的密码 。
新的 密码:无效的密码: 密码少于 8 个字符
重新输入新的 密码:passwd:所有的身份验证令牌已经成功更新。
7 变量替换
[root@localhost /home]#vim test.sh
#!/bin/bash
doc_file="gkd.txt"
i="nanjing"
cat > $doc_file <<EOF
welcome to $i
EOF
[root@localhost /home]#sh test.sh
[root@localhost /home]#cat gkd.txt
welcome to nanjing
8 整体赋值给变量,用echo将变量值打印出来
[root@localhost /home]#vim test2.sh
#!/bin/bash
test="you are very good!"
mylife=$(cat <<EOF
冲冲冲!
干就完了!!!
$test
EOF
)
echo $mylife
[root@localhost /home]#sh test2.sh
冲冲冲! 干就完了!!! you are very good!
9 关闭变量替换的功能
#对标记加单引号,即可关闭变量替换
[root@localhost /home]#aa=$(cat <<'EOF'
> 10
> $a
> EOF
> )
[root@localhost /home]#echo $aa
10 $a
[root@localhost /home]#echo $a
8
10 去掉每行之前的 TAB 字符(顶格显示)
[root@localhost /home]#vim test3.sh
#!/bin/bash
cat <<EOF
hello
EOF
cat <<EOF
word
EOF
[root@localhost /home]#sh test3.sh
hello
word
[root@localhost /home]#vim test3.sh #EOF前面添加"-"能够去掉行首的tab制表符
#!/bin/bash
cat <<-EOF
hello
EOF
cat <<-EOF
word
EOF
[root@localhost /home]#sh test3.sh #加了"-"以后显示出的内容就会顶格显示
hello
word
11 多行注释
[root@localhost /home]#vim test4.sh
#!/bin/bash
: <<EOF #冒号表示多行注释,开头的标记内容不会被执行
hello?
who are you?
EOF
echo "What is the matter with you?"
[root@localhost /home]#sh test4.sh
What is the matter with you?
- Bash 的默认注释是"#",该注释方法只支持单行注释,在 Shell 脚本的工作中,"#"右侧的任何字符串,bash 都会将其忽略。
- " : "代表什么都不做的空命令。中间标记区域的内容不会被执行,会被bash 忽略掉,因此可达到批量注释的效果。
三、Expect 免交互
1、概述
expect 是一个免费的编程工具,用来实现自动的交互式任务,而无需人为干预,就是一套用来实现自动交互功能的软件。且想要用之前先下载 Expect。
[root@localhost /home]#yum install -y expect
2、基本命令
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
"密码1"{ send "abc123\r"}
"密码2"{ send "123456\r"}
"密码3"{ send "123123\r"}
#expect支持多个分支,只要匹配了其中一个情况,执行相应的send语句后退出该expect语句
5、 结束符
expect eof
- 表示交互结束,等待执行结束,退回到原用户,与spawn对应
- 比如:切换到root用户,expect脚本默认的是等待10s,当执行完命令后,默认停留10s后,就会自动切回原用户。
interact
- 执行完成后保持交互状态,把控制权交给控制台,会停留在目标终端,这个时候就可以手工操作了,interact 后的命令不起作用
- 比如 interact 会保持在终端而不会退回到原终端,比如切换到 root 用户,会一直在 root 用户状态下
- 比如2 ssh 到另一服务器,会一直在目标服务器终端,而不会切回的原服务器
需要注意的是:expect eof 与 interact 只能二选一
su
zhangsan -> lisi
ssh192.168.80.10 ->192.168.80.20
使用expect eof会出现如下情况:
zhangsan -> lisi --expect eof--> 退回到原用户zhangsan
192.168.80.10 -> 192.168.80.20 --expect eof--> 退回到原IP地址:192.168.80.10
使用interact会出现如下情况:
zhangsan -> lisi --interact--> 仍然保持用户lisi的状态
192.168.80.10 ->192.168.80.20 --interact--> 仍然保持在IP地址:192.168.80.20
6 set
expect 默认的超时时间是10秒,通过 set 命令可以设置会话超时时间,若不限制超时时间则应设置为-1
set timeout 20
Expect 案例
免交互修改密码:
[root@test1 opt]# vim passwd.sh
#!/usr/bin/expect #expect的路径指定使用expect编译器
set timeout 3 #设置退时间
spawn passwd zjf #开启修改密码
expect "新的 密码:" #捕获
send "123\r" #设置密码
expect "重新输入新的 密码:" #捕获
send "123\r" #设置密码
expect eof #退出
免交互方式实现SSh登录:
#!/usr/bin/expect
set ip 192.168.198.12
set user root
set passwd 000000
set timeout 5
spawn ssh $user@$ip
expect {
"yes/no" {send "yes\n";exp_continue}
"password" {send "${passwd}\n"}
}
interact