当前位置: 首页 > article >正文

shell编程之免交互

Here Document免交互

常用的交互程序:read,ftp,passwd,su,sudo。

cat也可配合免交互的方式重定向输出到文件。

Here Document 的作用:

  • 使用I/O重定向的方式将命令列表提供给交互式程序;
  • 标准输入的一种替代品

语法格式: (开始标记和终止标记之间,是输入的内容)

命令 <<标记
 ......
 ......
标记

Here Document使用注意事项

  • 标记可以使用任意合法字符,但开始标记与结尾标记需要保持一致。(常用标记EOF,使用其他字母也可以)
  • 结尾的标记一定要顶格写,前面不能有任何字符。
  • 结尾的标记后面也不能有任何字符(包括空行)。
  • 开头标记前后的空格会被省略掉。

Here Document基本用法

通过read命令接收输入并打印

read只能读取一行内容,只要遇到换行符就算一行结束,read就终止。

[root@yuji ~]# read i <<EOF
 > hello world
 > EOF
 [root@yuji ~]# echo $i
 hello world
 [root@yuji ~]# read a <<EOF
 > hello
 > world 
 > EOF
 [root@yuji ~]# echo $a      //read只能读取一行内容
 hello

统计输入的行数

将输入的内容传给wc命令。

开头和结尾的标记,一定要保持一致。

[root@yuji ~]# wc -l <<EOF    //标记是EOF
 > 111
 > 222
 > 333
 > EOF
 3
 [root@yuji ~]# wc -l <<abc   //标记是abc
 > 111
 > 222
 > 333
 > EOF     //这里的EOF只会被当作普通的行内容
 > abc
 4

免交互修改用户密码

 [root@yuji ~]# passwd nancy <<EOF
 > abc123
 > abc123
 > EOF
 更改用户 nancy 的密码 。
 新的 密码:无效的密码: 密码少于 7 个字符
 重新输入新的 密码:passwd:所有的身份验证令牌已经成功更新。

cat命令+免交互

使用cat 打印。

使用cat命令+免交换的方式,重定向输出到文件。

[root@yuji ~]# cat <<EOF
 > hello world
 > today is a good day~
 > EOF
 hello world
 today is a good day~
 [root@yuji ~]# cat <<EOF > hello.txt   //将内容重定向输出到文件中
 > hello world
 > today is a good day
 > EOF
 [root@yuji ~]# cat hello.txt
 hello world
 today is a good day

tee命令(同时实现 标准输出+重定向输出)

[root@yuji ~]# tee h2.txt <<EOF
 > hello
 > world
 > EOF
 hello
 world
 [root@yuji ~]# cat h2.txt
 hello
 world

Here Document 变量的使用

Here Document也支持变量的使用。

如果标记之间有变量被使用,会先替换变量值。如果想要将一些内容写入文件,除了常规的方法外,也可以使用 Here Document。

如果写入的内容中包含变量,在写入文件时要先将变量替换成实际值,再结合cat命令完成输出。

重要::::

涉及到换行时,输出变量要加双引号

如果涉及到换行,输出变量时要加双引号,不然会显示在同一行。

[root@yuji ~]# cat c1.sh
 #!bin/bash
 var="I am going to school!"
 ​
 myvar=$(cat <<EOF
 hello world
 today is good day
 $var
 EOF
 )
 #涉及到换行时,输出变量要加双引号
 echo "$myvar"
 ​
 [root@yuji ~]# bash c1.sh
 hello world
 today is good day
 I am going to school!

输入的内容不进行变量的替换

 [root@yuji ~]# cat c2.sh
 #!bin/bash
 var="I am going to school!"
 ​
 #开始标记加上单引号后,输入的内容不会进行变量的替换
 myvar=$(cat << 'EOF'
 hello world
 today is good day
 $var
 EOF
 )
 #涉及到换行时,输出变量要加双引号
 echo "$myvar"
 ​
 [root@yuji ~]# bash c2.sh
 hello world
 today is good day
 $var

示例3:多行注释

使用冒号为开头的Here Document,是多行注释。输入的内容不会被执行。(一般直接使用#进行注释

[root@yuji ~]# cat c3.sh
 #!bin/bash
 ​
 : << EOF
 echo "hello world"
 EOF
 ​
 echo "myvar"
 
[root@yuji ~]# bash c3.sh
myvar

示例4: 忽略行首TAB键

如果希望忽略每行行首的tab键,在开始标记前加 - 。

注意:<< 和 - 之间不能有空格。

 [root@yuji ~]# cat c4.sh
 #!bin/bash
 var="I am going to school!"
 ​
 #开始标记加上 - 后,会忽略每行行首的tab键。<< 和 - 之间不能有空格。
 myvar=$(cat <<-'EOF'
     hello world
         today is good day
     $var
 EOF
 )
 #涉及到换行时,输出变量要加双引号
 echo "$myvar"

 [root@yuji ~]# bash c4.sh
 hello world
 today is good day
 $var

Expect

Expect是建立在 tcl 语言基础上的一个工具,常被用于进行自动化控制和测试,解决shell脚本中交互相关的问题。

需要安装两个软件包:expect,tcl。

建立在 tcl 语言基础上的一个工具,常被用于进行自动化控制和测试,解决 shell 脚本中交互相关的问题

Expect基本命令

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支持多个分支
 expect               #只要匹配了其中一个情况,执行相应的send语句后退出该 expect 语句
 {
 "密码1" {send "abc123\r"}
 "密码2" {send "123456\r"}
 "密码3" {send "123123\r"}
 }

5、结束符(expect eof 与 interact 只能二选一)

1)expect eof

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

