38、shell之免交互

免交互

交互:我们发出指令控制程序的运行,程序在接收到指令之后按照指令的效果做出对应的反应。

免交互:间接的,通过第三方的方式把指令传送给程序,不用直接的下达指令。

一、Here Document 免交互:

这是命令行格式,也可以写在脚本当中。通过i/o重定向的方式将命令的列表传送给交互式程序或目命令。

是标准输入的一种替代品。代替了人工的输入方式。

1.1、语法格式:

命令 (linux的系统命令) <<标记

内容1

内容2

内容3

标记

less 复制代码
[root@test1 opt]# wc -l <<xy102

> 123
> 234
> 456
> xy102
> 3
[root@test1 ~]# wc -l <<xy

> 1
> 2
> 3
> 4
> 5
> xy
> 5

1.2、注意事项:

1、标记可以任意合法字符(一般不用特殊字符,不以数字开头,通常用以EOF作为默认的标记位)

2、结尾的标记一定要顶格写。且前面不能有任何字符,空格也不行。

3、结尾的标记后面也不能有任何字符,包括空格。

1.3、免交互之重定向:

[root@test1 opt]# read i <<EOF
TES
EOF

[root@test1 opt]# echo $i
TES
[root@test1 opt]# passwd ly <<EOF

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

> 123
> abc
> ABC
> EOF
> [root@test1 opt]# cat test3.txt
> 1 www.kgc.com
> 2 mail.kgc.com
> 3 ftp.kgc.com
> 4 linux.kgc.com
> 5 blog.kgc.co
> 123
> abc
> ABC
[root@test1 opt]# tee test3.txt <<EOF  #<<覆盖
> 456
> 654
> EOF
> 456
> 654
> [root@test1 opt]# cat test3.txt
> 456
> 654

1.3、cat > $a <<EOF以及cat <<EOF引入变量值

file="test4.sh"
i=school
cat > $file <<EOF   #变量值引入file--test4.sh
I am going to $i
EOF

[root@test1 opt]# cat > test   ##在此基础上进行重定向输入到文件中;
asasa
sad
asd
asd
fss
[root@test1 opt]# cat > test <<EOF
> 123
> 234
> EOF
[root@test1 opt]# cat <<EOF

> 123
> 1234
> 345
> 2314
> EOF
> 123
> 1234
> 345
> 2314
##相当于cat一个文件,文件里面包含这些内容。免交互形式的写入内容
less 复制代码
[root@test1 opt]# vim test3.sh

#整体变量赋值
var="Great! i am going to sschool"
myvar=$(cat <<EOF
THIS is monday
$var   ##=Great! i am going to sschool
EOF
)
echo $myvar

[root@test1 opt]# sh test3.sh
THIS is monday Great! i am going to sschool

关闭EOF后,EOF内部变量失效变成字符串。

less 复制代码
[root@test1 opt]# vim test3.sh

var="Great! i am going to sschool"
myvar=$(cat <<'EOF'
THIS is monday
$var
EOF
)
echo $myvar



[root@test1 opt]# sh test3.sh
THIS is monday $var

[root@test1 opt]# cat <<'EOF'     
THIS is monday
$var
EOF

THIS is monday
$var
[root@test1 opt]# cat <<EOF##相当于cat一个文件,文件里面包含这些内容。
THIS is monday
$var
EOF
THIS is monday

二、Expect实现免交互

用tcl语言写的一个工具,主要用自动化控制和测试,解决shell脚本交互的问题。

转义符:

\n:换行

\r:回车

\t:相当于tab键

\b:表示退格,删除

需要安装软件

2.1、Expect免交互实现用户密码更改

less 复制代码
[root@test1 opt]# vim passwd

#!/usr/bin/expect
#声明解释器,不再是默认的bash。需要声明
#set设置,timeout超时时间,expect有默认超时时间是10秒,设置超时时间5秒。
#set也可以作为设置变量
spawn passwd ly
#spawn 后面用来声明需要执行的命令,开启会话过程,并且跟踪后续的交互信息。

expect "新的*"
#捕获需要执行的命令行,只要能捕获就行,不需要完整的,可以*代表所有

send "123\r"
#输入指令代码
expect "重新输入新的 密码:"

send "123\r"

#最后一定要有结束语,结束语只能写一个
expect eof
#交互指令结束之后,会退回原用户,5秒之后切换回原用户
#interact
#留在当前用户,不会动


