Shell高级用法

您所在的位置:网站首页 shell判断闰年 Shell高级用法

Shell高级用法

2023-08-20 20:18| 来源: 网络整理| 查看: 265

函数介绍(function用法) 1、function用法

1、函数function是由若干条shell命令组成的语句块,实现代码重用和模块化编程。

2、它与shell程序形式上是相似的,不同的是它不是一个单独的进程,不能独立运 行,而是shell程序的一部分,定义函数只对当前的会话窗口有效,如果再打开一个窗口再定义另外一个函数,就对另一个窗口有效,两者互不影响。

3、函数和shell程序比较相似,区别在于以下两种:

(1)Shell程序在子Shell中运行。

(2)而Shell函数在当前Shell中运行。因此在当前Shell中,函数可以对shell中变量进行修改。

2、定义函数

函数由两部分组成:函数名和函数体

help function 语法一: f_name (){ ...函数体... } 语法二: function f_name { ...函数体... } 语法三: function f_name () { ...函数体... }

可以使用declare -F 选项进行查看所有定义的函数,用unset 加上变量名 就可以删除定义的变量

3、函数的定义和使用:

1、函数的定义和使用:

(1)可在交互式环境下定义函数

(2)可将函数放在脚本文件中作为它的一部分

(3)可放在只包含函数的单独文件中

2、调用:函数只有被调用才会执行

调用:给定函数名

函数名出现的地方,会被自动替换为函数代码

3、函数的生命周期:被调用时创建,返回时终止

4、函数返回值

函数有两种返回值:

1、函数的执行结果返回值:

(1) 使用echo等命令进行输出

(2) 函数体中调用命令的输出结果

 

 

2、函数的退出状态码:

(1) 默认取决于函数中执行的最后一条命令的退出状态码

(2) 自定义退出状态码,其格式为:

return 从函数中返回,用最后状态命令决定返回值:

  (1)return 0 无错误返回。

  (2)return 1-255 有错误返回

5、使用函数文件

1、可以将经常使用的函数存入函数文件,然后将函数文件载入shell

2、文件名可任意选取,但最好与相关任务有某种联系。例如:functions.main

3、一旦函数文件载入shell,就可以在命令行或脚本中调用函数。可以使用set命 令查看所有定义的函数,其输出列表包括已经载入shell的所有函数

4、若要改动函数,首先用unset命令从shell中删除函数。改动完毕后,再重新载 入此文件

6、删除shell函数

1、现在对函数做一些改动后,需要先删除函数,使其对shell不可用。使用unset命 令完成删除函数

2、命令格式为: unset function_name 

示例: unset findit

            再键入set命令,函数将不再显示

3、环境函数

(1)使子进程也可使用

(2)声明:export -f function_name

(3)查看:export -f 或 declare -xf

7、函数参数

函数可以接受参数: 传递参数给函数:调用函数时,在函数名后面以空白分隔给定参数列表即可;

例如“testfunc arg1 arg2 ...”

在函数体中当中,可使用$1, $2, ...调用这些参数;还可以使用$@, $*, $# 等特殊变量

8、函数变量

变量作用域:

环境变量:当前shell和子shell有效

本地变量:只在当前shell进程有效,为执行脚本会启动专用子shell进程; 因此,本地变量的作用范围是当前shell脚本程序文件,包括脚本中的函数

局部变量:函数的生命周期;函数结束时变量被自动销毁

注意:如果函数中有局部变量,如果其名称同本地变量,使用局部变量

          在函数中定义局部变量的方法:local NAME=VALUE

 

实例1:

第一种写法:如果命令过多,这行执行不太方便

#!/bin/bash func_os_version () { # 定义一个function函数名为func_os_version,然后在大括号里边定义命令,取出操作系统的版本号,类似于定义别名一样 sed -nr 's/.* ([0-9]+)\..*/\1/p' /etc/redhat-release } echo OS version is `func_os_version` # 直接写上定义函数名称,或者用echo 加上反向单引号进行输出结果

查看输出结果:

[root@centos-7 ~]# bash osversion.sh OS version is 7

第二种写法:将定义的函数存放到文件中,并将要执行的脚本与定义的函数以及定义函数的文件名进行关联

