• Shell编程


    Shell脚本介绍

    Shell是一种脚本语言,和传统语言C,Python...相比还是比较简单的。

    可以使用逻辑判断,循环等语法

    可以自定义函数

    shell是系统命令的集合

    shell脚本可以实现自动化运维,能大大增加我们的运维效率

     Shell脚本结构和执行方法

    1.开头必须要#!/bin/bash  解释器(如果shell中执行的命令在本机有,不加也能执行,但是还是建议加上这段)命令,下面的命令是通过bin/bash解释器执行的

       我们发现sh其实只是bash的软连接(bin/bash就是bin/sh)

    [root@bogon ~]# mkdir shell
    [root@bogon ~]# cd shell/
    [root@bogon shell]# ls
    [root@bogon shell]# ll /bin/sh
    lrwxrwxrwx. 1 root root 4 2月  10 2017 /bin/sh -> bash
    [root@bogon shell]# ll /bin/bash
    -rwxr-xr-x. 1 root root 960376 11月 20 2015 /bin/bash
    [root@bogon shell]# 
    
    [root@bogon shell]# vim 01.sh
    #!/bin/bash
    echo "123"
    w
    ls
    [root@bogon shell]# sh 01.sh 
    123
     10:18:18 up 4 days, 19:01,  3 users,  load average: 0.85, 0.79, 0.53
    USER     TTY      FROM             LOGIN@   IDLE   JCPU   PCPU WHAT
    root     :0       :0               262月18 ?xdm?   5:54m  2.43s gdm-session-worker [pam/gdm-p
    root     pts/0    :0               262月18 19:29m  0.13s  0.13s /bin/bash
    root     pts/1    10.21.95.237     三14    2.00s  0.35s  0.21s -bash
    01.sh

    2.除过第一行,剩下以#开头的大多只是作为解释说明用  

    3..脚本的名字通常以.sh结尾,用于区分这是一个shell脚本。

    4.执行方法有两种

    [root@bogon shell]# ./01.sh
    -bash: ./01.sh: 权限不够
    [root@bogon shell]# 
    [root@bogon shell]# ll
    总用量 4
    -rw-r--r--. 1 root root 28 3月  15 10:18 01.sh
    [root@bogon shell]# chmod +x 01.sh;
    [root@bogon shell]# ./01.sh 
    123
     10:26:47 up 4 days, 19:09,  3 users,  load average: 0.01, 0.22, 0.36
    USER     TTY      FROM             LOGIN@   IDLE   JCPU   PCPU WHAT
    root     :0       :0               262月18 ?xdm?   5:55m  2.44s gdm-session-worker [pam/gdm-p
    root     pts/0    :0               262月18 19:38m  0.13s  0.13s /bin/bash
    root     pts/1    10.21.95.237     三14    7.00s  0.29s  0.23s -bash
    01.sh
    [root@bogon shell]# 
    

     

    [root@bogon shell]# ll
    总用量 4
    -rwxr-xr-x. 1 root root 28 3月  15 10:18 01.sh
    [root@bogon shell]#

    (1)chmod +x 01.sh;./01.sh    先给脚本执行权限,然后用相对路径执行(因为$PATH里有/bin/的路径)

    (2)bash 01.sh 或者 sh 01.sh

    [root@bogon shell]# bash 01.sh 
    123
     10:31:34 up 4 days, 19:14,  3 users,  load average: 0.08, 0.14, 0.29
    USER     TTY      FROM             LOGIN@   IDLE   JCPU   PCPU WHAT
    root     :0       :0               262月18 ?xdm?   5:55m  2.44s gdm-session-worker [pam/gdm-p
    root     pts/0    :0               262月18 19:43m  0.13s  0.13s /bin/bash
    root     pts/1    10.21.95.237     三14    6.00s  0.30s  0.24s -bash
    01.sh
    [root@bogon shell]# sh 01.sh 
    123
     10:31:38 up 4 days, 19:14,  3 users,  load average: 0.08, 0.14, 0.29
    USER     TTY      FROM             LOGIN@   IDLE   JCPU   PCPU WHAT
    root     :0       :0               262月18 ?xdm?   5:55m  2.44s gdm-session-worker [pam/gdm-p
    root     pts/0    :0               262月18 19:43m  0.13s  0.13s /bin/bash
    root     pts/1    10.21.95.237     三14    2.00s  0.26s  0.25s -bash
    01.sh
    [root@bogon shell]#

    5.查看脚本执行过程

    sh -x + 脚本        (每一个+表示一个动作)

    [root@bogon shell]# sh -x 01.sh 
    + echo 123
    123
    + w
     10:36:34 up 4 days, 19:19,  3 users,  load average: 0.20, 0.13, 0.24
    USER     TTY      FROM             LOGIN@   IDLE   JCPU   PCPU WHAT
    root     :0       :0               262月18 ?xdm?   5:56m  2.44s gdm-session-worker [pam/gdm-p
    root     pts/0    :0               262月18 19:48m  0.13s  0.13s /bin/bash
    root     pts/1    10.21.95.237     三14    2.00s  0.26s  0.25s -bash
    + ls
    01.sh
    [root@bogon shell]# 
    

    6.查看脚本是否语法错误

    [root@bogon shell]# sh -n 01.sh 
    [root@bogon shell]# 
    

    (我们为了看到实验效果,故意写一个错的脚本,在for循环的结尾少写一个done)

    [root@bogon shell]# vim 01.sh 
    [root@bogon shell]# cat 01.sh
    #!/bin/bash
    
    for i in `seq 1 10`
    
    do
    
       echo $i
    [root@bogon shell]# sh -n 01.sh 
    01.sh:行8: 语法错误: 未预期的文件结尾
    [root@bogon shell]# 
    

    date命令用法

    1.在shell里直接输入date,会显示时间信息。

    [root@bogon shell]# date
    2018年 03月 15日 星期四 10:44:29 CST
    [root@bogon shell]# 
    

    2.日期显示成英文

    [root@bogon shell]# LANG=en
    [root@bogon shell]# date
    Thu Mar 15 10:51:31 CST 2018
    [root@bogon shell]# 
    

    3.标记四位的年

    [root@bogon shell]# date +%Y
    2018
    [root@bogon shell]# 
    

    4.标记两位的年

    [root@bogon shell]# date +%y
    18
    [root@bogon shell]# 
    

    5.显示月份

    [root@bogon shell]# date +%m
    03
    

    6.显示分钟

    [root@bogon shell]# date +%M
    54
    [root@bogon shell]# 
    

    7.显示日期

    [root@bogon shell]# date +%d
    15
    [root@bogon shell]# 
    

    8.外国日期显示法

    [root@bogon shell]# date +%D
    03/15/18
    [root@bogon shell]#
    

    9.显示年月日

    [root@bogon shell]# date +%Y%m%d
    20180315
    [root@bogon shell]# 
    
    [root@bogon shell]# date +%F
    2018-03-15
    [root@bogon shell]# 
    

    10.显示小时

    [root@bogon shell]# date +%H
    11
    [root@bogon shell]# 
    

    11.显示时间戳

    [root@bogon shell]# date +%s
    1521083272
    [root@bogon shell]# 
    

    12.显示秒

    [root@bogon shell]# date +%S
    50
    [root@bogon shell]# 
    

    13.显示时间

    [root@bogon shell]# date +%T
    11:10:04
    [root@bogon shell]# 
    
    [root@bogon shell]# date +%H:%M:%S
    11:12:15
    [root@bogon shell]# 

    14.英文的月

    [root@bogon shell]# date +%h
    Mar
    [root@bogon shell]#
    

    15.显示周几

    [root@bogon shell]# date +%w
    4
    [root@bogon shell]# 
    

    16.显示今年的第几周

    [root@bogon shell]# date +%W
    11
    [root@bogon shell]# 
    

    17.显示日期cal

    [root@bogon shell]# cal
         March 2018     
    Su Mo Tu We Th Fr Sa
                 1  2  3
     4  5  6  7  8  9 10
    11 12 13 14 15 16 17
    18 19 20 21 22 23 24
    25 26 27 28 29 30 31
    
    [root@bogon shell]# 
    

    18.显示年月日时分秒

    [root@bogon shell]# date +%Y-%m-%d/%H:%M:%S
    2018-03-15/11:19:47
    [root@bogon shell]# 
    
    [root@bogon shell]# date +%F/%T
    2018-03-15/11:20:49
    [root@bogon shell]# 
    

    19.所以我们得出结论

    date +%Y-%m-%d = date +%F

    date  +/%H:%M:%S = date +%T

    20.现在有一个实例,今天是1月11日,你要写一个切割日志脚本,在每天的0点切割日志,但是我们都知道,一到0点,时间就会显示后一天。所以我们要学会增加减少,我们以减少为例。

    显示昨天的日期

    [root@bogon shell]# date -d "-1 day"
    Wed Mar 14 11:25:30 CST 2018
    [root@bogon shell]# date -d "-1 day" +%F
    2018-03-14
    [root@bogon shell]# 
    

    21.显示一个月前的今天

    [root@bogon shell]# date -d "-1 month" +%F   
    2018-02-15
    [root@bogon shell]# 
    

    22.显示去年的今天

    [root@bogon shell]# date -d "-1 years" +%F     
    2017-03-15
    [root@bogon shell]# 
    

    23.前一小时

    [root@bogon shell]# date -d "-1 hour" +%T
    10:29:41
    [root@bogon shell]# 
    

    24.将时间戳显示为日期形式

    [root@bogon shell]# date -d @1521084694
    Thu Mar 15 11:31:34 CST 2018
    [root@bogon shell]# 
    

    25.将日期显示为时间戳

    [root@bogon shell]# date +%s -d "2018-03-15 00:00:00"  
    1521043200
    [root@bogon shell]# 
    

     Shell脚本中的变量

    当脚本中使用某个字符串比较频繁,并且字符串长度很长时间,就应该使用变量代替,使脚本变的简单明了

    使用条件语句时,尝试用变量 if[$a -gt 1];then...;fi

    引用某个命令时,用变量替代 n='wc -l 1.txt'

    写用户交互脚本时,变量也是必不可少的

    内置变量$1,$2,$3...$0表示脚本本身,$1第一个参数,$2第二个,...$#表示参数个数

    数学运算a=1;b=2;c=$(($a+$b))或者$[$a+$b]

     Shell脚本中的逻辑判断

    1.for循环用;和不用;号,seq用于产生从某个数到另外一个数之间的所有整数
    例一:
    # seq 1 10

    [root@bogon shell]# for i in `seq 1 5`; do echo $i; done
    1
    2
    3
    4
    5
    [root@bogon shell]# 
    
    [root@bogon shell]# for i in `seq 1 5`
    > do
    > echo $i
    > done
    1
    2
    3
    4
    5
    [root@bogon shell]# 
    

    2.如果a大于3然后输出ok(用空格分隔开)

    [root@bogon shell]# a=5
    [root@bogon shell]# if [ $a -gt 3 ]; then echo ok; fi
    ok
    [root@bogon shell]# 
    

    3.逻辑判断表达式:

    -gt = 大于    -lt = 小于    -ge = 大于等于   -le = 小于等于   -eq = 恒等于  -ne = 不等于

    4.格式1:if条件;then语句;fi        (如果...然后...)

    [root@bogon shell]# vi if1.sh
    [root@bogon shell]# sh if1.sh 
    ok
    [root@bogon shell]# cat if1.sh 
    #!/bin/bash
    a=5
    if [ $a -gt 3 ]
    then
            echo ok
    fi
    [root@bogon shell]# 
    

    5.格式2:if条件;then语句;else语句;fi        (如果...然后...;不满足条件...然后....)

    [root@bogon shell]# vi if1.sh
    [root@bogon shell]# sh if1.sh 
    no ok
    [root@bogon shell]# cat if1.sh 
    #!/bin/bash
    a=1
    if [ $a -gt 3 ]
    then
            echo ok
    else
            echo no ok
    fi
    [root@bogon shell]# 
    

    6.格式3:if...;then...;elif...;then...;else...;fi (如果...然后...;还有...然后...,不满足条件...然后...)

    [root@bogon shell]# vi if1.sh 
    [root@bogon shell]# sh if1.sh 
    <6 && >=1
    [root@bogon shell]# cat if1.sh 
    #!/bin/bash
    a=5
    if [ $a -lt 1 ]
    then
            echo '<1'
    elif [ $a -lt 6 ]
    then
            echo '<6 && >=1'
    else
            echo no ok
    fi
    [root@bogon shell]# 
    

    7.用数学符号的>  < 也可以,需要改书写格式

    [root@bogon shell]# a=3
    [root@bogon shell]# if (($a>1)); then echo ok; fi
    ok
    [root@bogon shell]# 

    8.也可以用&&和||结合多个条件

    [root@bogon shell]# vi if1.sh 
    [root@bogon shell]# sh if1.sh 
    <6=5
    [root@bogon shell]# cat if1.sh 
    #!/bin/bash
    a=5
    if [ $a -lt 6 ] && [ $a -eq 5 ]
    then
            echo '<6=5'
    else
            echo no ok
    fi
    [root@bogon shell]# 
    

     文件目录属性判断

     1.[-f file]判断是否是普通文件,是否存在

    [root@bogon shell]# vi file1.sh 
    [root@bogon shell]# cat file1.sh 
    #!/bin/bash
    f="/tmp/testfile"
    if [ -f $f ]
    then
            echo $f exist
    else
            touch $f
    fi
    第一次执行
    [root@bogon shell]# sh -x file1.sh 
    + f=/tmp/testfile
    + '[' -f /tmp/testfile ']'
    + touch /tmp/testfile 
    第二次执行
    [root@bogon shell]# sh -x file1.sh   
    + f=/tmp/testfile
    + '[' -f /tmp/testfile ']'
    + echo /tmp/testfile exist
    /tmp/testfile exist
    [root@bogon shell]# 
    

    2.判断是否是普通目录,是否存在

    [root@bogon shell]# vi file2.sh  
    [root@bogon shell]# cat file2.sh 
    #!/bin/bash
    d="/tmp/files"
    if [ -d $d ]
    then
            echo $d exist
    else
            mkdir $d
    fi
    [root@bogon shell]# sh -x file2.sh 
    + d=/tmp/files
    + '[' -d /tmp/files ']'
    + mkdir /tmp/files
    [root@bogon shell]# sh -x file2.sh 
    + d=/tmp/files
    + '[' -d /tmp/files ']'
    + echo /tmp/files exist
    /tmp/files exist
    [root@bogon shell]# 
    

    3.[-e file]只是判断文件或者目录是否存在

    [root@bogon shell]# vi file3.sh 
    [root@bogon shell]# cat file3.sh 
    #!/bin/bash
    f="/tmp/efile"
    if [ -e $f ]
    then
            echo $f exsit
    else
            touch $f
    fi
    [root@bogon shell]# sh -x file3.sh 
    + f=/tmp/efile
    + '[' -e /tmp/efile ']'
    + touch /tmp/efile
    [root@bogon shell]# sh -x file3.sh 
    + f=/tmp/efile
    + '[' -e /tmp/efile ']'
    + echo /tmp/efile exsit
    /tmp/efile exsit
    [root@bogon shell]# 
    

    4.[ -r $f ] [ -w $f ] [ -x $f ]分别表示辨别一个文件是否可读,可写,可执行

     可读

    [root@centos-02 ~]# vi file4.sh
    [root@centos-02 ~]# cat file4.sh 
    #!/bin/bash
    f="/tmp/file"
    if [ -r $f ]
    then
    	echo $f readable
    else
    	touch $f
    fi
    [root@centos-02 ~]# sh -x file4.sh 
    + f=/tmp/file
    + '[' -r /tmp/file ']'
    + echo /tmp/file readable
    /tmp/file readable
    [root@centos-02 ~]#  

    可写

    [root@centos-02 ~]# vi file4.sh
    [root@centos-02 ~]# cat file4.sh 
    #!/bin/bash
    f="/tmp/file"
    if [ -w $f ]
    then
    	echo $f writeable
    else
    	touch $f
    fi
    [root@centos-02 ~]# sh -x file4.sh 
    + f=/tmp/file
    + '[' -w /tmp/file ']'
    + echo /tmp/file writeable
    /tmp/file writeable
    [root@centos-02 ~]#   

    可执行

    [root@centos-02 ~]# vi file4.sh
    [root@centos-02 ~]# cat file4.sh 
    #!/bin/bash
    f="/tmp/file"
    if [ -x $f ]
    then
    	echo $f exeable
    else
    	touch $f
    fi
    [root@centos-02 ~]# sh -x file4.sh 
    + f=/tmp/file
    + '[' -x /tmp/file ']'
    + touch /tmp/file
    [root@centos-02 ~]# 
    

    2.另外一种if判断写法

    [root@centos-02 ~]# vi file5.sh
    [root@centos-02 ~]# cat file5.sh 
    #!/bin/bash
    f="/tmp/file"
    [ -f $f ] && rm -f $f (如果前面成立,执行后面的)
    等于
    if [ -f $f ]  
    then
    	rm -f $f
    fi


    [ -f $f ] || touch $f (如果前面的不成立,执行后面的)
    [ ! -f $f] (如果$f文件不存在)
    [root@centos-02 ~]#

    if特殊用法                      

    1.-z 判断变量值为空时

    [root@centos-02 ~]# vim file5.sh 
    [root@centos-02 ~]# cat file5.sh 
    #!/bin/bash
    n=`wc -l /tmp/file11111`
    
    if [ -z "$n" ]  
    then
    	echo empty
    fi
    [root@centos-02 ~]# sh -x file5.sh 
    ++ wc -l /tmp/file11111
    wc: /tmp/file11111: 没有那个文件或目录
    + n=
    + '[' -z '' ']'
    + echo empty
    empty
    [root@centos-02 ~]# 
    

    2.-n 判断变量值不为空的时候

    [root@centos-02 ~]# vim file5.sh 
    [root@centos-02 ~]# cat file5.sh 
    #!/bin/bash
    n=`wc -l /tmp/file`
    
    if [ -n "$n" ]  
    then
    	echo noempty
    fi
    [root@centos-02 ~]# sh -x file5.sh 
    ++ wc -l /tmp/file
    + n='0 /tmp/file'
    + '[' -n '0 /tmp/file' ']'
    + echo noempty
    noempty
    [root@centos-02 ~]# 
    

    3.还可以判断文件是否为空(变量的时候需要用双引号引起来,如果是文件的话就不用了)

    [root@centos-02 ~]# ls
    123  anaconda-ks.cfg  dir  dir1  file4.sh  file5.sh
    [root@centos-02 ~]# if [ -n anaconda-ks.cfg ]; then echo ok; fi
    ok
    [root@centos-02 ~]# 
    
    [root@centos-02 ~]# echo $b
    
    [root@centos-02 ~]# if [ -n "$b" ]; then echo $b; else echo "null"; fi
    null
    [root@centos-02 ~]# 
    

    4.使用命令的结果作为判断条件(-w是精准匹配单词,-q是仅仅做过滤,但是不把过滤的内容显示出来)

    [root@centos-02 ~]# grep -w 'user1' /etc/passwd
    user1:x:1004:1002::/home/user1:/bin/bash
    [root@centos-02 ~]# if grep -wq 'user1' /etc/passwd; then echo "user1 exist"; fi
    user1 exist
    [root@centos-02 ~]# 
    

    5.如果不存在user1就创建一个

    [root@centos-02 ~]# if ! grep -wq 'user1' /etc/passwd; then useradd user1; fi
    [root@centos-02 ~]# 
    

    case判断  

    1. (;;)双分号表示,这个条件执行结束,进入下个判断

    2.我们在介绍case这个命令之前,先解释一个read -p命令。

    [root@bogon shell]# read -p "Please input a number:" n
    Please input a number:5
    [root@bogon shell]# echo $n
    5
    [root@bogon shell]# 
    

    3.通过上面的实验我们可以发现,read -p 可以和用户实现一个交互,并赋给变量一个值n。

    我们等会写一个关于case的脚本。我们把它分成2部分来解析。首先看第一部分:

    #!/bin/bash
    read -p "Please input a number:" n
    if [ -z "$n" ]
    then
            echo "Please input a number."
            exit 1
    fi
    

    4.首先,我们让用户输入一个数字,-z表示如果变量为空,那么会返回一个Please input a number.的字符串,并且exit退出。

    还记得我们编译时,如果失败了,当我们用echo $?查询时,发现返回值为1,这里的1就是这个意思。

    [root@bogon shell]# vim sh1.sh
    [root@bogon shell]# cat sh1.sh 
    #!/bin/bash
    read -p "Please input a number:" n
    if [ -z "$n" ]
    then
            echo "Please input a number."
            exit 1
    fi
    
    [root@bogon shell]# sh sh1.sh 
    Please input a number:
    Please input a number.
    [root@bogon shell]# echo $?
    1
    [root@bogon shell]# 
    

    5.如果用户输入的值不为空,那么跳入这一步,首先会把用户输入的变量拿出来,做一个过滤,sed命令把所有数字全部清空,-n表示如果sed清空数字后,字符不为空,则表示用户输入了一个不是数字的字符,则会返回,Please input a number!,这里加一个!和上面的做区分。

    n1=`echo $n|sed 's/[0-9]//g'`
    
    if [ -n(或者! -z) "$n1" ]
    
    then
    
     echo "Please input a number."
    
     exit 1
    
    fi  

    6.执行结果:

    [root@bogon shell]# vim sh1.sh
    [root@bogon shell]# sh -x sh1.sh 
    + read -p 'Please input a number:' n
    Please input a number:5
    + '[' -z 5 ']'
    ++ echo 5
    ++ sed 's/[-0-9]//g'
    + n1=
    + '[' '!' -z ']'
    + '[' 5 -lt 60 ']'
    + '[' 5 -ge 0 ']'
    + tag=1
    + case $tag in
    + echo 'not ok'
    not ok
    [root@bogon shell]# sh -x sh1.sh 
    + read -p 'Please input a number:' n
    Please input a number:80
    + '[' -z 80 ']'
    ++ echo 80
    ++ sed 's/[-0-9]//g'
    + n1=
    + '[' '!' -z ']'
    + '[' 80 -lt 60 ']'
    + '[' 80 -ge 60 ']'
    + '[' 80 -lt 80 ']'
    + '[' 80 -ge 80 ']'
    + '[' 80 -lt 90 ']'
    + tag=3
    + case $tag in
    + echo ook
    ook
    [root@bogon shell]# 

    完整代码

    #!/bin/bash
    read -p "Please input a number:" n
    if [ -z "$n" ]
    then
            echo "Please input a number."
            exit 1
    fi
    
    n1=`echo $n|sed 's/[-0-9]//g'`
    if [ ! -z $n1 ]
    then
            echo "Please input a number."
            exit 1
    fi
    
    if [ $n -lt 60 ] && [ $n -ge 0 ]
    then
            tag=1
    elif [ $n -ge 60 ] && [ $n -lt 80 ]
    then
            tag=2
    elif [ $n -ge 80 ] && [ $n -lt 90 ]
    then
            tag=3
    elif [ $n -ge 90 ] && [ $n -le 100 ]
    then
            tag=4
    else
            tag=0
    fi
    
    case $tag in
            1)
            echo "not ok"
            ;;
            2)
            echo "ok"
            ;;
            3)
            echo "ook"
            ;;
            4)
            echo "oook"
            ;;
            *)
            echo "The number range 0-100"
            ;;
    esac
    

    第二部分:使用了if...then...;elif...then...;eles....

    如果变量是n大于等于0,小于等于60,则变量tag=1。

    如果变量n大于等于60,小于等于80,则变量tag=2。

    如果变量n大于等于80,小于等于90,则变量tag=3。

    如果变量n大于等于90,小于等于100,则变量tag=4。

    if [ $n -lt 60 ] && [ $n -ge 0 ]
    then
            tag=1
    elif [ $n -ge 60 ] && [ $n -lt 80 ]
    then
            tag=2
    elif [ $n -ge 80 ] && [ $n -lt 90 ]
    then
            tag=3
    elif [ $n -ge 90 ] && [ $n -le 100 ]
    then
            tag=4
    else
            tag=0
    fi
    

    第三部分,就是我们要说的case循环了.注意格式,case 变量 in ,1)...;; 2)...;; 3)...;;,最后结尾用esac,我们也可以|来表示并列,例如,3|4),就是当变量等于3或者4时,返回下面的命令。

    case $tag in
            1)
            echo "not ok"
            ;;
            2)
            echo "ok"
            ;;
            3)
            echo "ook"
            ;;
            4)
            echo "oook"
            ;;
            *)
            echo "The number range 0-100"
            ;;
    esac
    

    for循环

    1.计算1-10所有数字的和

    执行过程:

    0+1

    1+2

    3+3

    6+4

    10+5

    15+6

    ……

    [root@bogon shell]# vim for.sh 
    [root@bogon shell]# cat for.sh 
    #!/bin/bash
    sum=0
    for i in `seq 1 10`
    do
            sum=$[$sum+$i]
    done
    echo $sum
    [root@bogon shell]# sh -x for.sh 
    + sum=0
    ++ seq 1 10
    + for i in '`seq 1 10`'
    + sum=1
    + for i in '`seq 1 10`'
    + sum=3
    + for i in '`seq 1 10`'
    + sum=6
    + for i in '`seq 1 10`'
    + sum=10
    + for i in '`seq 1 10`'
    + sum=15
    + for i in '`seq 1 10`'
    + sum=21
    + for i in '`seq 1 10`'
    + sum=28
    + for i in '`seq 1 10`'
    + sum=36
    + for i in '`seq 1 10`'
    + sum=45
    + for i in '`seq 1 10`'
    + sum=55
    + echo 55
    55
    [root@bogon shell]# 
    

    2.列出/etc/sysconfig下所有子目录,并且使用ls -d命令查看。

    [root@centos-02 etc]# vim etcsh.sh 
    [root@centos-02 etc]# cat etcsh.sh 
    #!/bin/bash
    cd /etc/sysconfig
    for a in `ls /etc/sysconfig`
    do
    	if [ -d $a ]
    	then
    		echo $a
    		ls $a
    	fi
    done
    [root@centos-02 etc]# sh -x etcsh.sh 
    + cd /etc/sysconfig
    ++ ls /etc/sysconfig
    + for a in '`ls /etc/sysconfig`'
    + '[' -d authconfig ']'
    + for a in '`ls /etc/sysconfig`'
    + '[' -d cbq ']'
    + echo cbq
    cbq
    + ls cbq
    avpkt  cbq-0000.example
    + for a in '`ls /etc/sysconfig`'
    + '[' -d console ']'
    + echo console
    console
    + ls console
    + for a in '`ls /etc/sysconfig`'
    + '[' -d cpupower ']'
    + for a in '`ls /etc/sysconfig`'
    + '[' -d crond ']'
    + for a in '`ls /etc/sysconfig`'
    + '[' -d ebtables-config ']'
    + for a in '`ls /etc/sysconfig`'
    + '[' -d firewalld ']'
    + for a in '`ls /etc/sysconfig`'
    + '[' -d grub ']'
    + for a in '`ls /etc/sysconfig`'
    + '[' -d htcacheclean ']'
    + for a in '`ls /etc/sysconfig`'
    + '[' -d httpd ']'
    + for a in '`ls /etc/sysconfig`'
    + '[' -d init ']'
    + for a in '`ls /etc/sysconfig`'
    + '[' -d ip6tables ']'
    + for a in '`ls /etc/sysconfig`'
    + '[' -d ip6tables-config ']'
    + for a in '`ls /etc/sysconfig`'
    + '[' -d iptables ']'
    + for a in '`ls /etc/sysconfig`'
    + '[' -d iptables-config ']'
    + for a in '`ls /etc/sysconfig`'
    + '[' -d iptables.save ']'
    + for a in '`ls /etc/sysconfig`'
    + '[' -d irqbalance ']'
    + for a in '`ls /etc/sysconfig`'
    + '[' -d kdump ']'
    + for a in '`ls /etc/sysconfig`'
    + '[' -d keepalived ']'
    + for a in '`ls /etc/sysconfig`'
    + '[' -d kernel ']'
    + for a in '`ls /etc/sysconfig`'
    + '[' -d man-db ']'
    + for a in '`ls /etc/sysconfig`'
    + '[' -d modules ']'
    + echo modules
    modules
    + ls modules
    + for a in '`ls /etc/sysconfig`'
    + '[' -d netconsole ']'
    + for a in '`ls /etc/sysconfig`'
    + '[' -d network ']'
    + for a in '`ls /etc/sysconfig`'
    + '[' -d network-scripts ']'
    + echo network-scripts
    network-scripts
    + ls network-scripts
    ifcfg-ens33  ifdown-isdn      ifup	    ifup-plip	   ifup-tunnel
    ifcfg-lo     ifdown-post      ifup-aliases  ifup-plusb	   ifup-wireless
    ifdown	     ifdown-ppp       ifup-bnep     ifup-post	   init.ipv6-global
    ifdown-bnep  ifdown-routes    ifup-eth	    ifup-ppp	   network-functions
    ifdown-eth   ifdown-sit       ifup-ib	    ifup-routes    network-functions-ipv6
    ifdown-ib    ifdown-Team      ifup-ippp     ifup-sit
    ifdown-ippp  ifdown-TeamPort  ifup-ipv6     ifup-Team
    ifdown-ipv6  ifdown-tunnel    ifup-isdn     ifup-TeamPort
    + for a in '`ls /etc/sysconfig`'
    + '[' -d rdisc ']'
    + for a in '`ls /etc/sysconfig`'
    + '[' -d readonly-root ']'
    + for a in '`ls /etc/sysconfig`'
    + '[' -d rsyslog ']'
    + for a in '`ls /etc/sysconfig`'
    + '[' -d run-parts ']'
    + for a in '`ls /etc/sysconfig`'
    + '[' -d selinux ']'
    + for a in '`ls /etc/sysconfig`'
    + '[' -d sshd ']'
    + for a in '`ls /etc/sysconfig`'
    + '[' -d wpa_supplicant ']'
    [root@centos-02 etc]# 
    

    2.for循环另外一种写法`seq 1 3` == 1 2 3

    [root@centos-02 ~]# for i in `seq 1 3`; do echo $i; done
    1
    2
    3
    [root@centos-02 ~]# for i in 1 2 3; do echo $i; done
    1
    2
    3
    [root@centos-02 ~]# 
    

    3.建立三个文件1 2 3空格4.txt

    [root@centos-02 ~]# touch 1 2 3 4.txt
    [root@centos-02 ~]# ls -l
    总用量 12
    -rw-r--r--  1 root root        0 3月  18 14:56 1
    lrwxrwxrwx. 1 root root       11 11月 15 21:32 123 -> dir/123.txt
    -rw-r--r--  1 root root        0 3月  18 14:56 2
    -rw-r--r--  1 root root        0 3月  18 14:56 3 4.txt
    -rw-------. 1 root root     1422 11月  5 06:16 anaconda-ks.cfg
    drwxr-sr-x. 2 root sunyujun   44 11月 15 23:34 dir
    drwxr-xr-x. 3 root root       38 11月 12 16:24 dir1
    -rw-r--r--  1 root root       79 3月  15 22:27 file4.sh
    -rw-r--r--  1 root root       72 3月  15 23:19 file5.sh
    

    4.最终循环出来了1 2 3 4.txt,将3 4.txt一个文件分成了两个文件了,它会已空格或者回车进行分割

    [root@centos-02 ~]# for i in `ls ./`; do echo $i ; done
    1
    123
    2
    3
    4.txt
    anaconda-ks.cfg
    dir
    dir1
    file4.sh
    file5.sh
    [root@centos-02 ~]# 
    

     while循环

    语法 while条件;do...;done

    写一个脚本来监控系统负载,当系统负载大于10时,发邮箱警告

    [root@centos-02 ~]# vim while1.sh
    [root@centos-02 ~]# cat while1.sh 
    while : (:号可以换成true)
    do 
        load=`w|head -1|awk -F 'load average: ' '{print $2}'|cut -d. -f1`
        if [ $load -gt 10 ]
        then
            /usr/local/sbin/mail.py xxx@qq.com "load high" "$load"
        fi
        sleep 30
    done
    [root@centos-02 ~]# 
    
    [root@centos-02 ~]# w (查看系统负载)
     15:15:13 up  2:24,  3 users,  load average: 0.04, 0.08, 0.09
    USER     TTY      FROM             LOGIN@   IDLE   JCPU   PCPU WHAT
    root     tty1                      六17   21:33m  0.06s  0.06s -bash
    root     pts/0    192.168.133.1    六17   20:16m  3.16s  3.16s -bash
    root     pts/1    192.168.133.1    14:50    1.00s  0.22s  0.05s w
    [root@centos-02 ~]# uptime (查看负载信息的第一行,等于w|head -1)
     15:15:18 up  2:24,  3 users,  load average: 0.04, 0.08, 0.09
    [root@centos-02 ~]# 
    [root@centos-02 ~]# uptime|awk -F 'load average:' '{print $2}' (awk -F 指定一个分割符load average:,打印出第二段)
     0.11, 0.07, 0.08
    [root@centos-02 ~]# [root@centos-02 ~]# uptime|awk -F 'load average:' '{print $2}'|cut -d . -f1 (cut -d . -f1 继续已点为分隔符截取第一段)
     0
    [root@centos-02 ~]# 
    [root@centos-02 ~]# uptime|awk -F 'load average:' '{print $2}'|cut -d . -f1|sed 's/ //'(sed 's/ //' 去掉0前面的空格)
    0
    [root@centos-02 ~]# 
    

    3.监控测试

    [root@centos-02 ~]# sh -x while1.sh 
    + :
    ++ head -1
    ++ w
    ++ awk -F 'load average: ' '{print $2}'
    ++ cut -d. -f1
    + load=0
    + '[' 0 -gt 10 ']'
    + sleep 30
    

    类似于之前写过的for循环的脚本,输入一个数字,如果不是数字返回一个字符串,如果输入为空返回一个字符串,如果是数字返回。

    在看脚本之前,我们需要知道continue和break的意思。

    continue是继续的意思,也就是当运行结果不满足条件时,在从头循环一遍。

    break是跳出循环的意思。

    [root@centos-02 ~]# vim while2.sh 
    [root@centos-02 ~]# cat while2.sh 
    #/bin/bash
    while :
    do
        read -p "please input a number: " n
        if [ -z "$n" ]
        then
           echo "你需要输入东西."
           continue
        fi
        n1=`echo $n|sed 's/[0-9]//g'`
        if [ ! -z "$n1" ]
        then
           echo "你只能输入一个纯数字."
           continue
        fi
        break
    done
    echo $n
    [root@centos-02 ~]# sh -x while2.sh 
    + :
    + read -p 'please input a number: ' n
    please input a number: 8
    + '[' -z 8 ']'
    ++ echo 8
    ++ sed 's/[0-9]//g'
    + n1=
    + '[' '!' -z '' ']'
    + break
    + echo 8
    8
    [root@centos-02 ~]# sh -x while2.sh 
    + :
    + read -p 'please input a number: ' n
    please input a number: a
    + '[' -z a ']'
    ++ echo a
    ++ sed 's/[0-9]//g'
    + n1=a
    + '[' '!' -z a ']'
    + echo $'344275240345217252350203275350276223345205245344270200344270252347272257346225260345255227.'
    你只能输入一个纯数字.
    + continue
    + :
    + read -p 'please input a number: ' n
    please input a number: 8
    + '[' -z 8 ']'
    ++ echo 8
    ++ sed 's/[0-9]//g'
    + n1=
    + '[' '!' -z '' ']'
    + break
    + echo 8
    8
    [root@centos-02 ~]# 
    

     break跳出循环  

     

    break在while循环中,我们提到了,这里来写一个脚本,加深印象

    如果输入的数字等于3,则跳出循环,则输出aaaa

    [root@bogon sunyujun]# vim break.sh 
    [root@bogon sunyujun]# cat break.sh 
    #!/bin/bash
    for i in `seq 1 5`
    do
            echo $i
            if [ $i -eq 3 ]
            then
                    break
            fi
            echo $i
    done
    echo aaa
    [root@bogon sunyujun]# sh -x break.sh 
    ++ seq 1 5
    + for i in '`seq 1 5`'
    + echo 1
    1
    + '[' 1 -eq 3 ']'
    + echo 1
    1
    + for i in '`seq 1 5`'
    + echo 2
    2
    + '[' 2 -eq 3 ']'
    + echo 2
    2
    + for i in '`seq 1 5`'
    + echo 3
    3
    + '[' 3 -eq 3 ']'
    + break
    + echo aaa
    aaa
    [root@bogon sunyujun]# sh break.sh 
    1
    1
    2
    2
    3
    aaa
    [root@bogon sunyujun]# 
    

    continue结束本次循环

    [root@bogon sunyujun]# vim continue.sh 
    [root@bogon sunyujun]# cat continue.sh 
    #!/bin/bash
    for i in `seq 1 5`
    do
            echo $i
            if [ $i -eq 3 ]
            then
                    continue
            fi
            echo $i
    done
    echo aaa
    [root@bogon sunyujun]# sh -x continue.sh 
    ++ seq 1 5
    + for i in '`seq 1 5`'
    + echo 1
    1
    + '[' 1 -eq 3 ']'
    + echo 1
    1
    + for i in '`seq 1 5`'
    + echo 2
    2
    + '[' 2 -eq 3 ']'
    + echo 2
    2
    + for i in '`seq 1 5`'
    + echo 3
    3
    + '[' 3 -eq 3 ']'
    + continue
    + for i in '`seq 1 5`'
    + echo 4
    4
    + '[' 4 -eq 3 ']'
    + echo 4
    4
    + for i in '`seq 1 5`'
    + echo 5
    5
    + '[' 5 -eq 3 ']'
    + echo 5
    5
    + echo aaa
    aaa
    [root@bogon sunyujun]# sh continue.sh 
    1
    1
    2
    2
    3
    4
    4
    5
    5
    aaa
    [root@bogon sunyujun]# 
    

    exit退出整个脚本  

    1.exit 直接退出程序,aaa都不输出了

    [root@bogon sunyujun]# vim exit.sh 
    [root@bogon sunyujun]# cat exit.sh 
    #!/bin/bash
    for i in `seq 1 5`
    do
            echo $i
            if [ $i -eq 3 ]
            then
                    exit
            fi
            echo $i
    done
    echo aaa
    [root@bogon sunyujun]# sh -x exit.sh 
    ++ seq 1 5
    + for i in '`seq 1 5`'
    + echo 1
    1
    + '[' 1 -eq 3 ']'
    + echo 1
    1
    + for i in '`seq 1 5`'
    + echo 2
    2
    + '[' 2 -eq 3 ']'
    + echo 2
    2
    + for i in '`seq 1 5`'
    + echo 3
    3
    + '[' 3 -eq 3 ']'
    + exit
    [root@bogon sunyujun]# sh exit.sh 
    1
    1
    2
    2
    3
    [root@bogon sunyujun]# 
    

    2.我们也可以将exit退出时加一个数字

    [root@bogon sunyujun]# vim exit.sh 
    [root@bogon sunyujun]# cat exit.sh 
    #!/bin/bash
    for i in `seq 1 5`
    do
            echo $i
            if [ $i -eq 3 ]
            then
                    exit 3
            fi
            echo $i
    done
    echo aaa
    [root@bogon sunyujun]# sh exit.sh 
    1
    1
    2
    2
    3
    [root@bogon sunyujun]# echo $?
    3
    [root@bogon sunyujun]# 
    

    shell中的函数  

     1.注意$10并不能打印出第10个函数,当n>=10时,用{10}来获取函数。$0表示脚本名字。$#表示多少个参数。

     

    [root@centos-02 ~]# vim function.sh 
    [root@centos-02 ~]# cat function.sh 
    #!/bin/bash
    function inp(){
    	echo $0 $1 $2 $3 $#
    }
    
    inp 1 2 3 4 
    [root@centos-02 ~]# sh -x function.sh 
    + inp 1 2 3 4
    + echo function.sh 1 2 3 4
    function.sh 1 2 3 4
    [root@centos-02 ~]# 
    

      

    2.执行脚本的时候直接传参数

    [root@centos-02 ~]# vim function.sh 
    [root@centos-02 ~]# cat function.sh 
    #!/bin/bash
    function inp(){
    	echo $0 $1 $#
    }
    
    inp $1 (外面传进来的参数)
    [root@centos-02 ~]# sh function.sh 5
    function.sh 5 1
    [root@centos-02 ~]# 
    

    用来定义一个加法

    [root@centos-02 ~]# vim function2.sh 
    [root@centos-02 ~]# cat function2.sh 
    #!/bin/bash
    sum(){
    	s=$[$1+$2]
    	echo $s
    }
    
    sum 1 10
    [root@centos-02 ~]# sh -x function2.sh 
    + sum 1 10
    + s=11
    + echo 11
    11
    [root@centos-02 ~]# 
    

    打印ip地址的最后一段,我这里是88,-A1指查找关键词所在的行和关键词所在行下面的一行

    [root@centos-02 ~]# ifconfig |grep -A1 "ens33" |tail -1 |awk '{print $2}' |awk -F '.' '{print $4}'
    

      

    写一个脚本,输入网卡名字则显示该网卡上的ip。

    [root@centos-02 ~]# vim function4.sh 
    [root@centos-02 ~]# cat function4.sh 
    #!/bin/bash
    ip(){
    	ifconfig |grep -A1 "$1: " |grep 'inet' |awk '{print $2}'
    }
    
    read -p "Please input the eth name: " eth
    ip $eth
    [root@centos-02 ~]# sh -x function4.sh 
    + read -p 'Please input the eth name: ' eth
    Please input the eth name: ens33
    + ip ens33
    + ifconfig
    + grep -A1 'ens33: '
    + grep inet
    + awk '{print $2}'
    192.168.133.88
    [root@centos-02 ~]# sh -x function4.sh 
    + read -p 'Please input the eth name: ' eth
    Please input the eth name: lo    
    + ip lo
    + ifconfig
    + grep -A1 'lo: '
    + grep inet
    + awk '{print $2}'
    127.0.0.1
    [root@centos-02 ~]# 
    

      

    三种获取ip的方法

    [root@centos-02 ~]# ifconfig |grep -A1 "ens33: " |tail -1 |awk '{print $2}'
    192.168.133.88
    [root@centos-02 ~]# ifconfig |grep -A1 "ens33: " |awk '/inet/ {print $2}'
    192.168.133.88
    [root@centos-02 ~]# ifconfig |grep -A1 "ens33: " |grep 'inet' |awk '{print $2}'
    192.168.133.88
    [root@centos-02 ~]# 
    

    shell中的数组  

    1.定义数组并查看数组全部值

    [root@centos-02 ~]# b=(1 2 3)
    [root@centos-02 ~]# echo ${b[*]}
    1 2 3
    [root@centos-02 ~]# echo ${b[@]}
    1 2 3
    [root@centos-02 ~]# 
    

    2.查看数组单一的值:(从零开始)

    [root@centos-02 ~]# echo ${b[0]}
    1
    [root@centos-02 ~]# 
    

    3.获取数组个数

    [root@centos-02 ~]# echo ${#b[*]}
    3
    [root@centos-02 ~]# 
    

    4.给数组赋值或更改

    [root@centos-02 ~]# b[3]=a
    [root@centos-02 ~]# echo ${b[*]}
    1 2 3 a
    [root@centos-02 ~]# 
    [root@centos-02 ~]# b[3]=b
    [root@centos-02 ~]# echo ${b[*]}
    1 2 3 b
    [root@centos-02 ~]# 
    

    5.删除元素unset

    [root@centos-02 ~]# unset b[3]
    [root@centos-02 ~]# echo ${b[*]}
    1 2 3
    [root@centos-02 ~]# 
    
    [root@centos-02 ~]# unset b
    [root@centos-02 ~]# echo ${b[*]}
    
    [root@centos-02 ~]# 
    

    1.数组分片(需求1到10,要求取从4-7)

    [root@centos-02 ~]# a=(`seq 1 10`)
    [root@centos-02 ~]# echo ${a[*]}
    1 2 3 4 5 6 7 8 9 10
    [root@centos-02 ~]# echo ${a[@]:3:4}
    4 5 6 7
    [root@centos-02 ~]# 
    

    2.从倒数第三个开始截,取两个

    格式:echo ${数组名称[@]:0-倒数第几个元素:截取几个}

    [root@centos-02 ~]# echo ${a[@]:0-3:2}
    8 9
    [root@centos-02 ~]#
    

    3.数组替换

    临时替换,将8改成6

    [root@centos-02 ~]# echo ${a[@]/8/6}
    1 2 3 4 5 6 7 6 9 10
    [root@centos-02 ~]# 

    永久替换

    [root@centos-02 ~]# a=(${a[@]/8/6})
    [root@centos-02 ~]# echo ${a[@]}
    1 2 3 4 5 6 7 6 9 10
    [root@centos-02 ~]# 
  • 相关阅读:
    Android 工程师进阶 34 讲
    300分钟搞定数据结构与算法
    即学即用的Spark实战44讲
    42讲轻松通关 Flink
    Webpack原理与实践
    大数据运维实战
    ZooKeeper源码分析与实战
    前端高手进阶
    重学数据结构与算法
    ElementUI中el-upload怎样上传文件并且传递额外参数给Springboot后台进行接收
  • 原文地址:https://www.cnblogs.com/sunyujun/p/8567590.html
Copyright © 2020-2023  润新知