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
分区创建成功
学习真好
相关推荐
技术探索者1 小时前
Shell:如何判断两个字符串相等
linux·shell
未知百分百2 小时前
Django任意URL跳转漏洞(CVE-2018-14574)
后端·python·安全·web安全·网络安全·django·shell
AI 研究所5 小时前
讯飞星火V4.0 发布,全面对标GPT-4 Turbo
人工智能·语言模型·机器人·交互·语音
#卢松松#5 小时前
微软关闭中国所有线下店,并不影响全球第一
microsoft
syluxhch17 小时前
Windows快速打开某个路径下的PowerShell
windows·microsoft
GaoJamie1 天前
macOS如何查看终端的shell类型
macos·终端·shell
Learning改变世界1 天前
Shell代码解读
python·shell
V言微语1 天前
2.3.2 主程序和外部IO交互 (文件映射方式)----IO Client实现
交互
V言微语1 天前
2.2.4 C#中显示控件BDPictureBox 的实现----ROI交互
开发语言·c#·交互
小袁搬码1 天前
wget之Win11中安装及使用
windows·shell