shell脚本基础4——function函数、expect

news2024/11/28 1:43:03

文章目录

  • 一、function函数
    • 1.1 函数的定义使用
    • 1.2 函数参数
      • 1.2.1 脚本内传参
      • 1.2.2 脚本外传参
    • 1.3 引用局部变量
      • 1.3.1 区分局部变量
      • 1.3.2 全局变量在函数外
      • 1.3.3 全局变量在函数体
      • 1.3.4 函数体直接输出具体值
  • 二、expect命令
    • 2.1 常用命令
    • 2.2 安装使用
    • 2.3 例一
    • 2.4 例二
    • 2.5 例三

一、function函数

函数作用:

  1. 函数function是由若干条shell命令组成的语句块,定义函数后,可以通过引用函数实现代码重用和模块化编程,而不是重复写多段代码。
  2. 它与shell程序形式上是相似的,不同的是它不是一个单独的进程,不能独立运 行,而是shell程序的一部分,定义函数只对当前的会话窗口有效,如果再打开一个窗口再定义另外一个函数,就对另一个窗口有效,两者互不影响。
  3. 函数和shell程序比较相似,区别在于以下两种:
    • Shell程序在子Shell中运行。
    • 而Shell函数在当前Shell中运行,因此在当前Shell中,函数可以对shell中变量进行修改。

1.1 函数的定义使用

基本了解:

  • 函数由两部分组成:函数名和函数体。
  • 引用函数直接写函数名即可。

注意事项:

  1. 可以function 【函数名】() 定义,也可以直接【函数名】() 定义。比如function qingjun(),也可以写成qingjun(),项目中大都使用简写定义函数。
  2. 参数返回,可以显示加:return 返回,如果不加,将以最后一条命令运行结果,作为返回值。 return后跟数值n(0-255)

1.简写式。

[root@localhost ~]# cat qingjun.sh 
#!/bin/bash
qingjun() {
  echo 'hehe'
}

qingjun

在这里插入图片描述
2.全写式。

[root@localhost ~]# cat qingjun.sh 
#!/bin/bash
function qingjun() {
  echo 'hehe'
}

qingjun

在这里插入图片描述

1.2 函数参数

  • 在Shell中,调用函数时可以向其传递参数。在函数体内部,通过 $n 的形式来获取参数的值,例如,$1表示第一个参数,$2表示第二个参数…

1.2.1 脚本内传参

1.传入的第一个参数“start”对应函数里的$1,可选项有“start"、“stop”,若不是这两个选项则直接匹配*;传入的第二个参数“httpd”对应函数里的$2。

[root@localhost ~]# cat qingjun.sh 
#!/bin/bash
my_service(){
    case $1 in
        "start")
            echo "start $2"
            ;;
        "stop")
            echo "stop $2"
            ;;
        *)
            echo "Usage: service $2 start|stop"
            ;;
    esac
}

my_service start httpd

在这里插入图片描述

1.2.2 脚本外传参

  • 函数里的传参变量是根据变量在脚本里的位置来对应的,函数里的$1对应下面传参的第1个数或变量,不管你是不是$1(如下就是下面传入的参数$2对应函数里的$1),函数里的$2对应下面传参的第2个数或变量,以此类推。
  • 函数里的变量只能在脚本里进行传参,若脚本里没有定义传参变量或脚本里没有直接传参,则直接匹配*。

1.例一,脚本里定义传参变量$2,$1,这两个变量值分别对应函数里的$1,$2,所以看到脚本里的传参时不要被名称给误导了,只需按照参数顺序依次对应函数里的$1,$2,$3,$4…即可。

[root@localhost ~]# cat qingjun.sh 
#!/bin/bash
my_service(){
    case $1 in
        "start")
            echo "start $2"
            ;;
        "stop")
            echo "stop $2"
            ;;
        *)
            echo "Usage: service $2 start|stop"
            ;;
    esac
}
my_service $2 $1

在这里插入图片描述
2.例二。