[root@centos-7 ~]# cat functions # 将定义的函数放到functions文件中 func_os_version () { sed -nr 's/.* ([0-9]+)\..*/\1/p' /etc/redhat-release } [root@centos-7 ~]# cat osversion.sh # 将要执行脚本的函数名和上面定义函数名的文件进行关联 #!/bin/bash source functions # source functions是关联上面的文件 func_os_version # 关联functions里边定义的函数名 [root@centos-7 ~]# chmod +x osversion.sh # 对脚本加上执行权限 [root@centos-7 ~]# ./osversion.sh # 查看此时的执行结果即可 7 实例2:

第一步:先定义functions函数文件

[root@centos-7 data]# cat functions # 定义functions函数文件 func_is_digit(){ if [ ! "$1" ];then # 如果输入的信息不是空,就为真,但又不是数字 echo "Usage:func_is_digit number" # 请输入数字 return 10 elif [[ $1 =~ ^[[:digit:]]+$ ]];then # 如果输入是数字 return 0 # return 0 返回的是正确结果,但是不会推出脚本 else echo "Not a digit" # 如果上面都不是,就提醒不是数字 return 1 fi }

第二步:调用functions函数文件,并对不同的成绩分段进行判断

[root@centos-7 data]# cat score.sh #!/bin/bash source /data/functions # 调用指定的函数文件的绝对路径 read -p "Input your score:" SCORE func_is_digit $SCORE # 直接调用上面的functions文件 if [ $? -ne 0 ];then #判断上面的命令执行不等于0(不成功)就退出 exit else if [ $SCORE -lt 60 ];then # 如果成功了,对成绩的三种判断如下。 echo "You are loser" elif [ $SCORE -lt 80 ];then echo "soso" else echo "very good" fi fi 实例3

生产中function配合case语法:

#!/bin/bash #Author: liupengju #date: 2020-06-22 #TEL: xxxxxxxxxx #代码发布与回滚 set -e set -u #adx代码部署变量定义 ADX_DIR=/gnome/adx adx_new_version="gnome-adx-0.0.1-SNAPSHOT-jar-with-dependencies.jar" ADX_NEW_MD5=`md5sum $adx_new_version | awk '{ print $1 }'` #此行需要修改为cf平台的md5码 ADX_CHK_MD5="43bcfe7594f083a8653126e0896b93ac" #directAd代码部署变量定义 direct_DIR=/gnome/directAd/ direct_version="direct-ad-0.0.1-SNAPSHOT-jar-with-dependencies.jar" direct_MD5=`md5sum $direct_version | awk '{ print $1 }'` #direct_old_version=$(ls -l |tail -n1 | awk '{print $9}') #此行需要修改为cf平台的md5码 direct_CHK_MD5="03c3c2fc62b2edfc92e548351010ee9f" ##########部署directAd代码############################# fun_copy_direct_code(){ mv $direct_DIR/$direct_version $direct_DIR/bak/${direct_version}_$(date +"%F-%T") echo "-----上一个版本已经移动到备份目录" cp /data/$direct_version $direct_DIR && echo "-----代码复制成功!!!" } fun_chk_direct_code(){ if [[ "$direct_MD5" == "$direct_CHK_MD5" ]];then echo "-----代码校验成功" && echo "代码部署成功后MD5值为:$direct_MD5" else echo "-----代码校验失败" && exit fi } fun_deploy_direct_restart(){ #$direct_DIR/restart.sh systemctl restart httpd systemctl restart nginx echo "后端服务重启成功!!!" } fun_chk_direct_port1(){ #验证端口存活状态 PORT1=`ss -nlt|grep 8080 |awk -F"[[:space:]]+|:" '{ print $7}'` PORT2=`ss -nlt|grep 8182 |awk -F"[[:space:]]+|:" '{ print $7}'` for port in $PORT1 $PORT2;do echo "The port is:$port------监听端口正常" done } #############回滚direct代码################################### fun_rollback_direct_code(){ cd $direct_DIR/bak direct_old_version=$(ls -l |tail -n1 | awk '{print $9}') # 提取上一个版本的jar包 mv $direct_DIR/${direct_version} $direct_DIR/bak/${direct_version}_$(date +"%F-%T") mv $direct_DIR/bak/${direct_old_version} $direct_DIR/${direct_version} echo "------旧版本代码移动成功" direct_old_MD5=$(md5sum $direct_DIR/${direct_version} | awk '{print $1}') echo "代码回滚后MD5值为:$direct_old_MD5" } fun_rollback_direct_restart(){ #$direct_DIR/restart.sh systemctl restart httpd systemctl restart nginx echo "--------后端服务重启成功" } fun_chk_direct_port2(){ #验证端口存活状态 PORT1=`ss -nlt|grep 8080 |awk -F"[[:space:]]+|:" '{ print $7}'` PORT2=`ss -nlt|grep 8182 |awk -F"[[:space:]]+|:" '{ print $7}'` for port in $PORT1 $PORT2;do echo "The port is:$port------端口监听正常" done } #####################adx代码部署######################################## fun_copy_adx__code(){ mv $ADX_DIR/$adx_new_version $ADX_DIR/bak/${adx_new_version}_$(date +"%F-%T") echo "-----上一个版本已经移动到备份目录" cp /data/$adx_new_version $ADX_DIR && echo "-----代码复制成功!!!" } fun_chk_adx_code(){ if [[ "$ADX_NEW_MD5" == "$ADX_CHK_MD5" ]];then echo "-----代码校验成功" && echo "代码部署成功后MD5值为:$ADX_NEW_MD5" else echo "-----代码校验失败" && exit fi } fun_deploy_adx_restart(){ #$ADX_DIR/restart.sh systemctl restart httpd systemctl restart nginx echo "后端服务已经启动!!!" } #验证端口存活状态 fun_chk_adx_port1(){ PORT1=`ss -nlt|grep 8080 |awk -F"[[:space:]]+|:" '{ print $7}'` PORT2=`ss -nlt|grep 8182 |awk -F"[[:space:]]+|:" '{ print $7}'` for port in $PORT1 $PORT2;do echo "The port is:$port------监听的端口正常启动" done } ###################################adx代码回滚########################### fun_rollback_adx_code(){ cd $ADX_DIR/bak adx_old_version=$(ls -l |tail -n1 | awk '{print $9}') mv $ADX_DIR/${adx_new_version} $ADX_DIR/bak/${adx_new_version}_$(date +"%F-%T") mv $ADX_DIR/bak/${adx_old_version} $ADX_DIR/${adx_new_version} echo "------旧版本代码移动成功" adx_old_MD5=$(md5sum $ADX_DIR/${adx_new_version} | awk '{print $1}') echo "代码回滚后MD5值为:$adx_old_MD5" } fun_rollback_adx_restart(){ #$ADX_DIR/restart.sh systemctl restart httpd systemctl restart nginx echo "--------后端服务已经启动" } fun_chk_adx_port2(){ #验证端口存活状态 PORT1=`ss -nlt|grep 8080 |awk -F"[[:space:]]+|:" '{ print $7}'` PORT2=`ss -nlt|grep 8182 |awk -F"[[:space:]]+|:" '{ print $7}'` for port in $PORT1 $PORT2;do echo "The port is:$port-------端口监听正常" done } case $1 in direct_deploy) fun_copy_direct_code fun_chk_direct_code fun_deploy_direct_restart fun_chk_direct_port1 ;; direct_rollback) fun_rollback_direct_code fun_rollback_direct_restart fun_chk_direct_port2 ;; adx_deploy) fun_copy_adx__code fun_chk_adx_code fun_deploy_adx_restart fun_chk_adx_port1 ;; adx_rollback) fun_rollback_adx_code fun_rollback_adx_restart fun_chk_adx_port2 ;; esac 实例4: #!/bin/bash #Auth: liupengju #TEL: xxxxx ########部署完成校验####### ####验证adserver版本号############# fun_chk_adx_version(){ ansible adx -m shell -a 'md5sum /gnome/adx/gnome-adx-0.0.1-SNAPSHOT-jar-with-dependencies.jar' |awk '{print $1}'|sort |head -n62 |tee version_adx |cat -n adx_version=$(ansible adx -m shell -a 'md5sum /gnome/adx/gnome-adx-0.0.1-SNAPSHOT-jar-with-dependencies.jar' |awk '{print $1}'|sort |tail -n62 |uniq -c|awk '{print $2}') echo -e "\e[1;32m新发布的版本号为:$adx_version\e[0m" version1=$(diff metadata version_adx) if [ -z $version1 ];then echo -e "\e[1;32m代码部署成功 \e[0m" else echo -e "\e[1;31m请检查错误 \e[0m" fi } ####验证directAd版本号############ fun_chk_direct_version(){ ansible adx -m shell -a ' md5sum /gnome/directAd/direct-ad-0.0.1-SNAPSHOT-jar-with-dependencies.jar'|awk '{print $1}'|sort |head -n62 |tee version_direct |cat -n direct_version=$(ansible adx -m shell -a 'md5sum /gnome/directAd/direct-ad-0.0.1-SNAPSHOT-jar-with-dependencies.jar'|awk '{print $1}'|sort |tail -n62 |uniq -c|awk '{print $2}') echo -e "\e[1;32m新发布的版本号为:$direct_version\e[0m" version2=$(diff metadata version_direct) if [ -z $version2 ];then echo -e "\e[1;32m代码部署成功 \e[0m" else echo -e "\e[1;31m请检查错误 \e[0m" fi } ###验证8080端口状态############### fun_chk_8080_port(){ chk_ip_8080=$(ansible adx -m shell -a ' netstat -ntulp |grep 8080' |awk '{print $1}' |egrep "[0-9]+\.*" |sort | tee data_8080.bak |cat -n) DIR_8080=$(diff metadata data_8080.bak) if [ -z $DIR_8080 ];then echo -e "\e[1;32m端口检查成功,端口号:8080 \e[0m" else echo -e "\e[1;31m请检查错误 \e[0m" fi } ####验证8182端口状态############# fun_chk_8182_port(){ chk_ip_8182=$(ansible adx -m shell -a ' netstat -ntulp |grep 8182' |awk '{print $1}' |egrep "[0-9]+\.*" |sort |tee data_8182.bak |cat -n) DIR_8182=$(diff metadata data_8182.bak) if [ -z $DIR_8182 ];then echo -e "\e[1;32m端口检查成功,端口号:8182 \e[0m" else echo -e "\e[1;31m请检查错误 \e[0m" fi } case $1 in adx) fun_chk_adx_version fun_chk_8080_port fun_chk_8182_port ;; direct) fun_chk_direct_version fun_chk_8080_port fun_chk_8182_port ;; esac expect命令 

