shell基础(三)函数

一、函数

function 函数名(){
    指令。。
    return n
}

以上可以简写成:
函数名(){
    指令..
    return n
}

二、函数的执行

一:不带参数的执行
1.function和后面的小括号都不带吗,仅仅时函数名就可以执行
2.函数的定义必须在执行之前定义或加载(即先定义后执行)
3.函数执行时,会和脚本公用变量,也可以为函数设定局部变量及特殊位置参数
4.函数中的return和脚本中的exit功能类似,return用来退出函数,exit是用来退出脚本
5.return的返回值会给调用函数的程序,而exit的返回值给执行程序的shell
6.如果讲函数独立与脚本之外,被脚本加载使用时,需要使用source或者"."来提前加载使用
  例如:
        . /etc/init.d/functions  #加载系统函数中的命令或者参数变量,以供后面的程序使用
7.local定义函数内部的局部变量,变量在离开函数后会消失

二:带参数的执行:
  函数名 参数1 参数2
1.shell的位置参数$1、$2、..$# 、$*、$?及$@都可以作为函数的参数使用,此时,父脚本的参数临时被隐藏,而$0仍然时父脚本的名称
2.当函数执行完成时,原来的命令行脚本的参数恢复
3.函数的参数变量是在函数体里面定义的

小插曲

1.使用cat命令追加多行,如打印选项菜单
cat <<END
    1.FIRST
    2.SECOND
    3.THIRD 
END

2.给输出的字体加颜色
echo -e 识别转义字符,这里识别字符的特殊含义,加颜色

 #颜色的开始
 RED_COLOR='\E[1;31m'
 GREEN_COLOR='\E[1;32m'
 YELLOW_COLOR='\E[1;33m'
 BLUE_COLOR='\E[1;33m'

 #颜色的结束
 RES='\E[0m'
  
 echo -e ${RED_COLOR} OLD ${RES}  #OLD是红色
 echo -e ${GREEN_COLOR} OLD ${RES} #OLD是绿色
 echo -e ${YELLOW_COLOR} OLD ${RES} #OLD是黄色
 echo -e ${BLUE_COLOR} OLD ${RES} #OLD是蓝色

实战题目一:

用shell脚本检查某网站是否存在异常

方式一(普通):
#!/bin/bash
 if [ $# -ne 1 ];then
        usage $"usage $0 url"
 fi
wget --spider -q -o /dev/null --tries=1 -T 5 $1 
#--spider用于测试,不下载,-q不在命令中显示 -o 输入到后面的文件中 ,--tries=number为尝试次数和-t一样  -T超时时间和--timeout一样 -S显示响应头
if [ $? -eq 0 ];then
        echo "ok"
else
        echo "error"
fi
方式二(函数封装):
#!/bin/bash
function Usage(){

        echo $"Usage:$0 url"
        exit 1
}
function check_url(){
        wget --spider -q -o /dev/null -t 1 -T 5 $1 
        if [ $? -eq 0 ];then
                echo "ok"
        else
                echo "error"
        fi 
}
function main(){
        if [ $# -ne 1 ];then
                Usage
        else
                check_url $1
        fi
}
main $*  #将脚本传入的参数全部都传到主函数中

实战题目二:参数传入脚本、检查某网站是否存在异常,以更专业的方式输出

#!/bin/bash
. /etc/init.d/functions  #调用(加载)系统函数,因为下面要用action函数
function Usage(){
        echo $"usage:$0 url"
        exit 1
}
function check_url(){
        wget --spider -q -o /dev/null -t 1 -T 5 $1
        if [ $? -eq 0 ];then
                action "test $1" /bin/true
        else
                action "test $1" /bin/false
        fi
}
function main (){
        if [ $# -ne 1 ];then
                Usage
        else
                check_url $1
        fi
}
main $*

效果如下:
[root@mycentos shell]# sh 3.sh www.baidu.com   
test www.baidu.com                                         [  OK  ]
[root@mycentos shell]# sh 3.sh www.baidu.c
test www.baidu.c                                           [FAILED]

实战题目三:用shell开发模块化rsync服务启动脚本

#!/bin/bash
#chkconfig:2345 21 81
#description
#上面2行是将rsync加入开机自启动服务

#调用系统函数
. /etc/init.d/functions


#输入错误提示
function Usage(){
        echo $"usage $0 {start|stop|restart}"
        exit 1
}


#启动服务
function Start(){
        rsync --daemon  #启动服务
        sleep 2    #启动服务2秒后再做判断

        if [ $(netstat -pantu | grep rsync | wc -l) -ne 0 ];then
                action "rsyncd is started" /bin/true
        else
                action "rsyncd is started" /bin/false
        fi
}
#停止服务
function Stop(){

        killall rsync&>/dev/null

        sleep 2

        if [ $(netstat -apntu| grep rsync | wc -l) -eq 0 ];then
                action "rsyncd is stopped" /bin/true
        else
                action "rsyncd is stopped" /bin/false
        fi
}

case "$1" in
 "start")
        Start
        ;;
 "stop")
        Stop
        ;;
 "restart")
        Stop
        sleep 1
        Start
        ;;
  *)
        Usage