[root@localhost ~]# cat qingjun.sh 
#!/bin/bash
my_service(){
    case $1 in
        "start")
            echo "start $2"
            ;;
        "stop")
            echo "stop $2"
            ;;
        *)
            echo "Usage: service $2 start|stop"
            ;;
    esac
}

my_service $1 $2

在这里插入图片描述
3.例三,脚本不传参,则直接匹配*。

[root@localhost ~]# cat qingjun.sh 
#!/bin/bash
my_service(){
    case $1 in
        "start")
            echo "start $2"
            ;;
        "stop")
            echo "stop $2"
            ;;
        *)
            echo "Usage: service $2 start|stop"
            ;;
    esac
}

my_service

在这里插入图片描述

1.3 引用局部变量

  • 局部变量使用local来定义,比如本地变量是a=10,定义成局部变量为local a=10。
  • 局部变量只对当前代码段生效。

1.3.1 区分局部变量

1.定义本地变量a=10对全局生效,函数里定义局部变量a=20只对当前函数代码块生效,所以在最后echo $a时,用的是全局变量a=10。那为什么没有把函数里的echo $a打印出来?是因为没有引用函数,所以不执行函数里的操作。

在这里插入图片描述
2.此时引用函数,则执行函数体,会把函数里的echo $a打印出来,引用的是函数里的局部变量local a=20。
在这里插入图片描述

1.3.2 全局变量在函数外

1.此时定义第2个全局变量a=30,这样最后一行的echo $a输出的是全局变量a=30,因为后者全局变量会把前者覆盖,而不会覆盖函数里的局部变量a=20。
在这里插入图片描述

1.3.3 全局变量在函数体

  • 当函数里即存在局部变量,也存在全局变量时,需要看两者的先后顺序,因为顺序不同覆盖效果也不同。
    • 若全局变量在局部变量后面,则覆盖函数内的局部变量。
    • 若全局变量在局部变量前面,则覆盖函数外的全局变量。

1.如下示例,有两个全局变量a=10和a=30,后者在函数内,此时a=30会覆盖局部变量a=20,函数外的全局变量不受影响,最后调用函数输出的是30。

[root@localhost ~]# cat qingjun.sh 
#!/bin/bash
a=10
my_service(){
    local a=20
    a=30
    echo $a
}
my_service
echo $a

在这里插入图片描述
2.当全局变量在局部变量前面时,会覆盖函数外的全局变量,函数内的局部变量不受影响。

[root@localhost ~]# cat qingjun.sh 
#!/bin/bash
a=10
my_service(){
    a=30
    local a=20
    echo $a
}
my_service
echo $a

在这里插入图片描述

1.3.4 函数体直接输出具体值

1.当函数体不存在局部变量时,此时会直接输出函数体结果,即时存在全局变量也是覆盖函数外的全局变量。

[root@localhost ~]# cat qingjun.sh 
#!/bin/bash
a=10
my_service(){
    a=30
    echo 50
}
my_service
echo $a

在这里插入图片描述
2.此时函数内添加局部变量,需要看添加位置,若是加在全局变量前面,则会被函数内的全局变量覆盖,但最终引用函数输出的值是具体值50,最后一行输出的值是函数外的全局变量值10。

[root@localhost ~]# cat qingjun.sh 
#!/bin/bash
a=10
my_service(){
    local a=20
    a=30
    echo 50
}
my_service
echo $a

在这里插入图片描述
3.当添加的局部变量在函数里的全局变量后面,则不会受影响,最后一行的echo $a是用的函数里的全局变量a=30,将函数外的a=10覆盖了。

[root@localhost ~]# cat qingjun.sh 
#!/bin/bash
a=10
my_service(){
    a=30
    local a=20
    echo 50
}
my_service
echo $a

在这里插入图片描述

二、expect命令

基本了解:

  • 若需要交互式的命令,比如ssh到其他机器,需要输入密码,scp命令这种需要交互式的输入密码则可以用expect。
  • expect是一个自动化交互套件,主要应用于执行命令和程序时,系统以交互形式要求输入指定字符串,实现交互通信。

