shell编程之免交互

一.交互、免交互概念

1.交互

人工发出指令控制程序的运行,程序在接收到人工相应的指令后,做出相应的反应

2.免交互

程序按照编写好的运行方式进行指定指令的动作,在这过程中,不需要人工进行指定操作,自动化完成

二.Here Document 概述及常规用法

1.特点

(1)使用I/O重定向的方式将命列表提供给交互式程序

(2)口标准输入的一种替代品

(3)语法格式

命令 <<标记

标记

2.免交互重定向输入

2.1一般格式

[root@test1 opt]# read i <<EOF
> zjf,123
> EOF
[root@test1 opt]# echo $i
zjf,123

2.2 用免交互的方式给用户zhangsan设置密码

[root@test1 opt]# useradd zhangsan
[root@test1 opt]# passwd zhangsan <<EOF
> 123
> 123
> EOF
更改用户 zhangsan 的密码 。
新的 密码:无效的密码: 密码少于 8 个字符
重新输入新的 密码:passwd:所有的身份验证令牌已经成功更新。

2.3 通过cat实现查看和重定向输出到指定文件

[root@test1 opt]# cat <<EOF
> this is an apple
> yes
> EOF
this is an apple
yes
[root@test1 opt]# cat <<EOF>test5.txt
> this is an apple
> yes
> EOF
[root@test1 opt]# cat test5.txt 
this is an apple
yes

3.Here Docunment 变量设定

3.1 变量替换

[root@test1 opt]# vim zz.sh 
[root@test1 opt]# cat zz.sh 
file="xx.txt"
i="banana"
cat > $file <<EOF
this is a $i
EOF
[root@test1 opt]# sh zz.sh 
[root@test1 opt]# cat xx.txt 
this is a banana
[root@test1 opt]# vim qq.sh 
[root@test1 opt]# cat qq.sh 
var="GREAT! i am going to school!"
cat > rr.txt <<EOF
today is monday
$var
EOF
[root@test1 opt]# sh qq.sh 
[root@test1 opt]# cat rr.txt 
today is monday
GREAT! i am going to school!

3.2 整体赋值变量

[root@test1 opt]# vim ztfz.sh
[root@test1 opt]# cat ztfz.sh 
var="GREAT! i am going to school!"
myvar=$(cat <<EOF
today is monday
$var
EOF
)
echo $myvar
[root@test1 opt]# sh ztfz.sh 
today is monday GREAT! i am going to school!

3.3 关闭免交互

[root@test1 opt]# vim ztfz.sh
[root@test1 opt]# cat ztfz.sh 
var="GREAT! i am going to school!"
myvar=$(cat <<'EOF'
today is monday
$var
EOF
)
echo $myvar
[root@test1 opt]# sh ztfz.sh 
today is monday $var

4.去掉每行前面的TAB字符

tab键的空可以去掉

空格不可以去掉

[root@test2 ~]# cat qd.sh 
cat <<-'EOF'
		zjf
 123
EOF
[root@test2 ~]# sh qd.sh 
zjf
 123

5.使用免交互方式实现多行注释

[root@test2 ~]# cat qd.sh 
: <<-'EOF'
		zjf
 123
EOF
[root@test2 ~]# sh qd.sh 
[root@test2 ~]# 

三.Expect 概述

1.概述

(1)建立在tcl之上的一个工具

(2)用于进行自动化控制和测试

(3)解决shel脚本中交互相关的问题

2.Expect安装

[root@test2 ~]# rpm -q expect
未安装软件包 expect 
[root@test2 ~]# yum -y install expect

3.expect中的基本命令

3.1 脚本解释器

expect 脚本中首先引入文件,表明使用的是哪一个 shell。#!/usr/bin/expectchmod 777 xxx. sh
bash sh

./

3.2 spawn

spawn 后面通常跟一个Linux执行命令,表示开启一个会话、启动进程,并跟踪后续交互信息。例: spawn passwd root

3.3 expect

判断上次输出结果中是否包含指定的字符串,如果有则立即返回,否则就等待超时时间后返回;只能捕捉由spawn启动的进程的输出:用于接收命令执行后的输出,然后和期望的字符串匹配.