[root@test1 opt]# chmod 777 passwd
[root@test1 opt]# ./passwd
spawn passwd ly
更改用户 ly 的密码 。
新的 密码:
无效的密码: 密码少于 8 个字符
重新输入新的 密码:
passwd:所有的身份验证令牌已经成功更新。
[root@test1 opt]# 

2.2、expect位置传参-----interact留在当前用户

less 复制代码
#!/usr/bin/expect
#声明解释器,不再是默认的bash。需要声明
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 打印指定内容
#结束语
interact

结果
[liyang@test1 ~]$ ./test1.sh ly 123
spawn su - ly
密码:
上一次登录:三 6月 26 00:55:13 CST 2024pts/3 上
[ly@test1 ~]$ ok

expect eof留在当前用户

less 复制代码
#!/usr/bin/expect
#声明解释器,不再是默认的bash。需要声明
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 打印指定内容
#结束语
#interact
expect eof



结果:

[root@test1 opt]# ./passwd ly
spawn su - ly
上一次登录:二 6月 25 11:19:38 CST 2024pts/3 上
[ly@test1 ~]$ 
[ly@test1 ~]$ ok[root@test1 opt]# 
[liyang@test1 ~]$ ./test1.sh ly 123
spawn su - ly
密码:
上一次登录:三 6月 26 00:47:40 CST 2024pts/2 上
[ly@test1 ~]$ ok[liyang@test1 ~]$ 

三、嵌入模式

3.1、/bin/bash嵌入模式

less 复制代码
#嵌入执行模式,在shell当中加入expect,涉及到环境切换的场景不建议使用嵌套。
#ssh su不适合使用嵌入模式
#!/bin/bash
user=$1
password=$2
#非交互指令,使用的是shell
useradd $user
#嵌入免交互
/usr/bin/expect <<-EOF
spawn password $user
expect "新的*"
send "$password\r"
expect "重新*"
send "$password\r"
expect eof
EOF


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

3.2、expect脚本内参数赋值

less 复制代码
[root@test1 opt]# vim ssh.sh

#!/usr/bin/expect
set ip 192.168.168.20   #相当于内部写入参数的值,spawn命令执行,直接使用。
set user root    ##此处规定了用户和密码
set password 123
set timeout 5
#进入命令行:
spawn ssh $user@$ip

expect {
        "yes/no" {send "yes\r";exp_continue}
#这里捕获两次,表示该项被匹配之后,继续匹配其他的指定内容。类似于循环的continue,允许。
        "password" {send "$password\r"}
}
interact

[root@test1 opt]# chmod 777 ssh.sh
[root@test1 opt]# ./ssh.sh
spawn ssh root@192.168.168.20
The authenticity of host '192.168.168.20 (192.168.168.20)' can't be established.
ECDSA key fingerprint is SHA256:yaufdRU2oi//z+PpV7wdWdPdTdEZT2SrypnKy30CsdY.
ECDSA key fingerprint is MD5:85:b0:7c:f3:f0:3a:95:f0:25:19:47:f4:90:46:bc:f5.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added '192.168.168.20' (ECDSA) to the list of known hosts.
root@192.168.168.20's password: 
Last login: Tue Jun 25 13:47:39 2024 from 192.168.168.11
[root@localhost ~]# 

[root@test1 opt]# vim ssh.sh
[root@test1 opt]# ./ssh.sh
spawn ssh root@192.168.168.20
root@192.168.168.20's password: 
Last login: Tue Jun 25 13:57:00 2024 from 192.168.168.10

3.3、expect脚本外部传参

less 复制代码
#!/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\r"}
}
interact



[root@test1 opt]# ./ssh1.sh root@192.168.168.20
spawn ssh root@192.168.168.20
root@192.168.168.20's password: 
Last login: Tue Jun 25 14:02:19 2024

[root@test1 opt]# ./ssh1.sh root@192.168.168.30
spawn ssh root@192.168.168.30
ssh: connect to host 192.168.168.30 port 22: No route to host
spawn_id: spawn id exp6 not open
    while executing
"interact"
    (file "./ssh1.sh" line 15)



[root@test1 opt]# ./ssh1.sh root@192.168.168.30
spawn ssh root@192.168.168.30
The authenticity of host '192.168.168.30 (192.168.168.30)' can't be established.
ECDSA key fingerprint is SHA256:yaufdRU2oi//z+PpV7wdWdPdTdEZT2SrypnKy30CsdY.
ECDSA key fingerprint is MD5:85:b0:7c:f3:f0:3a:95:f0:25:19:47:f4:90:46:bc:f5.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added '192.168.168.30' (ECDSA) to the list of known hosts.
root@192.168.168.30's password: 
Last login: Tue Jun 25 14:17:43 2024 from 192.168.168.11

