全套学习资料移步至公众号【学神来啦】更多学习资料添加扣扣资源群:661308959

本节所讲内容:

  22.1  跳出循环

  22.2  Shift参数左移指令

  22.3  函数的使用

  22.4  实战-自动备份mysql数据库和nginx服务启动脚本

22.1  跳出循环break和continue

在我们使用循环语句进行循环的过程中,有时候需要在未达到循环结束条件时强制跳出循环,那么Shell给我们提供了两个命令来实现该功能:break和continue

Break:跳出整个循环

Continue:跳过本次循环,进行下次循环

break概述:跳出当前整个循环或结束当前循环,在for、while等循环语句中,用于跳出当前所在的循环体,执行循环体之后的语句,后面如果什么也不加,表示跳出当前循环等价于break 1,也可以在后面加数字,假设break 3表示跳出第三层循环

continue概述:忽略本次循环剩余的代码,直接进行下一次循环;在for、while等循环语句中,用于跳出当前所在的循环体,执行循环体之后的语句 

例1:写一个shell菜单,当按数字键4时退出,否则一直循环显示

[root@xuegod63 ~]# vim break-continue.sh

#! /bin/sh

while true

do

 echo "*******************************"

 echo "Please select your operation:"

 echo " 1 Copy"

 echo " 2 Delete"

 echo " 3 Backup"

 echo " 4 Quit"

 echo "*******************************"

 read op

 case $op in

    1)

 continue    #这里加了continue后,忽略本次循环剩余代码,后面内容都不执行了,直接进行下次一次循环

     echo "your selection is Copy"

 ;;

    2)

       echo "your selection is Delete"

 ;;

    3)

 echo "your selection is Backup"

 ;;

    4)

 echo "your selection is Exit"

 break    #跳出循环体

 ;;

     *)

  echo "invalid selection,please try again"

  esac

done

例2:使用交互式方法批量添加用户

[root@bogon sh]# vim useradd.sh

#!/bin/bash

echo     "*********************"

read -p  "请输入要创建的用户名:" name

read -p  "请输入要创建的用户数:" num

read -p  "请输入要创建用户密码:" pas

echo     "*********************"

for ((i=1;i<=$num;i=i+1))

do

        useradd $name$i &> /dev/null

        echo "$pas" | passwd --stdin $name$i &> /dev/null

done

echo "创建用户完成,结果是..."

tail -$num /etc/passwd

vim   userdel.sh

#!/bin/bash

echo "******************"

read -p "请输入要删除的用户名:" name

read -p "请输入要删除的用户数:" num

echo "******************"

for ((i=1;i<=$num;i++ ))

do

        if [ $i -eq 4 ];then

        continue

        #break

        else

        userdel -r $name$i &> /dev/null

        fi

done

echo "删除用户完成,结果是..."

tail -$num /etc/passwd

[root@xuegod63 ~]# vim break1.sh

#!/bin/bash

while :

do

    echo -n "输入 1 到 5 之间的数字:"

    read aNum

    case $aNum in

        1|2|3|4|5) echo "你输入的数字为 $aNum!"

        ;;

        *) echo "你输入的数字不是 1 到 5 之间的! 游戏结束"

            break

        ;;

    esac

done

[root@xuegod63 ~]# vim continue1.sh

#!/bin/bash

while :

do

    echo -n "输入 1 到 5 之间的数字: "

    read aNum

    case $aNum in

        1|2|3|4|5) echo "你输入的数字为 $aNum!"

        ;;

        *) echo "你输入的数字不是 1 到 5 之间的!"

            continue

            echo "游戏结束"

        ;;

    esac

done

运行代码发现,当输入大于5的数字时,会执行continue忽略本次循环,执行下一次循环,语句 echo "游戏结束" 永远不会被执行

22.2  Shift参数左移指令

shift命令用于对参数的移动(左移),通常用于在不知道传入参数个数的情况下依次遍历每个参数然后进行相应处理(常见于Linux中各种程序的启动脚本)

在扫描处理脚本程序的参数时,经常要用到的shift命令,如果你的脚本需要10个或10个以上的参数,你就需要用shift命令来访问第10个及其后面的参数

作用:每执行一次,参数序列顺次左移一个位置,$#的值减1,用于分别处理每个参数,移出去的参数,不再可用

例子:加法计算器

[root@xuegod63 ~]# vim shift.sh

#!/bin/bash