esac

结果如下:
[root@mycentos init.d]# /etc/init.d/rsyncd start
rsyncd is started                                          [  OK  ]
[root@mycentos init.d]# lsof -i:873
COMMAND  PID USER   FD   TYPE DEVICE SIZE/OFF NODE NAME
rsync   1478 root    4u  IPv4  13067      0t0  TCP *:rsync (LISTEN)
rsync   1478 root    5u  IPv6  13068      0t0  TCP *:rsync (LISTEN)
[root@mycentos init.d]# /etc/init.d/rsyncd stop
rsyncd is stopped                                          [  OK  ]
[root@mycentos init.d]# lsof -i:873
[root@mycentos init.d]# /etc/init.d/rsyncd restart
rsyncd is stopped                                          [  OK  ]
rsyncd is started                                          [  OK  ]
[root@mycentos init.d]# lsof -i:873               
COMMAND  PID USER   FD   TYPE DEVICE SIZE/OFF NODE NAME
rsync   2379 root    4u  IPv4  19734      0t0  TCP *:rsync (LISTEN)
rsync   2379 root    5u  IPv6  19735      0t0  TCP *:rsync (LISTEN)

注:
1.在安装或者启动时,如果遇到找不到“/etc/rsync.conf”文件时,要用touch建立一个,实际工作中要写入东西,此处为了方便就不写,为了启动rsync服务即可
2.rsync具体的脱离xinetd启动的方式见"shell基础二"
3.放在/etc/init.d目录下就可以用service命令启动,启动前需要是脚本有执行权限,否则无法执行,也无法自动补全。
4.要加入开机自启动,则需要加如脚本中解释器下面2行,然后“chkconfig --add rsyncd”加入自启动 "rsyncd"是/etc/init.d目录下的服务名称

实战四:执行shell脚本,打印如下菜单,柑橘选择,给选择的水果加一种颜色。

1.红色的苹果
2.绿色的苹果
3.黄色的苹果
4.蓝色的苹果

方法一(普通版)
#!/bin/sh

#定义好颜色,方便后面使用
RED_COLOR='\E[1;31m'
GREEN_COLOR='\E[1;32m'
YELLOW_COLOR='\E[1;33m'
BLUE_COLOR='\E[1;34m'

RES='\E[0m'

cat <<END
====================
        1.红色的苹果
        2.绿色的苹果
        3.黄色的苹果
        4.蓝色的苹果
====================
END

read -p "input a munber you want:" NUM