expect自动交互流程:

  • spawn启动指定进程 ——> expect获取指定关键字 ——>send向指定程序发送指定字符 ——> 执行完成退出

2.1 常用命令

子命令释义
spawn交互程序开始后面跟命令或者指定程序
expect获取匹配信息匹配成功则执行expect后面的程序动作
send exp_send用于发送指定的字符串信息
exp_continue在expect中多次匹配就需要用到
send_user用来打印输出相当于she11中的echo
exit退出expect脚本
eofexpect执行结束 退出
set定义变量
puts输出变量
set_timeout设置超时时间

2.2 安装使用

  • 需要提前安装expect,之后才能在脚本中引用子命令。

1.安装。

yum install -y expect

2.查看。
在这里插入图片描述

2.3 例一

1.远程到192.168.130.161主机上,并且执行命令df -Th查看磁盘资源。

[root@localhost ~]# cat qingjun.sh 
#!/usr/bin/expect            ##固定写法,使用expect执行脚本。
spawn ssh root@192.168.130.161 df -Th     ##spawn固定写法,后面跟需要交互的命令,df -Th是交互完成后要执行的命令。
expect "*password"         ##期望匹配“*password”
send "citms@123\n"         ##发送密码,意思是写交互时要写入的密码。
expect eof                    ##期望结束。

在这里插入图片描述

2.4 例二

  • 例一写法有个弊端,就是当期望太多时,写出来的代码很长,所以可以使用以下这种写法。
[root@localhost ~]# cat qingjun.sh 
#!/usr/bin/expect
spawn ssh root@192.168.130.161 df -Th
expect {
    "*yes/no*" {send "yes\n"; exp_continue}    ##第一个期望,期望匹配“*yes/no*”时输入的值为“yes”,exp_continue代表继续。
    "*password:*" {send "redhat\n"}    ##第二个期望,期望匹配“*password:*”时输入的值为“redhat”,\n表示回车,不然输入密码后不会往后执行。
}
expect eof

2.5 例三

  • openssl签发CA证书。
[root@localhost ~]# cat qingjun.sh 
#!/bin/bash
  
if [ $UID -ne 0 ];then
    echo "请以管理员身份运行此脚本。"
    exit 120
fi

if [ ! -d /etc/pki/CA ];then
        mkdir -p /etc/pki/CA
fi
cd /etc/pki/CA
if [ ! -d private ];then
        mkdir -p private
fi
(umask 077;openssl genrsa -out private/cakey.pem 2048)

/usr/bin/expect <<EOF
spawn openssl req -new -x509 -key private/cakey.pem -out cacert.pem -days 365 
expect {
    "*code" {send "CN\n"; exp_continue}
    "Province" {send "HB\n"; exp_continue}
    "*city" {send "WH\n"; exp_continue}
    "*Company" {send "www.example.com\n"; exp_continue}
    "*section" {send "www.example.com\n"; exp_continue}
    "*hostname" {send "www.example.com\n"; exp_continue}
    "*Address" {send "1@2.com\n"}
}
expect eof
EOF


mkdir certs newcerts crl &>/dev/null
touch index.txt && echo 01 > serial
cd
(umask 077;openssl genrsa -out httpd.key 2048)


/usr/bin/expect <<EOF
spawn openssl req -new -key httpd.key -days 365 -out httpd.csr
expect {
    "*code" {send "CN\n";exp_continue}
    "*Province" {send "HB\n";exp_continue}
    "*city" {send "WH\n";exp_continue}
    "*Company" {send "www.example.com\n";exp_continue}
    "*section" {send "www.example.com\n";exp_continue}
    "*hostname" {send "www.example.com\n";exp_continue}
    "*Address" {send "1@2.com\n";exp_continue}
    "*password" {send "\n";exp_continue}
    "An*" {send "\n"}
}
expect eof
EOF

/usr/bin/expect <<EOF
spawn openssl ca -in httpd.csr -out httpd.crt -days 365
expect {
    "Sign*" {send "y\n";exp_continue}
    "*commit" {send "y\n"}
}
expect eof
EOF

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/628837.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Cmake工具的简单使用