2)interact

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

注意:expect eof 与interact只能二选一

6、 set 设置会话超时时间

  • expect 默认的超时时间是10秒,通过set 命令可以设置会话超时时间,若不限制超时时间则应设置为-1
  • 例如: set time out 30

7、exp_continue

  • exp_continue 附加于某个 expect 判断项之后,可以使该项被匹配后,还能继续匹配该 expect 判断语句内的其他项。
  • exp_continue 类似于控制语句中的 continue 语句。表示允许 expect 继续向下执行指令。
  • 并行执行,exp_continue 前面的匹配如果有就执行,没有就不执行;但后面的一定会执行。

8、send_users

  • 表示回显命令,相当于echo

9、接收参数

  • expect 脚本可以接受从bash命令行传递参数,使用 [lindex $argv n]获得。其中你从0开始,分别表示第一个,第二个,第三个.....参数
set hostname [lindex $argv 0]   相当于 hostname=$1
 set password [lindex $argv 1]   相当于 passswd=$2
 set hostname [lindex $argv 0]   相当于 hostname=$1
 set password [lindex $argv 1]   相当于 passswd=$2

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

案例1:passwd修改用户密码

#!/usr/bin/expect
 ​
 #设置expect等待的超时时间,默认是10s 
 set timeout 5
 ​
 #先用spawn开启对一个有交互过程命令进程的跟踪
 spawn passwd helen
 ​
 #用expect捕捉系统的交互提示信息。第一次匹配
 expect "新的 密码"
 ​
 #当expect匹配成功则会模拟用户发送字符串给交互进程,字符串结尾记得加\r或者\n
 send "abc1234\r"      
 ​
 #第二次匹配
 expect "重新输入新的 密码" {send "abc1234\r"}
 expect eof 

案例2:su命令切换用户

#!/usr/bin/expect
 #example:./expect2.sh <用户名> <密码>
 ​
 #设置超时时间
 set timeout 5
 ​
 #定义传入参数
 set username [lindex $argv 0]
 set password [lindex $argv 1]
 ​
 #开始追踪命令
 spawn su $username
 ​
 #免交互执行,用expect匹配系统提示信息,再用send模拟用户发送内容
 expect "密码:"
 send "$password\r"
 ​
 expect "*]#"
 #send_user表示回显命令,相当于echo
 send_user "sucessfully"
 ​
 #免交互结束后把控制权交给用户,并不会退回原用户
 #interact
 ​
 #免交互结束后会在超时等待时间过后退回原用户
 expect eof

案例3: 设置ssh免交互远程连接

#!/usr/bin/expect
 # ssh免交互,example:./demo3.sh <IP|hostname> <密码>
 ​
 #设置变量名,变量值来自位置变量1
 set hostname [lindex $argv 0]      
 set password [lindex $argv 1]
 ​
 #启动进程并跟踪
 spawn ssh root@$hostname
 expect {
     "No route to host" exit
     "Connection refused" exit
     #exp_continue 前面的匹配如果有就执行,没有就不执行;但后面的一定会执行。
     "(yes/no)" {send "yes\r;exp_continue"}
     "password" {send "$password\r"}
 }
 interact
 #interact后面的命令都不起作用

嵌套模式,将expect过程融入shell当中,方便出路和执行和处理

#!/bin/bash
disk=$1
/usr/bin/expect <<-EOF
spawn fdisk $disk
expect "Command" {send "n\r"}
expect "Select" {send "\r"}
expect "Partition" {send "\r"}
expect "First sector" {send "\r"}
expect "Last sector" {send "\r"}
expect "Command (m for help)" {send "w\r"}
expect eof
EOF          
partprobe
mkfs.xfs ${disk}1 -f &> /dev/null
if [ $? -eq 0 ]
then 
echo "磁盘格式化完成"
mkdir  /opt/disk
mount ${disk}1 /opt/disk
df -h
else
echo "格式化失败,脚本出错"
fi


http://www.kler.cn/a/6174.html

相关文章:

  • 比Qt更适合小公司的C++界面开发框架wxWidgets
  • 用户界面的UML建模10
  • 你已经分清JAVA中JVM、JDK与JRE的作用和关系了吗?
  • Outlook2024版如何回到经典Outlook
  • 【LLM-Agent】Building effective agents和典型workflows
  • 浅谈分布式共识算法
  • 为你的网站加上Loading等待加载效果吧 | Loading页面加载添加教程
  • 金丹三层 —— 内存函数和字符串操作函数详解
  • Android MediaCodec设置H264 Profile到High
  • Hadoop - HDFS文件系统
  • 宝塔Linux面板部署Python flask项目
  • MacOS中安装和配置Podman
  • linux系统编程(6)--守护进程
  • IDEA vs Eclipse:使用体验对比
  • 蓝桥杯算法全集之多重背包问题I(动态规划算法)
  • Vim超详细下载安装与使用教程
  • C语言模拟实现:atoi函数
  • unity物理碰撞检测和触发器碰撞检测的区别
  • 强引用和弱引用区别
  • php面向对象讲解
  • 2023年全国最新保安员精选真题及答案42
  • 计算机网络中端到端与点到点的区别
  • 【创作赢红包】求最大公因数与最小公倍数
  • 【新2023Q2模拟题JAVA】华为OD机试 - 总最快检测效率 or 核酸检测效率
  • 【云原生进阶之容器】第五章容器运行时5.5--容器运行时之Kata Containers
  • 2023年南京晓庄学院五年一贯制专转本秘书学专业考试大纲