case "$NUM" in
  1)
        echo -e ${RED_COLOR}apple${RES}
        ;;
  2)
        echo -e ${GREEN_COLOR}apple${RES}
        ;;
  3)
        echo -e ${YELLOW_COLOR}apple${RES}
        ;;
  4)
        echo -e ${BLUE_COLOR}apple${RES}
        ;;
  *)
        echo "usage:input {1|2|3|4}"
        exit 1
esac
方法二(函数封装):
#!/bin/sh

#定义好颜色,方便后面使用
RED_COLOR='\E[1;31m'
GREEN_COLOR='\E[1;32m'
YELLOW_COLOR='\E[1;33m'
BLUE_COLOR='\E[1;34m'

RES='\E[0m'

function Menu(){
cat <<END
====================
        1.红色的苹果
        2.绿色的苹果
        3.黄色的苹果
        4.蓝色的苹果
====================
END
}
function Usage(){

        echo "$usage:input a number{1|2|3|4}"
        exit 1
}
function Choose(){
read -p "input a munber you want:" NUM
case "$NUM" in
  1)
        echo -e ${RED_COLOR}apple${RES}
        ;;
  2)
        echo -e ${GREEN_COLOR}apple${RES}
        ;;
  3)
        echo -e ${YELLOW_COLOR}apple${RES}
        ;;
  4)
        echo -e ${BLUE_COLOR}apple${RES}
        ;;
  *)
        Usage
esac
}
function Main(){
        Menu
        Choose
}
Main             

效果如图:


image.png

实战五:紧接着上题,请开发一个给制定内容加上制定颜色的脚本

#!/bin/bash

RED_COLOR='\E[1;31m'
GREEN_COLOR='\E[1;32m'
YELLOW_COLOR='\E[1;33m'
BLUE_COLOR='\E[1;34m'

RES='\E[0m'

function Usage(){

        echo $"usage:$0 txt {red|green|yellow|pink}"
        exit 1
}

if [ $# -ne 2 ];then
           Usage
           exit
fi 
function Choose(){

        case "$2" in
                "red")
                        echo -e ${RED_COLOR}$1${RES}
                        ;;
                "green")
                        echo -e ${GREEN_COLOR}$1${RES}

                        ;;
                "yellow")
                        echo -e ${YELLOW_COLOR}$1${RES}
                        ;;
                "blue")
                        echo -e ${BLUE_COLOR}$1${RES}
                        ;;
                *)
                Usage
        esac
}
function Main(){
        Choose $1 $2
}
Main $*
注:
1.将参数二的颜色付给参数一
2.精确匹配单词的三种方式
  1.grep -w 'oldboy' file 
  2.grep "\boldboy\b" file
  3.grep "^oldboy$" file
以上都是将出现oldboy单词的行显示出来,而不是将包含oldboy的行显示出来

实战五:

启动Nginx服务的命令:/application/nginx/sbin/nginx
关闭Nginx服务的命令:/application/nginx/sbin/nginx -s stop

请开发脚本,以实现Nginx服务启动和关闭功能,具体脚本命令为/etc/init.d/nginxd {start|stop|restart},并通过chkconfig进行开机自启动

思路:
1.判断开启或关闭服务(一是检测pid文件是否存在,存在就是开启,不存在就是服务已经关闭),或者使用netstat链接数也可以
2.start和stop分别构成函数
3.对函数和命令运行的返回值进行处理
4.chkconfig实现服务自启动
代码:
#!/bin/sh
#chkconfig:2345 27 83
#description

source /etc/init.d/functions  #加载系统函数库