引言 本篇文章讲述如何简单的使用cmake工具构建一个项目&#xff0c;帮助入门的c新手学会如何使用cmake. 我们在Clion新创建一个项目时&#xff0c;会发现&#xff0c;除了main.cpp文件之外&#xff0c;还存在一个build-debug目录和一个CMakelists.txt文件&#xff0c;如图: …

Spring Boot 集成 Redisson 实现分布式锁

Redisson 是一种基于 Redis 的 Java 驻留集群的分布式对象和服务库&#xff0c;可以为我们提供丰富的分布式锁和线程安全集合的实现。在 Spring Boot 应用程序中使用 Redisson 可以方便地实现分布式应用程序的某些方面&#xff0c;例如分布式锁、分布式集合、分布式事件发布和订…

Java学习记录

引入包 把jar包复制到lib下面&#xff0c;然后右键add as library 常用方法 读取文件&#xff1a;FileInputStream获得当前路径&#xff1a;System.getProperty(“user.dir”) 快捷键 https://blog.csdn.net/W_317/article/details/114300373 常用的 生成循环&#xff1…

VMware Workstation 16 安装教程

哈喽&#xff0c;大家好。今天一起学习的是VMware Workstation 16的安装&#xff0c;vm虚拟机是小编非常喜欢的生产力软件&#xff0c;小编之前发布的测试教程钧在vm上进行的实验。 VMware Workstation是一款功能强大的桌面虚拟计算机软件&#xff0c;它能够让用户在宿主机操作…

Coggle 30 Days of ML 打卡任务一:两个赛题数据可视化

Coggle 30 Days of ML 打卡任务一&#xff1a;两个赛题数据可视化 任务一&#xff1a;两个赛题数据可视化 难度/分值&#xff1a;低/1 打卡内容&#xff1a; 参赛选手名称&#xff1a;AppleDoctor完成日期&#xff1a;2023.6.6任务完成情况&#xff1a; 使用的编程语言&…

【你真的会斗图嘛?】Python爬虫实战项目——你想要的图都可以爬到(附安装地址)

目录 一、安装知识&#xff08;1&#xff09;Python环境变量&#xff08;2&#xff09;Pycharm开发工具&#xff08;3&#xff09;requests模块1、安装下载好Pycharm之后&#xff0c;找到终端进行下载requests模块2、输入下载语法&#xff1a;3、此次项目还需用到正则&#xff…

【STM32】制作一个bootloader

工作环境&#xff1a;STM32CubeMXKeil 相关环境准备这里就不介绍了。 bootloader是什么 bootloader就是单片机启动时候运行的一段小程序&#xff0c;这段程序负责单片机固件的更新&#xff0c;也就是单片机选择性的自己给自己下载程序。可以更新&#xff0c;可以不更新&…

C++课程设计:电梯控制系统程序设计

目录 电梯控制系统程序设计背景 类结构图 程序设计 程序释义 运行展示 总结与体会 电梯控制系统程序设计背景 电梯控制系统程序设计旨在通过C编程实现电梯的模拟功能&#xff0c;使用户能够选择上行或下行&#xff0c;并输入要进入的楼层&#xff0c;程序将模拟电梯运行过…

死锁细究!

一、死锁的定义&危害 1、死锁是什么 发生在并发中互不想让&#xff1a;当两个&#xff08;或更多&#xff09;线程&#xff08;或进程&#xff09;相互持有对方所需要的资源&#xff0c;又不主动释放&#xff0c;导致所有人都无法继续前进&#xff0c;导致程序陷入无尽的…

学生成绩管理系统(C语言)

学生成绩管理系统 一、实现思路二、代码的实现&#xff08;1&#xff09;构造功能框架&#xff08;2&#xff09;实现各项功能 三、完整的代码四、总结 本篇博客介绍一个关于学生成绩管理系统的C语言代码&#xff0c;包含读取成绩、计算各门课程的总分和平均分、按分数排序、按…

快速实现一个分布式定时器