3.4 send

向进程发送字符串,用于模拟用户的输入;该命令不能自动回车换行,
一般要加\r (回车) 或者\n
例:
方式一:
expect"密码”{send “abc123\r”} #同一行send部分要有{}
方式二:

expect"密码”

send “abc123\r” #换行send部分不需要有{ }

方式三:
expect支持多个分支
expect #只要匹配了其中一个情况,执行相应的send语句后退出该expect语句
{
“密码1” {send “abc123\r”}

“密码2” {send “123456\r”}

“密码3” {send “123123\r”}

}

3.5 结束符

3.5.1 expect_eof——————切换之前的终端用户

表示交互结束,等待执行结束,退回到原用户,与spawn对应。比如切换到root用户,expect脚本默认的是等待10s,当执行完命令后,默认停留10s后,自动切回了原用户。

3.5.2 interact——————留在当前终端用户

执行完成后保持交互状态,把控制权交给控制台,会停留在目标终端而不会退回到原终端,这个时候就可以手工操作了,interact后的命令不起作用,比如interact后添加exit,并不会退出root用户而如果没有interact则登录完成后会退出,而不是留在远程终端上。使用interact会保持在终端而不会退回到原终端,比如切换到root用户,会一直在root用户状态下:比如ssh到另一服务器,会一直在目标服务器终端,而不会切回的原服务器。

注意: expect_eof 与 interact 只能二选一。

3.6 set

expect 默认的超时时间是 10 秒,通过 set 命令可以设置会话超时时间,若不限制超时时间则应设置为-1。

例: set timeout 5

3.7 exp_continue

exp_continue 附加于某个 expect 判断项之后,可以使该项被匹配后,还能续匹配该 expet 判断语句内的其他项。exp continue 类似于控制语句中的 continue 语句。表示允许 expect 继续向下执行指令。例如:下例将判断交互输出中是否存在 yes/no 或 password。如果匹配 yes/no 则输出 yes 并再次执行判断:如果匹配password 则输出 abc123 并结束该段 expect 语句。

3.8 send_user

send_user 表示回显命令,相当于 echo。打印的功能

3.9 接收参数

expect 脚本可以接受从bash命令行传递的参数,使用[lindex Sargv n]获得。其中n从0开始,分别表示第一个,第二个,第三个…参数。类似与位置变量,用法相同

例:

set hostname [lindex Sargv 0] ——————相当子 hostname=S1

set password [lindex Sarqy 1]————————相当于 password=S2

注意: expect脚本不能通过bash、 source、来执行(因为这三种方式是调用shell解释器),只能通过绝对路径或相对路径来执行。

四.典型示例

1.免交互预设值修改用户密码