expect 语法:   

       expect [选项] [ -c cmds ] [ [ -[f|b] ] cmdfile ] [ args ]

选项

    -c:从命令行执行expect脚本,默认expect是交互地执行的   

      示例:expect -c 'expect "\n" {send "pressed enter\n"}

     -d:可以输出输出调试信息   

     示例:expect  -d ssh.exp

expect中相关命令 :

spawn:启动新的进程 send:用于向进程发送字符串 expect:从进程接收字符串 interact:允许用户交互,并停留在远程连接的主机上 exp_continue 匹配多个字符串在执行动作后加此命令

expect最常用的语法(tcl语言:模式-动作)

单一分支模式语法:

expect “hi” {send “You said hi\n"}

匹配到hi后,会输出“you said hi”,并换行

多分支模式语法: 

expect "hi" { send "You said hi\n" } \ "hehe" { send "Hehe yourself\n" } \ "bye" { send "Good bye\n" }

匹配hi,hello,bye任意字符串时,执行相应输出。等同如下: 

expect { "hi" { send "You said hi\n"} "hehe" { send "Hehe yourself\n"} "bye" { send " Good bye\n"} } 实例5 #!/usr/bin/expect set ip 192.168.8.100 set user root set password centos set timeout 10 spawn ssh $user@$ip expect { "yes/no" { send "yes\n";exp_continue } "password" { send "$password\n" } } interact 实例6:shell调用脚本expect #!/bin/bash ip=$1 user=$2 password=$3 expect


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3