定时器&#xff08;Timer&#xff09;是一种在业务开发中常用的组件&#xff0c;主要用在执行延时通知任务上。本文以笔者在工作中的实践作为基础&#xff0c;介绍如何使用平时部门最常用的组件快速实现一个业务常用的分布式定时器服务。同时介绍了过程中遇到问题的一些解决方案…

手机越狱:探索自由与风险的边界

&#x1f604;作者简介&#xff1a; 小曾同学.com,一个致力于测试开发的博主⛽️&#xff0c;主要职责&#xff1a;测试开发、CI/CD 如果文章知识点有错误的地方&#xff0c;还请大家指正&#xff0c;让我们一起学习&#xff0c;一起进步。&#x1f60a; 座右铭&#xff1a;不想…

100天精通Golang(基础入门篇)——第5天: Go语言中的数据类型学习

&#x1f337; 博主 libin9iOak带您 Go to Golang Language.✨ &#x1f984; 个人主页——libin9iOak的博客&#x1f390; &#x1f433; 《面试题大全》 文章图文并茂&#x1f995;生动形象&#x1f996;简单易学&#xff01;欢迎大家来踩踩~&#x1f33a; &#x1f30a; 《I…

htmlCSS-----盒模型

目录 前言&#xff1a; 盒子 1.内容区域 2. 边框 3. 内边距区域 4. 外边距区域&#xff08;margin&#xff09; 怪异盒模型 前言&#xff1a; 前面我们学习了CSS中的选择器的使用方法&#xff0c;那这一节我们就学习CSS中的盒模型&#xff0c;通过盒模型我们可以去更好的…

uni-app引入html2canvas截图以及截长图

下载安装html2canvas 方式一&#xff0c;https://www.bootcdn.cn/ CDN网站下载html2canvas插件 这里下载后放在测项目目录common下面 页面中引入 方式二、npm方式安装html2canvas 1、npm方式下载 npm i html2canvas2、引入html2canvas import html2canvas from html2can…

数据结构——广义表

文章目录 前言二、特殊矩阵的压缩存储数组的存储结构和实现按行优先存储按列优先存储 矩阵的压缩存储稀疏矩阵 广义表 总结 前言 数组&#xff0c;数组的压缩存储&#xff0c;广义表 二、特殊矩阵的压缩存储 数组的存储结构和实现 对于多维数组&#xff0c;可以分为按行优先…

UnityVR--组件9--视频组件VideoPlayer

目录 前言 参数解释 RenderMode渲染方式 VideoPlayer类中的API 前言 在之前的VR场景中已经使用过VideoPlayer播放视频&#xff08;Unity.UI的交互&#xff08;6&#xff09;-播放视频&#xff09;&#xff0c;不过在VR中设置是有些不同的&#xff0c;这里更详细地说明一下V…

8.面向对象编程(高级部分)|Java学习笔记

文章目录 类变量和类方法类变量类变量使用注意事项和细节 类方法类方法使用注意事项和细节 理解 main 方法语法代码块代码块使用注意事项和细节讨论 单例设计模式单例模式应用实例饿汉式 VS 懒汉式 final 关键字final 使用注意事项和细节 抽象类抽象类的介绍抽象类使用的注意事…

软件测试|测试金字塔是什么,它的目的是什么,以及它包含哪些层次?

一、测试金字塔的概念&#xff1a; 测试金字塔是2009年Mike Cohn在他的著作《Succeeding with Agile》一书正式提出的。他是一个类比的概念&#xff0c;形容每一层&#xff0c;或者说不同集成阶段测试覆盖率和知行效率之间的一个相对关系。 测试金字塔最初的原型分三层&#…

chatgpt赋能python:Python循环间隔-了解如何在循环中增加延时

Python循环间隔 - 了解如何在循环中增加延时 在Python编程中&#xff0c;循环是非常常见且重要的控制语句。 它使我们可以多次执行代码块。 但是&#xff0c;在有些情况下&#xff0c;您可能需要在循环之间增加一定的延时时间。 这就是Python循环间隔的概念。 在本文中&#x…