shell编程

作者: 酷酷的伟 | 来源:发表于2019-07-16 00:35 被阅读5次

    Shell入门

    什么是shell?

    Shell其实是一个命令解释器,作用是解释执行用户输入的命令以及程序等,用户每输入一条命令,Shell给予解释执行一条。这种键盘一输入命令,就可以立即得到回应的对话方式,称为交互模式。
    Shell存在于操作系统的最外层,负责与用户直接对话。处理用户的输入,并将操作系统执行结果返回给用户。在用户登陆到操作系统之后的所有操作均由Shell解释执行。Shell在操作系统中所处的位置如下

    image

    什么是shell脚本?

    简言之,如果shell命令通过写入到一个程序文件并执行的时候,此程序我们就称之为shell脚本。但是在生产环境中的Shell脚本不仅仅是这么简单,而是将一些命令、变量以及流程控制语句有机结合并生成的功能完善的强大的应用程序。

    什么时候使用shell脚本?

    Linux批量管理
    自动化完成系统优化
    自动化安装Linux操作系统(kickstart和cobbler)
    测试工具和内容自动化
    邮件自动发送
    服务自动重启
    代码上线
    定时备份和定时启停服务
    Linux系统监控、服务监控、端口监控、IP黑名单监控、流量监控(脚本+zabbix)
    服务的日志切割、存储备份、日志分析等等

    如何学好shell脚本?

    基础变量、条件表达式、流程判断、if、for循环、while循环、case语句、循环控制
    从简单的判断和循环开始写
    阅读、模仿、尝试从零开始写
    写注释,将任务分解成一个个小任务,类似于打游戏闯关
    找一本合适的教材,或者自己认真记笔记
    多练习-思考-练习-思考,循环往复

    解释型语言和编译型语言

    编译型语言:

    指用专用的编译器,针对特定的操作平台(操作系统)将某种高级语言源代码一次性翻译成可被硬件平台直接运行的二进制机器码,这个过程叫做编译。
    编译好的可执行文件(.exe),可在相对应的平台运行(移植性差,但是效率高)。
    C\C++.....

    解释型语言:

    用专门解释器对源程序逐行解释成特定平台的机器码并立即执行的语言,相当于把编译型语言的编译执行过程混合在一起同时完成的。
    编译型语言执行效率较低,切不能脱离解释器运行。但是跨平台比较容易,只需提供相应的解释器
    shell\python
    注:Java属于特殊的。既可以说成是解释型语言,又可以说成是编译型语言

    shell是命令解释器
    shell脚本是由命令组合成的一个可执行的文件
    编译型语言和解释型语言

    shell脚本建立和执行

    解释器类型

    bash是centos中的默认解释器
    sh

    脚本定义

    脚本开头

    # !/bin/bash

    父shell和子shell

    脚本嵌套
    父shell中的环境变量,在子shell中可以看到
    而子shell中的变量,在父shell中看不到

    shell执行方式

    sh & bash,最常用的使用方式
    cat *.sh | bash,适用于执行多个脚本
    sh < oldboy.sh,了解一下,输入重定向
    /root/oldboy.sh,需要执行权限
    . oldboy.sh
    source oldboy.sh

    shell开发习惯

     脚本存放在固定目录
     开头加脚本解释器信息
     附带作者和版权信息
     脚本中尽量不用中文
     脚本扩展名用.sh
     成对的符号一次性书写完成
     注意缩进
     养成写注释的良好习惯

    总结

    脚本放在指定目录
    创建脚本,后缀是.sh
    在第一行顶格添加命令解释器的声明#!/bin/bash
    添加作者时间和版权信息
    养成良好习惯,添加注释
    Centos7默认解释器是/bin/bash
    退出当前shell的命令是:exit
    有一个小问题:在使用history的时候,加入脚本中,执行什么也不会输出。
    在脚本中加入set -o history即可解决,但是默认显示的是这个脚本里的历史命令。但是
    如果还想显示脚本外的历史记录,可以使用source 执行脚本。

    变量基础

    定义变量

    值可变的量,称为变量
    变量名=变量值,常说的变量,一般是变量名
    字母数字下划线,不能是数字开头

    环境变量和普通变量

    环境变量(全局变量)

     可在创建他们的shell以及派生出来的任意子shell中使用
     环境变量包括内置的环境变量和自定义的环境变量,且通常为大写。
     环境变量的定义方式:

    declare -x 变量名=value
    export 变量名=value

     环境变量有四个文件,他们的执行顺序如下图所示:

    image

     登陆shell会加载所有的环境变量
     非登陆shell可能会加载~/.bashrc或者/etc/bashrc(上图非绿色部分),然而有些定时任务以上两个根本不会加载,所以需要手动指定,建议在定义变量时定义到/etc/bashrc
     可以在环境变量文件中定义普通变量

    普通变量

     普通变量只有在当前shell下才能使用
     定义方式
    # 适用于一般场景,不适用于带有空格等字符
    变量名=value
    # 所见即所得的定义方式
    变量名=’value’
    # 解析双引号之内的变量
    变量名=”value

     注意点:(举例说明)

    1. 变量如果后面有内容,一定要把变量括{}起来
    2. 希望变量内容原样输出则加单引号
    3. 希望获取变量中的命令执行结果用``或者$()

    1、定义环境变量的方式:
    export 变量名=变量值
    2、定义普通变量的方式:
    变量名=变量值
    3、定义变量的三种方式

    # 适用于一般场景,不适用于带有空格等字符
    [export] 变量名=value
    # 所见即所得的定义方式
    [export] 变量名=’value’
    # 解析双引号之内的变量
    [export] 变量名=”value”
    4、环境变量文件的加载顺序
    /etc/profile ===> ~/.bash_profile ===> ~/.bashrc ===> /etc/bashrc
    5、非登录式(ssh)的shell只加载后两个

    临时变量和永久变量(了解)

    如果按照变量的生存周期来划分的话,Linux变量可以分为两类:
     永久变量:需要修改变量配置文件,使得变量永久生效
     临时变量,使用export命令或者直接在当前shell中赋值的变量

    shell特殊变量

    参数特殊变量

    特殊变量 作用说明
    0获取当前执行shell脚本文件名,如果执行脚本带路径,则包括完整路径
    n获取当前执行脚本的第n个参数值,若n>9,则用大括号包裹,如10#传递到脚本的参数个数
    *以一个单字符串显示所有向脚本传递的参数@与$*相同,但是使用时加引号,并在每个引号中返回每个参数
    n 获取当前执行shell脚本的第n个参数值,若n>9,则用大括号包裹,如10#
    传递到脚本的参数个数
    *以一个单字符串显示所有向脚本传递的参数@ 与$*相同,但是使用时加引号,并在引号中返回每个参数。

    进程特殊变量

    特殊变量 作用说明
    ?显示最后命令的特殊状态,0表示没有错误,非0表示有错误。此变量最常用的$$显示脚本
    ! 后台运行的最后一个进程的ID号,此变量不常用,了解即可
    $_ 之前运行脚本的最后一个参数,此变量最不常用,了解即可

    shell变量子串

    表达式 作用说明
    {param} 返回变量param内容
    {#param} 返回变量param内容的字符长度,也适合特殊变量,此表达式最常用
    {param:offset} 在变量param中,从位置offset之后开始提取子串到结尾
    {param:offset:length} 在变量param中,从位置offset之后开始提取长度为length的子串
    {param#word} 在变量param开头删除最短匹配的word子串
    {param##word} 在变量param开头删除最长匹配的word子串
    {param%word} 在变量param结尾删除最短匹配的word子串
    {param%%word} 在变量param结尾删除最长匹配的word子串
    {param/pattern/string} 将变量param中符合pattern的第一个内容用string取代
    {param//pattern/string} 将变量param中符合pattern的所有内容用string取代

    总结:获取变量字符串长度的五种方法:

    [root@shell ~]# oldboy="www.oldboy.com"
    [root@shell ~]# echo ${#oldboy}
    14
    [root@shell ~]# echo ${oldboy} |wc -L
    14
    [root@shell ~]# expr length $oldboy
    14
    [root@shell ~]# echo ${oldboy}|awk '{print length}'
    14
    [root@shell ~]# echo ${oldboy}|awk '{print length($0)}'
    14
    
    

    练习:

    1、 请使用shell脚本打印下面语句中字符数不小于6的单词
    I am teacher oldchang and I like eating and sleeping

    for n in $*                                  
    do
        [ ${#n} -ge 6 ] && echo $n
    done
    
    

    2、 写出shell脚本,通过传参的方式,传入以下内容,并打印下面语句中字符数不小于6的单词
    I am teacher oldchang and I like eating and sleeping

    read -p '请输入你要处理的字符串: ' n
    for n in $n
    do
        if [ ${#n} -ge 6 ];then                
            echo $n
        fi
    done
    
    

    变量传参

    脚本变量传参的三种方式:
     直接赋值

    [oldchang@oldboy-node101 ~]$ cat 1.sh 
    IP=127.0.0.1
    echo $IP
    [oldchang@oldboy-node101 ~]$ sh 1.sh 
    127.0.0.1
    
    

     传参方式

    [oldchang@oldboy-node101 ~]$ cat 1.sh 
    IP=$1
    echo $IP
    [oldchang@oldboy-node101 ~]$ sh 1.sh 127.0.0.1
    127.0.0.1
    
    

     read方式

    [oldchang@oldboy-node101 ~]$ cat 1.sh 
    read -p "请输入一个参数: " IP
    echo $IP
    [oldchang@oldboy-node101 ~]$ sh 1.sh 
    请输入一个参数: 127.0.0.1
    127.0.0.1
    

    运算符与运算命令

    image image image
    [root@shell scripts]# a=8
    [root@shell scripts]# echo $((a%6))
    2
    [root@shell scripts]# echo $a
    8
    [root@shell scripts]# echo $((a%=6))
    2
    [root@shell scripts]# echo $a
    2
    
    

    练习取值

    [root@oldboyedu ~]# echo 1+1 | bc
    2
    [root@oldboyedu ~]# echo 3.3*8.7 | bc
    28.7
    [root@oldboyedu ~]# echo "scale=4;3.3*8.7" | bc
    28.71
    [root@oldboyedu ~]# echo "scale=4;3.33*8.7" | bc
    28.971
    [root@oldboyedu ~]# echo "scale=4;3.333*8.7" | bc
    28.9971
    [root@oldboyedu ~]# echo "scale=4;3.3333*8.7" | bc
    28.9997
    [root@oldboyedu ~]# echo "scale=10;3.3333*8.7" | bc
    28.99971
    [root@oldboyedu ~]# echo 1 2 | awk '{print $1}'
    1
    [root@oldboyedu ~]# echo 1 2 | awk '{print $1+$2}'
    3
    [root@oldboyedu ~]# echo 3.4 2 | awk '{print $1+$2}'
    5.4
    [root@oldboyedu ~]# echo 3.4 2.444444 | awk '{print $1+$2}'
    5.84444
    [root@oldboyedu ~]# let a=1+1
    [root@oldboyedu ~]# let a=1.1+1
    -bash: let: a=1.1+1: syntax error: invalid arithmetic operator (error token is ".1+1")
    [root@oldboyedu ~]# echo $?
    1
    [root@oldboyedu ~]# expr 1 + 1
    2
    [root@oldboyedu ~]# echo $?
    0
    [root@oldboyedu ~]# expr 1.1 + 1
    expr: non-integer argument
    [root@oldboyedu ~]# echo $?
    2
    [root@oldboyedu ~]# echo 3/2 | bc
    1
    [root@oldboyedu ~]# echo $((2**3))
    8
    [root@oldboyedu ~]# let a=2**3
    [root@oldboyedu ~]# echo $a
    8
    [root@oldboyedu ~]# let b=2**3
    [root@oldboyedu ~]# echo $b
    8
    [root@oldboyedu ~]# expr 2 ** 3
    expr: syntax error
    [root@oldboyedu ~]# expr 2 * * 3
    expr: syntax error
    [root@oldboyedu ~]# expr 2 \** 3
    expr: syntax error
    [root@oldboyedu ~]# expr 2 \*\* 3
    expr: syntax error
    [root@oldboyedu ~]# expr "2 ** 3"
    2 ** 3
    [root@oldboyedu ~]# expr 2 "**" 3
    expr: syntax error
    [root@oldboyedu ~]# expr 2 ^ 3
    expr: syntax error
    [root@oldboyedu ~]# expr 2 \^ 3
    expr: syntax error
    [root@oldboyedu ~]# echo $[2**3]
    8
    [root@oldboyedu ~]# declare -i c=2**3
    [root@oldboyedu ~]# echo $c
    8
    [root@oldboyedu ~]# echo 2**3 | bc 
    (standard_in) 1: syntax error
    [root@oldboyedu ~]# echo 2^3 | bc 
    8
    [root@oldboyedu ~]# a=1
    [root@oldboyedu ~]# echo a++
    a++
    [root@oldboyedu ~]# echo $((a++))
    1
    [root@oldboyedu ~]# echo $((a++))
    2
    [root@oldboyedu ~]# echo $((a++))
    3
    [root@oldboyedu ~]# echo $((a++))
    4
    [root@oldboyedu ~]# a=1
    [root@oldboyedu ~]# echo $((++a))
    2
    [root@oldboyedu ~]# echo $((++a))
    3
    [root@oldboyedu ~]# echo $((++a))
    4
    [root@oldboyedu ~]# echo $((++a))
    5
    [root@oldboyedu ~]# 
    [root@oldboyedu ~]# a=1
    [root@oldboyedu ~]# b=1
    [root@oldboyedu ~]# x=a++
    [root@oldboyedu ~]# y=++b
    [root@oldboyedu ~]# 
    [root@oldboyedu ~]# echo a
    a
    [root@oldboyedu ~]# echo $a
    1
    [root@oldboyedu ~]# echo $x
    a++
    [root@oldboyedu ~]# x=$((a++))
    [root@oldboyedu ~]# y=$((++b))
    [root@oldboyedu ~]# echo $a
    2
    [root@oldboyedu ~]# a=1
    [root@oldboyedu ~]# b=1
    [root@oldboyedu ~]# x=$((a++))
    [root@oldboyedu ~]# y=$((++b))
    [root@oldboyedu ~]# echo $a
    2
    [root@oldboyedu ~]# echo $x
    1
    [root@oldboyedu ~]# echo $b
    2
    [root@oldboyedu ~]# echo $y
    2
    [root@oldboyedu ~]# 8%5
    -bash: 8%5: command not found
    [root@oldboyedu ~]# expr 8 % 5
    3
    [root@oldboyedu ~]# a=8
    [root@oldboyedu ~]# echo $((a%=5))
    3
    [root@oldboyedu ~]# echo $a
    3
    [root@oldboyedu ~]# echo $((a=a%5))
    3
    
    

    使用脚本传参的方式实现整数的加、减、乘、除、取余、幂运算

    x=$1
    y=$2
    
    echo 1.利用'$(())'计算
    echo 加:$1\+$2="$(($x+$y))"
    echo 减:$1\-$2="$(($x-$y))"
    echo 乘:$1\*$2="$(($x*$y))"
    echo 除:$1\/$2="$(($x/$y))"
    echo 幂:$1\**$2="$(($x**$y))"
    echo 余:$1\%$2="$(($x%$y))"  
    
    echo 2.利用awk计算
    echo 加:$1+$2=`awk -vx=$x -vy=$y "BEGIN{print x+y}"`
    echo 减:$1+$2=`awk -vx=$x -vy=$y "BEGIN{print x-y}"`
    echo 乘:$1+$2=`awk -vx=$x -vy=$y "BEGIN{print x*y}"`
    echo 除:$1+$2=`awk -vx=$x -vy=$y "BEGIN{print x/y}"`
    echo 幂:$1+$2=`awk -vx=$x -vy=$y "BEGIN{print x**y}"`
    echo 余:$1+$2=`awk -vx=$x -vy=$y "BEGIN{print x%y}"`
    [root@shell scripts]# sh bc03.sh 2 6
    1.利用$(())计算
    加:2+6=8
    减:2-6=-4
    乘:2*6=12
    除:2/6=0
    幂:2**6=64
    余:2%6=2
    2.利用awk计算
    加:2+6=8
    减:2+6=-4
    乘:2+6=12
    除:2+6=0.333333
    幂:2+6=64
    
    
    [root@shell scripts]# cat bc02.sh 
    #!/bin/bash
    ##############################################################
    # File Name: bc03.sh
    # Version: V1.0
    # Author: lcx
    # Organization: www.oldboyedu.com
    ##############################################################
    x=$1
    y=$2
    echo="echo $1 $2"
    
    echo 1.利用'$(())'计算
    echo 加:$1\+$2="$(($x+$y))"
    echo 减:$1\-$2="$(($x-$y))"
    echo 乘:$1\*$2="$(($x*$y))"
    echo 除:$1\/$2="$(($x/$y))"
    echo 幂:$1\**$2="$(($x**$y))"
    echo 余:$1\%$2="$(($x%$y))"  
    echo '###################'
    echo 2.利用awk计算
    echo 加:$1+$2=`$echo|awk -vx=$x -vy=$y "BEGIN{print x+y}"`
    echo 减:$1+$2=`$echo|awk -vx=$x -vy=$y "BEGIN{print x-y}"`
    echo 乘:$1+$2=`$echo|awk -vx=$x -vy=$y "BEGIN{print x*y}"`
    echo 除:$1+$2=`$echo|awk -vx=$x -vy=$y "BEGIN{print x/y}"`
    echo 幂:$1+$2=`$echo|awk -vx=$x -vy=$y "BEGIN{print x**y}"`
    echo 余:$1+$2=`$echo|awk -vx=$x -vy=$y "BEGIN{print x%y}"`
    [root@shell scripts]# sh bc02.sh 6 3
    1.利用$(())计算
    加:6+3=9
    减:6-3=3
    乘:6*3=18
    除:6/3=2
    幂:6**3=216
    余:6%3=0
    ###################
    2.利用awk计算
    加:6+3=9
    减:6+3=3
    乘:6+3=18
    除:6+3=2
    幂:6+3=216
    余:6+3=0
    
    

    表达式

    条件测试表达式

    image.png
    image.png
    image.png
    image.png

    文件测试表达式

    image.png
    [root@shell scripts]# test -L "/bin/sh" && echo ture||echo false
    ture
    [root@shell scripts]# test -s "/bin/sh" && echo ture||echo false
    ture
    [root@shell scripts]# test -d "/root" && echo ture||echo false
    ture
    [root@shell scripts]# test -x "ip.sh" && echo ture||echo false
    ture    #文件可执行
    [root@shell scripts]# test  -x "bc.sh" && echo ture||echo false
    false   #文件不可执行
    [root@shell scripts]# test ! -x "bc.sh" && echo ture||echo false
    ture    #取反
    [root@shell scripts]# test -s "bc.sh" && echo ture||echo false
    ture    #文件存在非空
    [root@shell scripts]# test ! -s "bc.sh" && echo ture||echo false
    false   #取反
    
    
    ##############
    #测试表达式
    ##############
    [root@shell scripts]# test -f "/etc/hosts" && echo ture||echo false
    ture
    [root@shell scripts]# test -f "/etc/host" && echo ture||echo false
    false
    [root@shell scripts]# test -e "/etc/" && echo ture||echo false
    ture
    [root@shell scripts]# test -e "/etcetc/" && echo ture||echo false
    false
    [root@shell scripts]# test -d "/etc/hosts" && echo ture||echo false
    false
    [root@shell scripts]# test -d "/etc/" && echo ture||echo false
    ture
    [root@shell scripts]# test -L "/bin/sh" && echo ture||echo false
    ture
    [root@shell scripts]# test -L "/bin/ls" && echo ture||echo false
    false
    [root@shell scripts]# test -s "1.sh" && echo ture||echo false
    ture
    [root@shell scripts]# touch 2.sh
    [root@shell scripts]# test -s "2.sh" && echo ture||echo false
    false
    ############
    #取反  
    ############
    [root@shell scripts]# test ! -x "bc.sh" && echo ture||echo false
    ture    #取反
    [root@shell scripts]# test -s "bc.sh" && echo ture||echo false
    ture    #文件存在非空
    [root@shell scripts]# test ! -s "bc.sh" && echo ture||echo false
    false   #取反
    
    ######################
    #测试文件可读可写可执行
    ######################
    [root@shell scripts]# su - oldboy   #切换到普通用户下
    Last login: Thu May 16 17:01:19 CST 2019 on pts/0
    [oldboy@shell ~]$ 
    [oldboy@shell ~]$ test -r "test_01.sh" && echo ture||echo false
    false
    [oldboy@shell ~]$ test -w "test_01.sh" && echo ture||echo false
    false
    [oldboy@shell ~]$ test -x "test_01.sh" && echo ture||echo false
    false
    
    

    练习

    image image

    采坑:

    read读入方式定义的变量写为12了,与取参的12冲突了

    [root@shell scripts]# cat testday2-1.sh 
    #!/bin/bash
    ##############################################################
    # File Name: testday2-1.sh
    # Version: V1.0
    # Author: lcx
    # Organization: www.oldboyedu.com
    ##############################################################
    read -p "请输入两个文件的路径: " a b
    
    [ -f $a ]&& echo $a||{
        echo "第一个文件${a}不存在"
    }
    
    [ -f $b ]&& echo $b||{
        echo "第二个文件${b}不存在"
        exit
    }
    [root@shell scripts]# sh testday2-2.sh 
    请输入两个文件的路径: xxx yyy
    第一个文件xxx不存在
    第二个文件yyy不存在
    [root@shell scripts]# sh testday2-2.sh 
    请输入两个文件的路径: bc.sh xxx
    bc.sh
    第二个文件xxx不存在
    [root@shell scripts]# sh testday2-2.sh 
    请输入两个文件的路径: xxx bc.sh
    第一个文件xxx不存在
    bc.sh
    
    #2.0版 自动化
    [root@shell scripts]# cat testday2-1-1.sh 
    #!/bin/bash
    read -p "请输入指定文件路径: " file   
    
    for f in `echo $file`
    do
        [ -f $f ]&&echo ${file}存在||{
        echo "${f}不存在"
    }
    done
    [root@shell scripts]# sh 1.sh 
    请输入指定文件路径: /server/scripts/1.sh /etc/hosts /etc/hostname
    /server/scripts/1.sh /etc/hosts /etc/hostname存在
    /server/scripts/1.sh /etc/hosts /etc/hostname存在
    /server/scripts/1.sh /etc/hosts /etc/hostname存在
    
    

    字符串测试表达式

    image.png
    #################
    #判断变量是否存在
    #################
    [root@shell ~]# a=111
    [root@shell ~]# b=1111
    [root@shell ~]# test "$a" = "$b" && echo ture||echo false
    false
    [root@shell ~]# test "$a"="$b" && echo ture||echo false
    ture
    [root@shell ~]# echo $a
    111
    [root@shell ~]# echo $b
    1111
    
    [root@shell scripts]# test -n "$a" && echo ture||echo false
    ture
    [root@shell scripts]# test -z "$a" && echo ture||echo false
    false
    [root@shell scripts]# echo $a
    123
    [root@shell scripts]# unset a
    [root@shell scripts]# test -n "$a" && echo ture||echo false
    false
    [root@shell scripts]# test -z "$a" && echo ture||echo false
    ture
    
    

    练习

    image

    1. 方法第一种

    #第二种
    [root@shell scripts]# cat testday2-3-2.sh
    #!/bin/bash
    # 判断传入参数的个数
    [ "$#" != "2" ] && {
        echo "参数必须为2 Usage <$0 arg1 arg2>"
            exit 1
        }
    
        # 判断传参是否为整数
        expr $1 + $2 + 1 &> /dev/null
        [ "$?" != "0" ] && {
          echo "参数必须为整数"
            exit 2
        }  
    
        echo -n '相加: '; echo $(($1+$2))
        echo -n '相减: '; echo $(($1-$2))
        echo -n '相乘: '; echo $(($1*$2))
        echo -n '幂运算: '; echo $(($1**$2))
        # 判断除数是否为0
        [ "$2" = "0" ] && {
            echo "除数必须不能为0!!!"
                exit 3
            }
            echo -n '相除: '; echo $(($1/$2))
            echo -n '取余: '; echo $(($1%$2))
            [root@shell scripts]# sh testday2-3-2.sh 5 6.1
    参数必须为整数
    [root@shell scripts]# sh testday2-3-2.sh 5 6 7
    参数必须为2 Usage <testday2-3-2.sh arg1 arg2>
    [root@shell scripts]# sh testday2-3-2.sh 5 0
    相加: 5
    相减: 5
    相乘: 0
    幂运算: 1
    除数必须不能为0!!!
    [root@shell scripts]# sh testday2-3-2.sh 6 3
    相加: 9
    相减: 3
    相乘: 18
    幂运算: 216
    相除: 2
    取余: 0
    
    

    2.方法第二种

    #第三种 read读入默认2个参数
    
    [root@shell scripts]# cat testday2-5.sh
    #!/bin/bash
    ##############################################################
    # File Name: testday2-5.sh
    # Version: V1.0
    # Author: lcx
    # Organization: www.oldboyedu.com
    ##############################################################
    read -p "请输入需要计算的内容:" m n
    
    # 判断传参是否为整数
    expr $m + $n + 1 &> /dev/null
    [ "$?" != "0" ] && {
      echo "参数必须为整数"
        exit 2
    }  
    
    echo -n '相加: '; echo $(($m+$n))
    echo -n '相减: '; echo $(($m-$n))
    echo -n '相乘: '; echo $(($m*$n))
    echo -n '幂运算: '; echo $(($m**$n))
    # 判断除数是否为0
    [ "$n" = "0" ] && {
        echo "除数必须不能为0!!!"
            exit 3
        }
        echo -n '相除: '; echo $(($m/$n))
        echo -n '取余: '; echo $(($m%$n))
    [root@shell scripts]# sh testday2-5.sh
    请输入需要计算的内容:5 6 7
    参数必须为整数
    [root@shell scripts]# sh testday2-5.sh
    请输入需要计算的内容:5 6.1
    参数必须为整数
    [root@shell scripts]# sh testday2-5.sh
    请输入需要计算的内容:5 0
    相加: 5
    相减: 5
    相乘: 0
    幂运算: 1
    除数必须不能为0!!!
    [root@shell scripts]# sh testday2-5.sh
    请输入需要计算的内容:4 6
    相加: 10
    相减: -2
    相乘: 24
    幂运算: 4096
    相除: 0
    取余: 4
    
    

    整数二元比较操作符

    image.png
    image.png image

    查看当前磁盘/当前状态,如果使用率超过10%,则触发报警发邮件

    [root@shell scripts]# df -h|awk 'NR==2{print $(NF-1)}'
    11%
    
    [root@shell scripts]# df -h|awk 'NR==2{print $(NF-1)}'
    11%
    [root@shell scripts]# cat testday2-6.sh 
    #!/bin/bash
    ##############################################################
    # File Name: testday2-6.sh
    # Version: V1.0
    # Author: lcx
    # Organization: www.oldboyedu.com
    ##############################################################
    #查看当前磁盘/当前状态,如果使用率超过10%,则触发报警发邮件
    use=`df -h|awk 'NR==2{print $(NF-1)}'`
    userNum=${use/\%/}
    [ $userNum -gt 10 ] && {
        echo "shell服务器磁盘使用率超过$use"
        echo "shell服务器磁盘使用率超过$use"|mail -s "磁盘不足" 245684979@qq.com
    }
    [root@shell scripts]# sh testday2-6.sh
    shell服务器磁盘使用率超过11%
    
    

    查看内存使用状况,如果占用超过10%,则触发报警

    [root@shell day02]# cat testday2-7.sh 
    #!/bin/bash
    ##############################################################
    # File Name: testday2-7.sh
    # Version: V1.0
    # Author: lcx
    # Organization: www.oldboyedu.com
    ##############################################################
    #查看内存使用状况,如果占用超过10%,则触发报警
    free=`free -h|awk 'NR==2{print $3/$2*100}'`
    freeNum=${free/.*/}
    [ $freeNum -gt 5 ] && {
        echo "shell服务器内存使用率超过${freeNum}%"
        echo "shell服务器内存使用率超过${freeNum}%"|mail -s "内存不足" 245684979@qq.com
    }
    [root@shell day02]# sh testday2-7.sh 
    shell服务器内存使用率超过9%
    
    

    逻辑操作符

    image.png
    #练习查看结果
    # [ -f ip.sh -a 2 -lt 3 ]&& echo 0||echo 1
    0
    # [ -f ip.sh -a 2 -lt 3 -a 5 -gt 6 ]&& echo 0||echo 1
    1
    # [ -f ip.sh -o 2 -gt 3 ]&& echo 0||echo 1
    0
    # [ -f ip1.sh -o 2 -gt 3 ]&& echo 0||echo 1
    1
    # [ ! -f ip1.sh -o 2 -gt 3 ]&& echo 0||echo 1
    0
    # [ -f ip.sh ] && [ 2 -lt 3 ] && [ 2 -lt 3 ]&&echo 0||echo 1
    0
    # [ -f ip.sh ] && [ 2 -lt 3 ] && [ 2 -eq 3 ]&&echo 0||echo 1
    1
    # [ -f ip.sh ] && [ 2 -lt 3 ] && [ 2 -lt 3 ]&&echo 0||echo 1
    0
    # [[ -f ip.sh ]] && [[ 2 -lt 3 ]] && [[ 3 -gt 2 ]]&&echo 0||echo 1
    0
    
    

    6. 练习

    image

    1、 输入或者通过命令传入一个字符或者数字,如果传入的数字等于1就打印1,如果等于2就打印2;如果不等于1也不等于2,就提示输入不对,然后退出程序。(两种比较方式任选其一:数字比较或字符串比较)

    [root@shell day02]# cat testday2-10.sh 
    #!/bin/bash
    ##############################################################
    # File Name: testday2-10.sh
    # Version: V1.0
    # Author: lcx
    # Organization: www.oldboyedu.com
    ##############################################################
    
    read -p "请输入一个字符或者数字:" a
    
    [ $a -eq 1 ]&& {
        echo $a
        exit 0
    }||
    [ $a -eq 2 ]&& {
        echo $a 
        exit 0
    }||
        echo 输入错误!
        exit 1
    }
    
    #[ $a -ne 1 -a $a -ne 2 ]&& echo 输入错误!
    [root@shell day02]# sh testday2-10.sh 
    请输入一个字符或者数字:1
    1
    [root@shell day02]# sh testday2-10.sh 
    请输入一个字符或者数字:2
    2
    [root@shell day02]# sh testday2-10.sh 
    请输入一个字符或者数字:3
    输入错误!
    
    

    2、 开发shell脚本,分别以脚本传参方式和read读入方式比较两个整数大小,用条件表达式(禁止if)进行判断并以屏幕输出的方式提醒用户比较结果。(一共需要开发2个脚本,在传参和read读入方式实现时,需要对变量是否为数字及传参个数是否正确给予提示)

    1)判断是否是两个参数

    2)判断是否为整数

    3)[ 2 -gt 3 ] && echo “2大于3”|| echo “2等于3”|| echo “2小于3“

    第一种read读入方式

    [root@shell scripts]# cat testday2-8.sh
    #!/bin/bash
    #read读入方式
    read -p "请输入两个整数: " a b
    #判断是否为整数
    expr $a + $b &> /dev/null
    [ $? -eq 0 ]&& echo 参数正确!||{
        echo "参数必须为整数"
        exit 2
    }
    [ $a -gt $b ]&& {
        echo "数值对比: [$a] > [$b]"
    }||{
    [ $a -lt $b ]&& {
        echo "数值对比: [$a] < [$b] "
    }||{
    [ $a -eq $b ]&& {
            echo "数值对比: [$a] = [$b]"
            }
        }
    }
    [root@shell scripts]# sh testday2-8.sh
    请输入两个整数: 5 6
    参数正确!
    数值对比: [5] < [6] 
    [root@shell scripts]# sh testday2-8.sh
    请输入两个整数: 8 1
    参数正确!
    数值对比: [8] > [1]
    [root@shell scripts]# sh testday2-8.sh
    请输入两个整数: 8 8
    参数正确!
    数值对比: [8] = [8]
    [root@shell scripts]# sh testday2-8.sh
    请输入两个整数: 2.1 1
    参数必须为整数
    
    

    第二种传参方式

    [root@shell scripts]# cat testday2-9.sh 
    #!/bin/bash
    #传参方式
    #判断是否是两个参数
    [ $# -ne 2 ]&&{
        echo "请输入两个参数进行对比!"
        exit
    }
    #判断是否为整数
    expr $1 + $2 &> /dev/null
    [ $? -eq 0 ]&& echo 参数正确!||{
        echo "参数必须为整数"
        exit 
    }
    #数值对比
    [ $1 -gt $2 ]&& {
        echo "数值对比: [$1] > [$2]"
    }
    [ $1 -lt $2 ]&& {
        echo "数值对比: [$1] < [$2] "
    }
    [ $1 -eq $2 ]&& {
        echo "数值对比: [$1] = [$2]"
    }
    [root@shell scripts]# sh testday2-9.sh 8 8
    参数正确!
    数值对比: [8] = [8]
    [root@shell scripts]# sh testday2-9.sh 8 6
    参数正确!
    数值对比: [8] > [6]
    [root@shell scripts]# sh testday2-9.sh 6 8
    参数正确!
    数值对比: [6] < [8] 
    [root@shell scripts]# sh testday2-9.sh 6 8.1
    参数必须为整数
    
    

    3、 打印菜单,按照选择项选择你喜欢的美女

    示例菜单:

    [root@oldboy scripts]# sh meinv.sh
    
    1.heijiajia
    
    2.高圆圆
    
    3.蔡徐坤
    
    please input the num you like: 
    
    

    要求:

    1)当用户输入1时,输出“I guess you like heijiajia”,然后退出脚本

    2)当用户输入非1-3的字符时,输出“I guess you are not man”,然后退出脚本

    [root@shell scripts]# cat caidan.sh 
    #!/bin/bash
    prefix="I guess you like "
    
    #菜单
    cat <<EOF
        1.heijiajia
        2.高圆圆
        3.蔡徐坤
    EOF
    
    read -p "please input the num you like: " num
    [ $num -eq "1" ] && {
        echo "$prefix"heijiajia
    }
    [ $num -eq "2" ] && {
        echo "$prefix"高圆圆
    }
    [ $num -eq "3" ] && {
        echo "打篮球那个 Are You OK??"
    }
    
    #echo -e "\t1.heijiajia\n\t2.gaoyuanyuan\n\t3.caixukun"
    
    [root@shell scripts]# sh caidan.sh 
        1.heijiajia
        2.高圆圆
        3.蔡徐坤
    please input the num you like: 1
    I guess you like heijiajia
    [root@shell scripts]# sh caidan.sh 
        1.heijiajia
        2.高圆圆
        3.蔡徐坤
    please input the num you like: 2
    I guess you like 高圆圆
    [root@shell scripts]# sh caidan.sh 
        1.heijiajia
        2.高圆圆
        3.蔡徐坤
    please input the num you like: 3
    打篮球那个 Are You OK??
    
    

    7.Shell练习作业

    1.检查OSPF route-ID配置,配置如下,请用shell编写代码,条件如下:

    检查OSPF route-ID配置,配置如下,请用shell编写代码,条件如下:
    1、检查ospf的route-id值
    2、route-id值必须与interface LoopBack0的IP地址值相同
    grep -A 1 "interface LoopBack0" 3.txt | sed -n '$p' | awk '{print $3}
    3、如果两个值不相等,或ospf的route-id值不以139开头,则打印出route-id的值
    ofpf 100
    route-id 139.11.0.1
     area 0.0.0.0
        network 139.11.0.1 0.0.0.0
        network 140.11.0.0 0.0.0.3
        network 140.11.0.8 0.0.0.3
        network 140.11.0.16 0.0.0.3
    network 140.11.0.24 0.0.0.3
    network 140.11.0.32 0.0.0.3
    #
    interface LoopBack0
     ip address 139.11.0.1 255.255.255.255
    #
    
    
    image image
    [root@shell day02]# vim zuoye01.sh 
      1 #!/bin/bash                                                                                    
      2 ##############################################################
      3 # File Name: zuoye01.sh
      4 # Version: V1.0
      5 # Author: lcx
      6 # Organization: www.oldboyedu.com
      7 ##############################################################
      8 #ospf route-ID配置文件路径/server/scripts/day02/3.txt
      9 dir=/server/scripts/day02/3.txt
     10 routeID=`cat $dir |awk 'NR==2{print $2}'`
     11 interfaceIP=`grep -A 1 "interface LoopBack0" $dir|awk 'NR==2{print $3}'`
     12 routeIPhead=`cat $dir |awk -F"[ .]+" 'NR==2{print $2}'`
     13 head="139"
     14 #检查ospf的route-id值
     15 echo "osps的route-id为: $routeID"
     16 #检查route-id与interface LoopBack0IP是否相同
     17 [ "$routeID" != "$interfaceIP" ]&&{
     18     echo "1.IP与ID不相等 IP为:$interfaceIP ID为$routeID"
     19 }
     20 [ "$routeIPhead" != "139" ]&&{
     21     echo "2.route-id的值不是139开头 routeID为:$routeID"
     22 }                                                                  
    [root@shell day02]# sh zuoye01.sh 
    osps的route-id为: 239.11.0.1
    1.IP与ID不相等 IP为:139.11.0.1 ID为239.11.0.1
    2.route-id的值不是139开头 routeID为:239.11.0.1
    [root@shell day02]# sh zuoye01.sh 
    osps的route-id为: 139.11.0.1
    
    

    2.处理以下文件内容,将域名提取并进行计数排序,如处理:

    处理以下文件内容,将域名提取并进行计数排序,如处理:
    http://www.baidu.com/index.html
    http://www.baidu.com/1.html
    http://post.baidu.com/index.html
    http://mp3.baidu.com/index.html
    http://www.baidu.com/3.html
    http://post.baidu.com/2.html
    得到如下结果:
    域名的出现次数  域名
    3   www.baidu.com
    2   post.baidu.com
    1   mp3.baidu.com
    
    

    思路:

    image
    [root@shell day02]# cat 4.txt |awk -F'[/]' '{print $3}'|sort|uniq -c|sort -rn|sed '1i域名的出现次数  域名'
    域名的出现次数  域名
          3 www.baidu.com
          2 post.baidu.com
          1 mp3.baidu.com
    
    

    3.打印菜单,按照选择项一键安装不同的web服务

    打印菜单,按照选择项一键安装不同的web服务
    示例菜单:
    [root@oldboy scripts]# sh menu.sh
     1.[install lnmp]
     2.[install lamp]
     3.[exit]
    please input the num you want: 
     要求:
     1)当用户输入1时,输出“start installing lamp提示”,然后执行/server/scripts/lamp.sh,(执行方式使用全路径方式执行)。
       脚本内容输出“lamp is installed”并退出脚本,此为工作中的一键安装lamp脚本
     2)当用户输入2时,输出“start installing lnmp提示”,然后执行/server/scripts/lnmp.sh, (执行方式使用 全路径方式执行)。
      脚本内容输出“lnmp is installed”并退出脚本,此为工作中的一键安装lnmp脚本
     3)当输出3时,退出当前菜单及脚本  
     4)当用户输入非1-3的字符时,输出“Input Error”,然后退出脚本
     5)对执行的脚本进行相关的条件判断,例如:脚本是否存在,是否可执行等操作,尽量使用今天讲的知识点
    
    
    image
    #技术水平有限,不求精简只求实现
    
    [root@shell day02]# cat zuoye02.sh 
    #!/bin/bash
    ##############################################################
    # File Name: zuoye02.sh
    # Version: V1.0
    # Author: lcx
    # Organization: www.oldboyedu.com
    ##############################################################
    #检测脚本是否存在且非空,是否可执行
    file1=`[ -s /server/scripts/lamp.sh ]&& echo ture||echo fluse`
    file2=`[ -s /server/scripts/lnmp.sh ]&& echo ture||echo fluse`
    exec1=`[ -x /server/scripts/lamp.sh ]&& echo ture||echo fluse`
    exec2=`[ -x /server/scripts/lnmp.sh ]&& echo ture||echo fluse`
    [ $file1 = "ture" ]&& echo lamp.sh脚本文件存在且非空||{
        echo "lamp.sh脚本文件不存在或是一个空文件!!!"
        }&&{
        [ $exec1 = "ture" ]&& echo lamp.sh脚本文件可以执行||{
            echo "lamp.sh脚本文件不可执行!!!"
        }&&{
        [ $file2 = "ture" ]&& echo lnmp.sh脚本文件存在且非空||
            echo -eq "lnmp.sh脚本文件不存在或是一个空文件!!!"
        }&&{
        [ $exec2 = "ture" ]&& echo lnmp.sh脚本文件可以执行||{
            echo "lnmp.sh脚本文件不可执行!!!"
            exit
           }
        }
    }
    #打印菜单,按照选择项一键安装不同的web服务
    cat <<EOF
        1.[install lnmp]
        2.[install lamp]
        3.[exit]
    EOF
    
    read -p "please input the num you want:" num
    #安装lamp环境
    [ $num -eq "1" ] &&{
        echo "start installing LAMP"
        sleep 1
        /server/scripts/lamp.sh
        exit
        }||{
        [ $num -eq "2" ] &&{
            echo "start installing LNMP"
            sleep 1
            /server/scripts/lnmp.sh
            exit
            }
        }||{
        [ $num -eq "3" ] &&{
            echo "即将退出脚本..."
            sleep 1
            exit
            }
        }||{
        [ $num != "{1..3}" ]&&{
            echo "Input Error错误!"
            exit
        }
    }
    
    

    测试结果

    image image image image

    相关文章

      网友评论

        本文标题:shell编程

        本文链接:https://www.haomeiwen.com/subject/tcyakctx.html