四、作业:

#免交互实现硬盘分区,分一个区即可,第一步要格式化,第二部实现挂载,挂载(手动挂载),然后再这个分区的挂载创建一个文件,写入内容"学习真好",并且打印结果。

#在一个脚本里完成,嵌入模式。

less 复制代码
#免交互实现硬盘分区,分一个区即可,第一步要格式化,第二部实现挂载,挂载(手
动挂载),然后再这个分区的挂载创建一个文件,写入内容"学习真好",并且打印结>果。

#在一个脚本里完成,嵌入模式。
#!/bin/bash
#非交互指令
#免交互指令
/usr/bin/expect <<-EOF
spawn fdisk /dev/sdb
expect "命令(输入 m 获取帮助):"
send "n\r"
expect "Partition type:
   p   primary (0 primary, 0 extended, 4 free)
   e   extended
Select (default p):"
send "p\r"
expect "分区号 (1-4,默认 1):"
send "1\r"
expect "起始 扇区 (2048-41943039,默认为 2048):"
send "\r"
expect "Last 扇区, +扇区 or +size{K,M,G} (2048-41943039,默认为 41943039):
"
send "+5G\r"
expect "命令(输入 m 获取帮助):"
send "w\r"
expect eof
EOF
mkfs.xfs -f /dev/sdb1
if [ $? -eq 0 ]
then
echo "分区创建成功"
mkdir /opt/data
mount /dev/sdb1 /opt/data
cd /opt/data
echo "学习真好" > file
cat file
else
echo "分区或文件系统创建失败"
fi





[root@test1 opt]# ./fenqu.sh
spawn fdisk /dev/sdb
欢迎使用 fdisk (util-linux 2.23.2)。

更改将停留在内存中,直到您决定将更改写入磁盘。
使用写入命令前请三思。


命令(输入 m 获取帮助):n
Partition type:
   p   primary (0 primary, 0 extended, 4 free)
   e   extended
Select (default p): p
分区号 (1-4,默认 1):1
起始 扇区 (2048-41943039,默认为 2048):
将使用默认值 2048
Last 扇区, +扇区 or +size{K,M,G} (2048-41943039,默认为 41943039):+5G
分区 1 已设置为 Linux 类型,大小设为 5 GiB

命令(输入 m 获取帮助):w
The partition table has been altered!

Calling ioctl() to re-read partition table.
正在同步磁盘。
meta-data=/dev/sdb1              isize=512    agcount=4, agsize=327680 blks
         =                       sectsz=512   attr=2, projid32bit=1
         =                       crc=1        finobt=0, sparse=0
data     =                       bsize=4096   blocks=1310720, imaxpct=25
         =                       sunit=0      swidth=0 blks
naming   =version 2              bsize=4096   ascii-ci=0 ftype=1
log      =internal log           bsize=4096   blocks=2560, version=2
         =                       sectsz=512   sunit=0 blks, lazy-count=1
realtime =none                   extsz=4096   blocks=0, rtextents=0
分区创建成功
学习真好
相关推荐
天郁青3 小时前
数据库交互的本地项目:后台管理系统
数据库·交互
梓贤Vigo5 小时前
【Axure高保真原型】2级下钻条形图
交互·产品经理·axure·原型·中继器
Selina K8 小时前
shell脚本知识点记录
笔记·shell
不收藏找不到我9 小时前
浏览器交互事件汇总
前端·交互
梓贤Vigo11 小时前
【Axure高保真原型】PDF阅读器
交互·产品经理·axure·原型·中继器
梓贤Vigo11 小时前
【Axure视频教程】多选按钮控制元件显示和隐藏
交互·产品经理·axure·原型·中继器
梓贤Vigo12 小时前
【Axure高保真原型】视频列表播放器
交互·产品经理·axure·原型·中继器
小奥超人13 小时前
PPT文件设置了修改权限,如何取消权?
windows·经验分享·microsoft·ppt·办公技巧
flashman91115 小时前
python在word中插入图片
python·microsoft·自动化·word
徒步僧1 天前
ThingsBoard规则链节点:RPC Call Reply节点详解
qt·microsoft·rpc