免交互:
交互:我们发出指令来控制程序的运行,程序在接收到指令之后按照指令的效果做出对应的反应。
免交互:间接的通过第三方的方式把指令传送给程序,不用直接的下达指令。
Here Document 免交互:
这是命令行格式,也可以写在脚本当中。通过I/O重定向的方式将命令的列表传送给交互式程序或命令。
是标准输入的一种替代品。代替了人工的输入方式。
语法格式:
命令(linux的系统命令)<< 标记 内容1 内容2 内容3 ... 标记
注意事项:
1、标记可以是任意合法字符(一般不用特殊字符,不以数字开头,通常以EOF作为默认的标记位)
2、结尾的标记一点要顶格写,且前面不能有任何字符,空格也不行。
3、结尾的标记后面也不能有任何字符,包括空格
4、开头的标记前后的空格都会被省略掉
练习:
[root@localhost ~]# wc -l <<xy102 > 123 > 45 > 789 > xy102 3 [root@localhost ~]# wc -l <<xy102 123 45 789 xy^C [root@localhost ~]# wc -l <<xy102 > 12 > 34 > 56 > 78 > 90 > xy102 5 [root@localhost ~]# read i <<EOF > qwe > EOF [root@localhost ~]# echo $i qwe [root@localhost ~]# echo $i+ qwe+ [root@localhost ~]# passwd dn <<EOF > 123 > 123 > EOF 更改用户 dn 的密码 。 新的 密码:无效的密码: 密码少于 8 个字符 重新输入新的 密码:passwd:所有的身份验证令牌已经成功更新。 [root@localhost opt]# cat <<EOF>>test1.txt > qwe > asd > zxc > EOF [root@localhost opt]# cat test1.txt qwe asd zxc
[root@localhost opt]# tee test2.txt <<EOF > 123 > 456 > EOf > EOF 123 456 EOf [root@localhost opt]# cat test2.txt 123 456 EOf
[root@localhost opt]# vim test3.sh #!/bin/bash #引入变量 file="test4.sh" i=school cat > $file <<EOF I am going to $i EOF [root@localhost opt]# sh test3.sh [root@localhost opt]# ls test3.sh test4.sh [root@localhost opt]# cat test4.sh I am going to school
整体变量赋值
[root@localhost opt]# vim test3.sh #!/bin/bash #整体变量赋值 var="Great! I am going to school" myvar=$(cat <<EOF this is monday $var EOF ) echo $myvar [root@localhost opt]# sh test3.sh this is monday Great! I am going to school
Expect实现免交互
用tcl语言写的一个工具,主要用自动化控制和测试。解决shell脚本交互的问题。
转义符:
\n:换行
\r:回车
\t:相当于一个tab键
\b:表示退格,删除
[root@localhost opt]# vim passwd.sh #!/usr/bin/expect #声明解释器,不再是默认的bash。需要声明 set timeout 5 #set设置,timeout超时时间,expect有一个默认的超时时间10秒。设置超时时间5秒 #set也可以作为设置变量 spawn passwd dn #spawn后面用来声明需要执行的命令,开启会话过程,并且跟踪后续的交互信息 expect "新的 密码*" #捕获需要执行的命令行,只要能够捕获即可,不需要完整的,可以*代表所有。 #捕获需要执行的命令行 send "123\r" #输入指令代码 expect "重新输入新的 密码:" send "123\r" #最后一定要有结束语,结束语只能写一个(expect eof或interact) #expect eof #交互指令结束之后,会退回原用户,切换回之前的用户 interact #留在当前用户,不会动 [root@localhost opt]# ./passwd.sh spawn passwd dn 更改用户 dn 的密码 。 新的 密码: 无效的密码: 密码少于 8 个字符 重新输入新的 密码: passwd:所有的身份验证令牌已经成功更新。
[root@localhost opt]# vim mjh2.sh #!/usr/bin/expect set timeout 5 #传参的方式来表示 set username [lindex $argv 0] set password [lindex $argv 1] #这种方式就是位置变量 #开始追踪 spawn su - $username #免交互开始执行 expect "密码" send "$password\r" #继续捕获: expect "~]$" send_user "ok" #send_user = echo 打印指定内容 #结束语 expect eof [zhang@localhost opt]$ ./mjh2.sh root 123 spawn su - root 密码: 上一次登录:二 6月 25 11:00:49 CST 2024从 192.168.60.1pts/0 上 [root@localhost ~]# ok[zhang@localhost opt]$
嵌入模式:
[root@localhost opt]# vim qiantao.sh #嵌入执行模式,在shell当中加入expect。涉及到环境的切换的场景不建议使用嵌套。 #ssh su不适合使用嵌入模式 #!/bin/bash user=$1 password=$2 #非交互命令,使用的是shell useradd $user #嵌入免交互 /usr/bin/expect <<-EOF spawn passwd $user expect "新的*" send "$password\r" expect "重新*" send "$password\r" expect eof EOF [root@localhost opt]# chmod 777 qiantao.sh [root@localhost opt]# ./qiantao.sh zxc 123 spawn passwd zxc 更改用户 zxc 的密码 。 新的 密码: 无效的密码: 密码少于 8 个字符 重新输入新的 密码: passwd:所有的身份验证令牌已经成功更新。
练习:
[root@test2 opt]# vim ssh.sh #进入命令行: spawn ssh $user@$ip expect {"yes/no" {send "yes\r";exp_continue} #这里捕获两次,表示该项被匹配之后,还能继续匹配其他的 指定内容。类似于循环的continue。允许expect语句继续向>> 下执行。"*password*" {send "$password\r"} } interact
[root@test2 opt]# vim ssh2.sh #!/usr/bin/expect set timeout 5 set hostname [lindex $argv 0] set password [lindex $argv 1] #进入命令格式: spawn ssh $hostname expect {"No route to host" {send_user "主机名/ip有误\n"}"Connection refused" {send_user "ssh连接拒绝\n"}"(yes/no)" {send "yes\r";exp_continue}"password" {send "$password\n"} } interact [root@test2 opt]# ./ssh2.sh root@192.168.60.30 123 spawn ssh root@192.168.60.30 root@192.168.60.30's password: Last login: Tue Jun 25 14:15:56 2024 from 192.168.60.20 [root@test3 ~]# exit 登出 Connection to 192.168.60.30 closed.
作业:
免交互实现硬盘分区,分一个区即可,分完之后,第一步要格式化,第二步实现挂载,挂载(手动挂载),然后在这个分区的挂载创建一个文件,写入内容“学习真好”,并且打印出结果
[root@test2 opt]# vim fdisk.sh #免交互实现硬盘分区,分一个区即可,分完之后,第一步要格式化,第二步实现挂载,挂载(手动 挂载),然后在这个分区的挂载创建一个文件,写入内容“学习真好”,并且打印出结果 #在一个脚本里完成,嵌入模式 #!/bin/bash disk=$1 /usr/bin/expect <<EOF spawn fdisk $disk expect "命令(输入 m 获取帮助):" send "n\r" expect "Select (default p): " send "p\r" expect "分区号 (1-4,默认 1):" send "\r" expect "起始 扇区 (2048-41943039,默认为 2048):" send "2048\r" expect "Last 扇区, +扇区 or +size{K,M,G} (2048-41943039,默认为 41943039):" send "\r" expect "命令(输入 m 获取帮助):" send "w\r" expect eof EOF mkfs.xfs -f /dev/sdc1 if [ $? -eq 0 ] then mkdir /opt/date mount /dev/sdc1 /opt/date file="/opt/date/date.txt" i="学习真好" cat > $file <<EOF $i EOF cat /opt/date/date.txt else echo "文件系统没创上" fi
运行截图