[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                    #退出
[root@test1 opt]# chmod 777 passwd.sh 
[root@test1 opt]# ./passwd.sh
spawn passwd zjf
更改用户 zjf 的密码 。
新的 密码:
无效的密码: 密码少于 8 个字符
重新输入新的 密码:
passwd:所有的身份验证令牌已经成功更新。

2.用传参的方式切换用户

expect eof 结束语

vim chuancan.sh 
#!/usr/bin/expect
set timeout 3

set username [lindex $argv 0]         #相当于$1
set password [lindex $argv 1]         #相当于$2

spawn su - $username

expect "Password:"
send "$password\r"
expect "*]$"                 #判断捕获 * 表示所有]前的所有
send_user "ok"
expect eof                   #跳出当前终端回到之前终端
[root@test1 opt]# chmod 777 chuancan.sh  
[root@test1 opt]# su - zjf
上一次登录:四 6月  8 19:28:03 CST 2023pts/7 上
[zjf@test1 ~]$ cd /opt/
[zjf@test1 opt]$ ./chuancan.sh lisi 123
spawn su - lisi
密码:
上一次登录:四 6月  8 19:30:44 CST 2023pts/7 上
[lisi@test1 ~]$ ok[zjf@test1 opt]$ 

interact 结束语

[root@test1 opt]# vim chuancan.sh 

#!/usr/bin/expect
set timeout 3

set username [lindex $argv 0]
set password [lindex $argv 1]

spawn su - $username

expect "Password:"
send "$password\r"
expect "*]$"
send_user "ok"
interact
[root@test1 opt]# chmod 777 chuancan.sh 
[root@test1 opt]# su - lisi
[lisi@test1 ~]$ cd /opt/
[lisi@test1 opt]$ ./chuancan.sh zjf 123
spawn su - zjf
密码:
上一次登录:四 6月  8 19:39:13 CST 2023pts/8 上
最后一次失败的登录:四 6月  8 19:43:54 CST 2023pts/2 上
最有一次成功登录后有 2 次失败的登录尝试。
[zjf@test1 ~]$ ok
[zjf@test1 ~]$ 

3.使用嵌套模式添加用户并输入密码

[root@test1 opt]# vim qtmo.sh

#!/bin/bash
user=$1
passwd=$2
useradd $1
/usr/bin/expect <<-EOF
spawn passwd $user
expect "新的 密码:"
send "${passwd}\r"
expect "重新输入新的 密码:"
send "${passwd}\r"
expect eof
EOF
[root@test1 opt]# chmod 777 qtmo.sh 
[root@test1 opt]# ./qtmo.sh ff 123    也可以用sh qtmo.sh dd 123方式
spawn passwd ff
更改用户 ff 的密码 。
新的 密码:
无效的密码: 密码少于 8 个字符
重新输入新的 密码:
passwd:所有的身份验证令牌已经成功更新。

4.使用免交互的方式实现ssh登录

4.1 指定变量方式

[root@test1 opt]# vim zdssh.sh

#!/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
[root@test1 opt]# chmod 777 zdssh.sh 
[root@test1 opt]# ./zdssh.sh 
spawn ssh root@192.168.198.12
root@192.168.198.12's password: 
Last failed login: Thu Jun  8 22:16:50 CST 2023 from 192.168.198.11 on ssh:notty
There were 4 failed login attempts since the last successful login.
Last login: Thu Jun  8 22:01:11 2023 from 192.168.198.1
[root@test2 ~]#     #如想退出终端在脚本命令中将interact修改为expect eof

4.2 使用传参的方式进行ssh免交互登录

[root@test1 opt]# vim ssh.sh 

#!/usr/bin/expect
set timeout 5
set hostname [lindex $argv 0]
set password [lindex $argv 1]

spawn ssh $hostname
expect {

     "connection refused" {send_user "ssh访问被拒绝\n"}
     "No route to host" {send_user "主机名/ip地址有误\n"}
     "yes/no" {send "yes\n";exp_continue}
     "password" {send "$password\n"}

}

interact
[root@test1 opt]# chmod 777 ssh.sh 
[root@test1 opt]# ./ssh.sh 192.168.198.14 123   #未开启的终端地址会直接报错
spawn ssh 192.168.198.14
ssh: connect to host 192.168.198.14 port 22: No route to host
主机名/ip地址有误

使输入密码的时候也免交互输入登录

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-KiRsj3Dy-1686235887057)(file:///C:\Users\zhao\AppData\Local\Temp\ksohtml10364\wps1.jpg)]
在这里插入图片描述

5.使用fdisk磁盘分区,格式化、挂载

[root@test1 ~]# vim fdisk.sh 
#!/bin/bash
/usr/bin/expect <<-EOF
set timeout 5
spawn fdisk /dev/sdb
expect {
 
    "命令(输入 m 获取帮助):" { send "n\n";exp_continue}
    "Select (default p): " {send "p\n";exp_continue}
    "分区号 (1-4,默认 1):" {send "\n";exp_continue}
    "起始 扇区 (2048-41943039,默认为 2048):" {send "\n";exp_continue}
    "Last 扇区*" {send "+10G\nw\n";exp_continue}    
expect eof
}
EOF

mkfs.xfs -f /dev/sdb1
mkdir /data
mount /dev/sdb1 /data
[root@test1 ~]# ./fdisk.sh

在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

一杯甜酒z

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值