#定义文件路径
PATH="/application/nginx/sbin"
PID_PATH="/application/nginx/logs/nginx.pid"
REVEAL=0
function Usage(){
        echo $"usage:$0 {start|stop|restart}"
        exit 1
}
#判断参数的个数
if [ $# -ne 1 ];then
        Usage
fi
#开始函数
function Start(){
        if [ ! -f $PID_PATH ];then  #若原来服务是关闭的
                $PATH/nginx  #开启服务
                REVEAL=$?  

                if [ $REVEAL -eq 0 ];then  #判断是否开启
                        action "nginx is started" /bin/true

                else
                        action "nginx is started" /bin/false
                fi

        else
                echo "nginx is running"

        fi
        return $REVEAL
}
function Stop(){#结束函数

        if [ -f $PID_PATH ];then  #若原来服务是启动的
                $PATH/nginx -s stop  #关闭服务
                REVEAL=$?

                if [ $REVEAL -eq 0 ];then  #判断是否关闭
                        action "nginx is stopped" /bin/true
                else
                        action "nginx is stopped" /bin/false
                fi
                return $REVEAL
        else
                echo "nginx is no running"
        fi
        return $REVEAL
}

        case "$1" in
           "start")
                 Start
                REVEAL=$?
                ;;
           "stop")
                Stop
                REVEAL=$?
                ;;
           "restart")
                Stop
                Start
                REVEAL=$?
                ;;
                *)
                Usage
        esac

 exit $REVEAL

效果如下:

[root@mycentos init.d]# /etc/init.d/nginxd start
nginx is running
[root@mycentos init.d]# /etc/init.d/nginxd stop
nginx is stopped                                           [  OK  ]
[root@mycentos init.d]# /etc/init.d/nginxd start
nginx is started                                           [  OK  ]
[root@mycentos init.d]# lsof -i:80
COMMAND  PID  USER   FD   TYPE DEVICE SIZE/OFF NODE NAME
nginx   2928  root    6u  IPv4  23795      0t0  TCP *:http (LISTEN)
nginx   2929 nginx    6u  IPv4  23795      0t0  TCP *:http (LISTEN)
[root@mycentos init.d]# /etc/init.d/nginxd restart
nginx is stopped                                           [  OK  ]
nginx is started                                           [  OK  ]
[root@mycentos init.d]# lsof -i:80                
COMMAND  PID  USER   FD   TYPE DEVICE SIZE/OFF NODE NAME
nginx   2940  root    6u  IPv4  24824      0t0  TCP *:http (LISTEN)
nginx   2941 nginx    6u  IPv4  24824      0t0  TCP *:http (LISTEN)

彩蛋一枚

return :
    1.用来退出函数,后面的函数里面的内容不再执行
exit:
     2.用来退出脚本,后面的内容不再执行

function test(){
  return 1
}  
test    #函数执行完成后,$?会得到test中return后面的返回值
ls -l ./  #这条命令执行成功,$?变成0
function test2(){
  exit 99
} 
test2 #函数执行完成后,$?变成99,也就是exit后面的数值
$?的值会不断的改变,有别于其他语言的函数调用的返回值。

结果:

#!/bin/bash
function test(){
        return 8
}
echo $?  #0
test
echo $? #8
function test2(){
        return 9
}
echo $? #0
test2
echo $? #9
ls -l ./
echo $? #0
exit 10

此shell执行结束后,echo $? 结果是10
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,053评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,527评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,779评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,685评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,699评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,609评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,989评论 3 396
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,654评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,890评论 1 298
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,634评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,716评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,394评论 4 319
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,976评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,950评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,191评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,849评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,458评论 2 342

推荐阅读更多精彩内容

  • 8.10 shell特殊符号cut命令8.11 sort_wc_uniq命令8.12 tee_tr_split命令...
    awsome365阅读 194评论 0 0
  • 第 2 章 SHELL 基础知识2.1 shell脚本我们在上面简单介绍了一下什么是shell脚本,现在我们来进一...
    LiWei_9e4b阅读 1,552评论 0 0
  • 字符串 单引号和双引号的区别: 单引号 双引号 拼接字符串 字符串最好放到双引号中,防止中间有空格等情况。 获取字...
    零一间阅读 223评论 0 0
  • 什么是运维 术语名词 IDC--(Internet Data Center)互联网数据中心,主要服务包括整机租用、...
    lyh165阅读 2,667评论 0 19
  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,591评论 18 139