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

文章目录

  • 一、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

shell脚本基础4——function函数、expect_第1张图片
2.全写式。

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

qingjun

shell脚本基础4——function函数、expect_第2张图片

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

shell脚本基础4——function函数、expect_第3张图片

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

shell脚本基础4——function函数、expect_第4张图片
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

shell脚本基础4——function函数、expect_第5张图片
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

shell脚本基础4——function函数、expect_第6张图片

1.3 引用局部变量

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

1.3.1 区分局部变量

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

shell脚本基础4——function函数、expect_第7张图片
2.此时引用函数,则执行函数体,会把函数里的echo $a打印出来,引用的是函数里的局部变量local a=20。
shell脚本基础4——function函数、expect_第8张图片

1.3.2 全局变量在函数外

1.此时定义第2个全局变量a=30,这样最后一行的echo $a输出的是全局变量a=30,因为后者全局变量会把前者覆盖,而不会覆盖函数里的局部变量a=20。
shell脚本基础4——function函数、expect_第9张图片

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

shell脚本基础4——function函数、expect_第10张图片
2.当全局变量在局部变量前面时,会覆盖函数外的全局变量,函数内的局部变量不受影响。

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

shell脚本基础4——function函数、expect_第11张图片

1.3.4 函数体直接输出具体值

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

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

shell脚本基础4——function函数、expect_第12张图片
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

shell脚本基础4——function函数、expect_第13张图片
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

shell脚本基础4——function函数、expect_第14张图片

二、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脚本
eof expect执行结束 退出
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 [email protected] df -Th     ##spawn固定写法,后面跟需要交互的命令,df -Th是交互完成后要执行的命令。
expect "*password"         ##期望匹配“*password”
send "citms@123\n"         ##发送密码,意思是写交互时要写入的密码。
expect eof                    ##期望结束。

shell脚本基础4——function函数、expect_第15张图片

2.4 例二

  • 例一写法有个弊端,就是当期望太多时,写出来的代码很长,所以可以使用以下这种写法。
[root@localhost ~]# cat qingjun.sh 
#!/usr/bin/expect
spawn ssh [email protected] 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 </dev/null
touch index.txt && echo 01 > serial
cd
(umask 077;openssl genrsa -out httpd.key 2048)


/usr/bin/expect <

shell脚本基础4——function函数、expect_第16张图片

你可能感兴趣的:(shell脚本,linux,bash,运维,自动化)