if [ $# -le 0 ];then

        echo "没有足够的参数"

        exit

fi

sum=0

while [ $# -gt 0 ]

do

        sum=$(( sum + $1 ))

        shift

        #shift 2

done

echo "结果是" $sum

测试:

[root@xuegod63 ~]# bash shift.sh  11 2 3 4

result is 20

***trong>hift 2

sh shift.sh 1 2 3 4 5 6 7 8

result is 16

22.3  函数的使用

函数是一个脚本代码块,你可以对它进行自定义命名,并且可以在脚本中任意位置使用这个函数,要使用这个函数,只要使用这个函数名称就可以了。使用函数的好处:模块化,代码可读性强。

22.3.1  函数创建语法

方法1:

function name {

commands

}

注意:name是函数唯一的名称

方法2:name后面的括号表示你正在定义一个函数

name(){

commands

}

调用函数语法:

函数名 参数1 参数2

调用函数时,可以传递参数。在函数中用$1$2…来引用传递的参数

22.3.2  函数的使用

例1:

[root@xuegod63 ~]# cat fun1.sh

#!/bin/bash

function fun_1 {    #定义函数

        echo "this is function"

}

fun1   #调用函数

注意:函数名的使用,如果在一个脚本中定义了重复的函数名,那么以最后一个为准

[root@xuegod63 ~]# vim fun2.sh

#!/bin/bash

function fun1 {

        echo "this is function"

}

function fun1 {

        echo "this is 2222222"

}

fun1

[root@xuegod63 ~]# bash fun2.sh

this is 2222222

22.3.3  返回值

使用return命令来退出函数并返回特定的退出码

例1:

[root@xuegod63 ~]# vim fun3.sh

#!/bin/bash

function fun1 {

        echo "this is function"

        ls /etc/passwd

        return 3

        echo "我不会被执行"

}

fun1

[root@xuegod63 ~]# bash fun3.sh   #查看结果

this is function

/etc/passwd

[root@xuegod63 ~]# echo $?

3

注:状态码的取值范围(0~255)

exit 数字 和return 数字的区别?

exit整个脚本就直接退出,返回数字  

return 只是在函数最后添加一行,然后返回数字,只能让函数后面的命令不执行,无法强制退出整个脚本。

22.3.4  把函数值赋给变量使用

例子: 函数名就相当于一个命令

[root@xuegod63 ~]# vim fun4.sh

#!/bin/bash

fun1(){

        read -p "Input a number: " va

        echo $[$va*5]

}

num=$(fun1)

echo current num is $num

[root@xuegod63 ~]# sh fun4.sh

Input a value: 22

current num is 110

22.3.5  函数的参数传递

第一种:通过脚本传递参数给函数中的位置参数$1

[root@xuegod63 ~]# vim fun5.sh

#!/bin/bash

fun1() {

        ls $1

}

fun1 $1   

#!/bin/bash

fun1() {

        ls $1

}

fun1   #这里如果不写$1 ,函数获取不到$1的值

sh  fun5.sh  /tmp

第二种:调用函数时直接传递参数

[root@xuegod63 ~]# touch  /root/a.txt  #创建一个测试文件

[root@xuegod63 ~]# vim fun5.sh

#!/bin/bash

fun1(){

        rm -rf $1

}

fun1 /root/a.txt

[root@xuegod63 ~]# bash fun5.sh    #测试

[root@xuegod63 ~]# ls /root/a.txt

ls: 无法访问/root/a.txt: 没有那个文件或目录

第三种:函数中多参数传递和使用方法

[root@xuegod63 ~]# vim fun6.sh

#!/bin/bash

fun() {

        echo $[$1*5]

        echo $[$2*2]

        echo $[$3*3]

}

fun 5 6 $3   

[root@xuegod63 ~]# bash fun6.sh 1 2 7  #测试

25

12 

21

22.3.6  函数中变量的处理

函数使用的变量类型有两种:局部变量、全局变量。

1、全局变量,默认情况下,你在脚本中定义的变量都是全局变量,你在函数外面定义的变量在函数内也可以使用

例子:

[root@xuegod63 ~]# vim fun7.sh

#!/bin/bash

function fun {

        num=$[var*2]

}

read -p "input a number:" var

fun

echo the new value is: $num

[root@xuegod63 ~]# bash fun7.sh

input a num:2

the new value is: 4

2、局部变量

  不能被引用到函数外

  定义方法:local value

[root@ xuegod63 ~]# vim fun8.sh

#!/bin/bash

 function fun(){

     local temp=$[ $value + 5 ]  # 定义temp为局部变量,只在函数内生效

     echo "local temp is $temp"

     result=$[ $temp *2 ]

 }

 temp=4   # 这两个变量是全局变量

 value=6

 fun

 echo "The result is $result"

 if [ $temp -gt $value ];then  # 此处的temp变量是temp=4这个全局变量,并不是fun中的局部变量

     echo "temp大于value,temp的值是$temp"

 else

     echo "temp不大于value,temp的值是$temp"     

fi

[root@xuegod63 ~]# bash fun8.sh

local temp is 11

The result is 22

temp不大于value,temp的值是4

22.4  实战自动备份mysql数据库脚本和nginx服务启动脚本

22.4.1  自动备份mysql数据库脚本

从centos7.0开始,系统中自带的mysql数据库包,改为mariadb数据库。

MariaDB数据库概述:MariaDB数据库管理系统是MySQL的一个分支,主要由开源社区在维护,采用GPL授权许可 MariaDB的目的是完全兼容MySQL,包括API和命令行,使之能轻松成为MySQL的代替品。MariaDB由MySQL的创始人Michael Widenius(迈克尔·维德纽斯)主导开发,他早前曾以10亿美元的价格,将自己创建的公司MySQL AB卖给了SUN,此后,随着SUN被甲骨文收购,MySQL的所有权也落入Oracle的手中。MariaDB名称来自Michael Widenius的女儿Maria(玛丽亚)的名字。

甲骨文公司收购了MySQL后,有将MySQL闭源的潜在风险,因此社区采用分支的方式来避开这个风险。 过去一年中,大型互联网用户以及Linux发行商纷纷抛弃MySQL,转投MariaDB阵营。MariaDB是目前最受关注的MySQL数据库衍生版,也被视为开源数据库MySQL的替代品。

安装mariadb数据库:

[root@xuegod63 ~]# yum -y install mariadb mariadb-server

# mariadb 是mysql的客户端命令 ; mariadb-server 是mysql服务端命令

[root@xuegod63 ~]# rpm -ql mariadb

[root@xuegod63 ~]# systemctl start mariadb

登录mysql:

[root@xuegod63 ~]# mysqladmin  -u root password "123456"   #给root用户配置一个密码123456

[root@xuegod63 ~]# mysql -u root -p123456  #登录mysql数据库

MariaDB [(none)]> show databases;

MariaDB [(none)]> create database xuegod  ;    #创建xuegod数据库

MariaDB [(none)]> use xuegod;        #选择数据库

MariaDB [xuegod]> create table user (id int);   #创建user表,只有一个id字段

MariaDB [xuegod]> insert into user values(1);   #插入一条记录,id字段值1

MariaDB [xuegod]> insert into user values(2);   #插入一条记录,id字段值2

MariaDB [xuegod]> select * from user;   #查看表中的数据

+------+

| id   |

+------+

|    1 |

|    2 |

+------+

mysql自动化备份脚本:

思路:

1、检查一下运行环境: 目录是否存在,时间,权限,用户

2、运行要执行的命令:备份,导出数据。。。

3、把命令执行过程中的没有用的文件删除一下

4、弹出命令运行成功的消息

[root@localhost shell]# vim mysql-back-auto.sh

#!/bin/bash

# 自动备份mysql脚本

# 定义变量

BAKDIR=/data/backup/mysql

MYSQL_DATABASE=xuegod

FILENAME=${MYSQL_DATABASE}_`date +%Y-%m-%d`.sql

MYSQL_USER=root

MYSQL_PASSWORD=123456

# 脚本必须是root用户才能运行

if [ $UID  -ne 0 ];then

echo 脚本必须root用户运行

exit 0

fi

# 判断目录是否存在,不存在则新建,否则如果备份文件存在则退出脚本

if [ ! -d $BAKDIR ];then

        mkdir -p $BAKDIR

elif [ -f $BAKDIR/${FILENAME}.tar.gz ];then

        echo "备份文件已存在"

        exit 1

fi

#使用mysqldump备份数据库

/usr/bin/mysqldump -u${MYSQL_USER} -p${MYSQL_PASSWORD} ${MYSQL_DATABASE} > ${BAKDIR}/${FILENAME}

cd $BAKDIR && tar -czf ${FILENAME}.tar.gz ${FILENAME}

#查找备份目录下以.sql结尾的文件并删除(不建议)

#[ $? -eq 0 ] && find $BAKDIR -type f -name *.sql -exec rm -rf {} \;

#打包命令执行成功了,提示成功,然后删除100天以前的备份文件

[ $? -eq 0 ] && echo "$FILENAME 数据库备份成功"

cd $BAKDIR && find . -type f -mtime +100 -exec rm -rf {} \;

ls $BAKDIR

tar tvf $BAKDIR/${FILENAME}.tar.gz

加入计划任务

crontab -e

0 3 * * * /bin/bash /root/mysql-back-auto.sh

22.4.1  nginx编译脚本

此nginx脚本中使用了函数功能,让脚本具有更强的可读性

[root@xuegod63 ~]# vim setup_nginx.sh

#!/bin/bash

#编译安装nginx-1.18.0

#定义变量

prefix=/usr/local/nginx

setup_file=nginx-1.18.0.tar.gz

setup_dir=/root/

setup_version=nginx-1.18.0

setup_url=http://nginx.org/download/nginx-1.18.0.tar.gz

#检查文件是否存在,不存在则下载

check_file(){

if [ ! -f ${setup_dir}${setup_file} ];then

cd ${setup_dir} && wget ${setup_url}

else

cd ${setup_dir}

echo "${setup_dir}${setup_file}存在,继续编译安装步骤"

fi

if [ ! -d ${prefix} ];then

mkdir -p /usr/local/nginx

else

echo "${prefix}存在"

fi

}

make1(){

check_file;

if [ -f ${setup_dir}${setup_file} ];then

tar -xvf ${setup_dir}${setup_file}

if [ $? -eq 0 ];then

echo "解压成功"

cd ${setup_dir}${setup_version}

echo "进入${PWD}目录"

yum install -y pcre-devel zlib-devel

./configure --prefix=${prefix}

make -j 4 && make install

if [ $? -eq 0 ]; then

echo "编译完成"

exit 0

else

echo "编译失败请检查!"

exit 1

fi

fi

fi

}

make1

[root@xuegod63 ~]# sh setup_nginx.sh

22.4.2  nginx服务启动脚本

此nginx脚本中使用了函数功能,让脚本具有更强的可读性

[root@xuegod63 ~]# vim /etc/init.d/nginx    

#!/bin/bash

#chkconfig: 2345 80 90

#description:nginx run

# nginx启动脚本

PATH_NGINX=/usr/local/nginx      #nginx路径

DESC="nginx daemon"       #nginx描述

NAME=nginx

DAEMON=$PATH_NGINX/sbin/$NAME   #/usr/local/nginx/sbin/nginx #nginx命令的绝对路径 

PIDFILE=$PATH_NGINX/logs/${NAME}.pid

SCRIPTNAME=/etc/init.d/$NAME

[ -x "$DAEMON" ] || exit 0   #不存在可执行的文件,则退出

do_start()

{

        [ ! -f "${PIDFILE}" ] && ${DAEMON} || echo -n " nginx already running"

        ps_aux

}

do_stop()

{

        [ -f "${PIDFILE}" ] && $DAEMON -s stop || echo -n " nginx not running"

}

do_reload()

{

        $DAEMON -s reload || echo -n "\n nginx can't reload"

}

ps_aux() {

        echo ""

        ps aux | grep "${NAME}" | grep -v "grep"

}

case "$1" in

start)                

echo -n "Starting $DESC: $NAME"

                do_start

                echo "."

        ;;

        stop)

                echo -n "Stopping $DESC: $NAME"

                do_stop

                echo "."

        ;;

        reload|graceful)

                echo -n "Reloading $DESC configuration..."

                do_reload

                echo "."

        ;;

        restart)

                echo -n "Restarting $DESC: $NAME"

                do_stop

                sleep 1

                do_start

        ;;

        *)

                echo "Usage: $SCRIPTNAME {start|stop|reload|restart}"

                exit 1

        ;;

esac

exit 0

[root@xuegod63 ~]# chmod +x /etc/init.d/nginx

[root@xuegod63 ~]# chkconfig --add /etc/init.d/nginx

[root@xuegod63 ~]# chkconfig nginx on

[root@xuegod63 ~]# chkconfig --list

[root@xuegod63 ~]# systemctl status nginx
[root@xuegod63 ~]# systemctl start nginx

[root@xuegod63 ~]# systemctl status nginx

更多学习资料请移步至公众号【学神来啦】