shell 脚本

shell 脚本




shell 脚本基础


1. 基础

    基础符号
        # echo $?   // 上一次命令成功 会返回0 不成功返回非0

        #!/bin/bash
            ping -c1 www.baidu.com &>/dev/null && echo "baidu is up"  || echo "baidu is down"

        #!       shebang  解释器   没有明确指定解释器shebang会生效  写shell脚本 可以不写 此行 不是注释
        &>       标准输出和错误输出 ping的结果 重定向到 黑洞/dev/null
        &> a.txt 意思是把 标准输出 和 标准错误输出 都重定向到文件file中

        2>&1    意思是把 标准错误输出 重定向到 标准输出  写成2&>1是不可以的
        >       默认为标准输出重定向,与 1> 相同

                0表示标准输入
                1表示标准输出
                2表示标准错误输出
                符号>& 是一个整体 不可分开,分开后就不是上述含义了。
                &>和>& 语义上是没有任何区别的,但是第一中方式是最佳选择,一般使用第一种

        &&  前一个命令才会执行后面的命令
        ||  前面命令失败 执行
        ;   命令的排序 不管前面命令成功与否 都执行后面的命令
        !   !为历史命令记忆功能 
            # !815      执行第815条命令
            # !vim      执行最近一个以vim开头的命令
            # tail !$   $为上一条命令的最后一个参数
            # !!        执行上一个命令

    快捷键

        # ^a        Ctrl + a   光标移动到命令最前面
        # ^e        Ctrl + e   光标移动到命令最后面  
        # ^k        Ctrl + k   删除光标后面的内容
        # ^u        Ctrl + u   删除光标前面的内容

        # ^r        Ctrl + r 搜索历史命令
        # ^d        退出 同exit
        # ^y        Ctrl + y   粘贴 ^k ^u 删除的内容
        # ^l        Ctrl + l   清屏  同 clear
        # ^s        Ctrl + s   冻结
        # ^q        Ctrl + q   恢复冻结 


    通配符       \\ 在shell中     在正则表达式中不一样
        *  匹配多个字符
        ?  匹配任意一个字符
        [] 匹配括号中的任意一个字符
            [abc]
            [a-z]
            [0-9]
            [a-z0-9]
            [^0-9]         ^ 取反

            # ls l[io]ve
        () 在子shell中执行命令
            # (umask 077; touch aa.txt)    \\ 设置umask值 创建aa.txt并赋予权限 umask的值不会影响到当前shell
        {} 集合
            # mkdir -p {1,2,a}             \\ 创建目录 1 2 a
            # mkdir -p a{1,2}               \\ 创建目录 a1 a2
            # mkdir -p {1..3}{a..c}          \\ 创建目录 1a 1b 1c 2a 2b 2c 3a 3b 3c
            # cp a.txt{,.bak}                 \\ 复制a.txt 到 a.txt.bak
        \ 转义符


2. 变量类型

    变量名必须以字母或下划线开头 区分大小写
        # vim a.sh
            ip=192.168.10.11                           \\ 定义一个变量ip 只在当前shell中生效
            read ip                                     \\ 从标准输入 读取
            read -p "please input a ip: " ip             \\ -p 给出提示 语句

            if [ $? -eq 0 ]; then                          \\ if判断
                    echo "$ip is up"
            else
                    echo "$ip is down"
            fi

    位置变量
        系统定义的 变量1 为脚本的第一个参数  引用为 $1
        $1
        $2
        ...
        ${10}


    自定义变量
        # ip1=3.3.3.3              \\ 自定义变量 只在当前shell中有效 在脚本中定义的属于 自定义变量
        # source a.sh               \\ 可以加载a.sh中定义的变量 但是只在当前shell中生效
        # . a.sh                     \\ . 同 source

        echo ${NAME:-tom}       \\ 变量 NAME 有值 返回NAME的值 如果没有值 显示 tom
        echo ${NAME:+tom}        \\ 变量 NAME 有值 返回 tom 如果没有值 那就没有值 啥都不返回
        

    系统定义的环境变量
        $HOSTNAME    \\ 获取主机名
        $UID          \\ 获取当前用户的uid 为0 则是root用户 可以判断是不是root用户
        $USER          \\ 获取当前用户的 用户名
        $LOGNAME        \\ 获取当前用户的 用户名

    环境变量
        # export ip2=4.4.4.4     \\ 环境变量 仅仅对当前shell及子shell中有效 一般不使用环境变量
        # export ip1              \\ 把已存在的 自定义变量 转换成 环境变量  关闭当前shell则失效
        # unset ip2                \\ 删除已经定义的 环境变量ip1
        # env                       \\ 查看所有的环境变量

        # echo $PATH                \\ 可以看到 PATH 路径
        # vim /etc/profile           \\ 环境变量 声明的 文件 对 所有用户有效 永久有效
            PATH=$PATH:/new/bin       \\ 可以新加 地址
            export PATH
        # source /etc/profile           \\ 重新加载文件
        # echo $PATH

        # vim /etc/profile
            HISTSIZE=5000               \\ 修改history 数目为5000
        # source /etc/profile            \\ 重新加载文件

    引用变量 2种方法
        $ip        \\ 引用变量ip
        ${ip}       \\ 引用变量ip 有分歧的地方 使用{}

    预定义变量         \\ 可用于脚本中的 参数 统计
        $0  脚本名       返回带路径的脚本名
        $*  所有的参数
        $@  所有的参数
        $#  参数的个数
            ${#i}            \\ 可以返回 变量 i 的长度
        $$  当前进程的PID
        $!  上一个后台进程的PID
        $?  上一个命令的返回值 0表示成功 

    # basename /data/a.txt        \\ 取文件的 文件名
        a.txt
    # dirname /data/a.txt           \\ 取文件的  目录名
        

    变量的赋值
        1 显示赋值
            ip=192.168.10.10
            school="bei jing"                \\ 引号里面可以有空格等
            today1=`date +%F`                 \\ 反引号里面 可执行语句 先执行 等于 $() 命令替换
            today2=$(date +%F)                 \\ (先执行)
        2 从键盘读取
            read ip                          \\ 从键盘输入读取
            read -p "input ip: " ip           \\ -p" " 为提示信息
            read -t 5 -p "input ip: " ip       \\ -t 5 设定时间 5秒
            read -n 2 name                      \\ -n 2 只取前两个字符
            read ip1 ip2                         \\ 可以定义多个变量 空格隔开

        " "    双引号 弱引用    可以引用变量的值
        ' '    单引号 强引用

    变量的运算
        方法 1
            expr 1 + 2               \\ +加  -减  \*乘   /除  %取余数    
            expr `$i + $n`            \\ 两个变量相加
            sum=`expr $sum + $i`       \\ 运算并赋值

            # expr 1 + 2 \* 5

            注: 都有空格
                默认会把计算结果输出到 屏幕
        方法 2                          \\ +加  -减  *乘  /除  %取余数
            echo $((1+2))                \\ $(())    里面放运算 算式
            echo $(($num1+$num2))         \\ 两个变量相加
            echo $((num1+num2))            \\ 两个变量相加    可以省略里面的 $符号
            echo $((5-3*2)) 
            echo $(((5-3)*2))                \\ 里面() 为先算
            echo $((2**5))                    \\ 2的5次方
            sum=$((1+2)); echo $sum            \\ 计算的值 给变量sum

            注:  用于 要运算的结果
                借助echo输出而已 默认没有输出
        方法 3
            echo $[]                 \\ +加  -减  *乘  /除  %取余数   用法同 $(())
        方法 4
            let i=2+3
            let i++         先赋值在计算
            let ++i         先计算
            let i=i+1

            let sum=$sum+$i     用sum的值加上i的值赋给sum    
            let sum+=$i         用sum的值加上i的值赋给sum
            let sum-=$i         用sum的值减去i的值赋给sum
            let sum*=$i
            let sum\=$i

            注: let用于变量赋值 时候的 运算
                不能加空格

    小数运算
        bc                       \\ 交互式计算器
        echo "2*4" | bc           \\ 一般使用传递参数 使用
        echo "2^4" | bc            \\ 2的四次方
        echo "scale=2;6/4"          \\ 保留两位小数

    变量的删除
        url=www.baidu.com      \\ 做以下操作不会对变量进行改变
        ${#url}                 \\ 获取变量的长度 可使用 echo ${#url} 协助查看
        ${url#www.}              \\ 删除 www.
        ${url#*bai}               \\ 删除 www.bai    *为匹配前面的字符
        ${url#*.}                  \\ 最短匹配 1个# 从前往后删除 到 第一个点 .
        ${url##*.}                  \\ 贪婪匹配 2个## 从前往后删除 到 最后一个点 .
        ${url%.com}                  \\ %从后往前删除
        ${url%.*}                     \\ 从后往前删除 到.
        ${url%%.*}                     \\ 从后往前删除 删除到最后一个点 .

        索引及切片
            url=www.baidu.com
                0123456789             \\ 对应的索引  一次类推10 11 12 ... ...
            ${url:0:5}                  \\ 从第0个索引取5个值
                www.b
            ${url:5:5}                    \\ 从第5个索引取5个值
                idu.c
            ${url:5}                        \\ 从第5个索引到最后

        替换
            url=www.baidu.com
            ${url/baidu/google}      \\ baidu 换个 googel

        替代
            ${var1-baidu.com}     \\ 变量var1  -为替代符号 如果变量var1有值或空值 则不替代 如果没有定义则赋予baidu.com
            ${var2:-baidu.com}     \\ 变量var2  :-为替代符号 如果变量var2有值则不替代 如果没有定义或空值则赋予baidu.com
            +
            :
            =
            :=
            ?
            :?

    脚本中的符号

        continue  \\ 跳过 跳过此次循环 执行下一次循环               只在循环中有效的参数
        break      \\ 跳出循环 结束循环  离开循环  执行后面的代码    只在循环中有效的参数
        break 1     \\ 同上 跳出 1层循环
        break 2      \\ 跳出 2层循环
        exit          \\ 结束符号  退出脚本 后面的代码 不在执行      任何时候碰到都退出脚本
        exit 1         \\ 返回1  可以任何一个数      默认返回0为成功
        shift           \\ 把参数 向左边 移动一位 删除一位  同 shift 1
        sleep 1          \\ 延迟1秒

        ()         子shell
        (())       运算 数值比较
        $()        命令替换    同 ` `   
        $(())      运算

        {}         集合
        ${}        变量引用 替换 替代

        []         条件测试  不支持正则
        [[]]       条件测试  支持正则表达式  
        $[]        整数运算

        # sh -vx a.sh     以调试的方式执行 查询整个执行过程
        # bash -vx a.sh   以调试的方式执行 查询整个执行过程
        # sh -n a.sh      检测语法
        # bash -n a.sh    检测语法

    执行方式:
        1 bash aa.sh    \\ 在子shell中执行 另开一个shell执行
          ./aa.sh

        2 . aa.sh          \\ 在当前shell中执行  希望脚本中的东西影响到当前 要在当前shell中执行
          source aa.sh


3. 条件测试

    1 test 条件表达式
        if test -d /data/www/; then         \\ -d 检测是否为目录
        else
        fi

    2 [ 条件表达式 ]                           \\ [ 为 关键字 同test        ]括号只为配合左边的
        if [ -d /data/www/ ]; then
        else
        fi

    3 [[ 条件表达式 ]]


    文件测试 符号
        -e dir|file   是否存在文件或目录
        -d dir        是否存在目录
        -f file       是否存在文件
        -r file       当前用户对改文件是否有读权限
        -x file       当前用户对改文件是否有执行权限
        -W file       当前用户对改文件是否有写权限      
        -L file       是否为链接文件
        -b            如果 FILE 存在且是一个块特殊文件则为真。  
        -c            如果 FILE 存在且是一个字特殊文件则为真。  

        -z            字符串的长度为零则为真。 字符串为空即NULL时为真。 
        -n            字符串的长度不为零则为真

        # if echo $a | grep -q '[^0-9]' &> /dev/null ;then     \\ 检测是否为数字

        以 [  为例子 同 test 和 [[

            # [ -L /etc/hosts ]; echo $?      \\ 是链接文件 返回0 不是非0
            # [ ! -d /data ]; && mkdir /data   \\ 不是目录返回真 则创建 
            # [ -d /data ]; || mkdir /data      \\ 是目录 返回真 则不执行后面的 不是目录返回假则创建   

    数值比较
        -eq   等于       equal 相等
        -ne   不等于      not equal 不等
        -gt   大于        greater than 大于
        -ge   大于等于    greater than or equal 大于或等于
        -lt   小于        less than 小于
        -le   小于等于    less than or equal 小于或等于

        ((1<2))        小于
        ((1==2))       等于
        ((1>2))        大于
        ((1>=2))       大于等于
        ((1<=2))       小于等于
        ((1!=2))       不等于
        ((`id -u`>0))  一个命令的结果 是否大于0
        (($UID==0))    一个命令的结果 是否等于0   

    字符串比较       \\ 一般都使用 " " 

        [ "$USER" = "root" ]
        [ "$USER" == "root"]
        [ "$USER" != "root"]
        [ -z "$BBB"]              字符长度是为0
        [ -n "$BBB"]              字符长度不为0

        [ 1 -lt 2 -a 5 -gt 10 ]         -a 并且  在 [ ] 里面加
        [ 1 -lt 2 -o 5 -gt 10 ]         -o 或者  在 [ ] 里面加
        [[ 1 -lt 2 && 5 -gt 10 ]]       && 并且  在 [[ ]] 里面加  支持正则表达式
        [[ 1 -lt 2 || 5 -gt 10 ]]       || 或者  在 [[ ]] 里面加


4. 循环 判断 语句

    case语句
        case "$aa" in
        111)
            命令
            ;;
        222)
            命令
            ;;
        333)
            命令
            ;;
        "")
            ;;                        \\ 输入为空 执行命令为空
        *)
            无匹配后 执行的命令            \\ 最后一个 可以不加 ;;
        esac

    :和 true 一样 都是永远返回为真  可用 用在死循环的条件上 或 if判断之后 执行一个为真的命令上


    if 语句


        if [ 条件 ]; then
        elif [ 条件 ]; then
        else
        fi

        if test ; then             \\ test 后跟 测试语句 相当于[ ]
        else
        fi

        if [[ 条件 ]]; then           \\ 支持正则表达式
        else
        fi

        if 条件; then
        else
        fi

        if ((条件)); then             \\ 数值比较
        else
        fi


    for 循环
        shell 风格
            for i in `seq 1 20`
            do
            done

            for i               \\ 没有 in 意思是取 所有的参数
            for i in {1..20}
            for i in 1 2 3 4 5
            for i in `cat ip.txt`     \\ 把文件url.txt 赋给 i
            for i in `cat $1`          \\ 把第1个参数文件 作为变量 赋给 i 
            for i in `seq 2 254`
            for i in `seq $n`

        c风格

            for((i=1;i<=5;i++))
            for((i=1;i<=$n;i++))

        IFS=$'\n'            \\ 定义for使用回车分隔符 默认空格  两种方式
        IFS='
        '                      \\ 第二种方法

        `seq 2 254`   产生序列

        seq 10     打印 序列 1-10
        seq 2 10   打印 序列 从 2 - 10
        seq 1 2 10 打印 序列 步长为2   1 3 5 7 9

        seq -w 10     -w 等位补齐
            01
            02
            ... ...
            10

        seq $i    可以使用变量


        if id teooo &>/dev/null; then         \\ if条件 形式01
        id teooo &>/dev/null
        if test $? -eq 0; then                  \\ if条件 形式02
        if [ $? -eq 0 ]; then                    \\ if条件 形式03


    while 循环                        循环不固定 一般使用while
        while 条件              条件为真的时候 循环
        do
        done

        while read line
        do
        done < a.txt

        while :              :为真或 true
        do
        done



    unit 循环                可用于 检查 是否上线

        unit 条件             与while相反 条件为假的时候循环
        do
        done

        unit false
        do
        done

        unit [ 1 -eq 2 ]
        do
        done

        unit asdfasdf &>/dev/null        随便写一个不存在的命令即可
        do
        done


    select 循环                常用于 打印菜单
        select i in aa bb cc
        do
        done


    expect 解决交互   看实例
        # yum install expect



    函数定义
        mayann(){

        }

        function mayann{

        }

        mayann             调用
        mayann 10          调用的时候 传递参数 传给$1


5. 正则表达式 RE

    基本元字符
        ^       行首定位符               ^love
        $       行尾定位符               love$
        .       匹配单个字符              l..e
        *       匹配前面的字符0到多次     ab*love

        []      匹配指定范围内的一个字符    [lL]ove                    \\ 只匹配一个
        [-]     匹配指定范围内的一个字符    [a-z]ove  [a-z0-9]ove       \\ 只匹配一个
        [^]     非  不在指定组内的字符    [^a-z0-9] [^a-Z]             \\ a-Z 涵盖 大写和小写

        \       用来转移元字符         love\.
        \<      词首定位符               \<love                  \\ 在这里 不是 转义符 整体是一个元字符
        \>      词尾定位符               love\>

        \(..\)  标签 后向引用                 s#\(www.\)#\1baidu.com#g
        \1  \2  调用 后项引用

        x\{m\}  字符x重复出现m次           o\{5\}
        x\{m,\} 字符x重复出现m次以上     o\{5,\}
        x\{m,n\}字符x重复出现m到n次     o\{5,10\}

        基本衍生常用组合

            .*          匹配多个字符
            ^$          空行          只有一个 回车 为空行
            ^[ \t]*$    空格或tab制表符有0个或多个 的行
            ^#          注释行 以#号开始的行
            ^[ \t]*#    #前面有有0个或多个空格或者tab制表符的行 也是注释行


    扩展元字符

        +       匹配1个或多个前面的字符    [a-z]+ove
        ?       匹配0个或1个前面的字符    lo?ve
        |       或者 a|b 匹配a或者b       love|hate
        ()      字符组                 loveadble|re    love(able|rs)ov    (ov)+

        (..)\1  标签 后项引用             (love)able\1er  

        x{m}    字符x重复m次             o{5}     [a-z]{9} 连续出现相同的英文字母9个
        x{m,}   字符x重复至少m次           o{5,}
        x{m,n}  字符x重复m到n次           o{5,10}


    POSIX字符
        [:alnum:]   字母与数字字符                 [[:alnum:]]  使用的时候在加 [] 为 匹配指定范围内的一个字符
        [:alpha:]   字母字符
        [:blank:]   空格与制表符
        [:digit:]   数字字母
        [:lower:]   小写字母
        [:upper:]   大写字母
        [:punct:]   标点符号
        [:space:]   换行符 回车 空格等在内的所有空白

    正则表达式 练习

        获取ip
            # ifconfig | grep 'inet' | sed -n '1p' |awk '{print $2}'

        内存剩余
            # free -m | grep Mem | awk '{print $4}'
        硬盘剩余
            # df -h | grep '/$' | awk '{print $4}'

        生成30位的随机口令
            # cat /dev/urandom | tr -dc "[:alnum:]" | head -c 1

        判断主机版本号
            # grep -o "[0-9]\+" /etc/centos-release | head -n1

        查出分区空间使用率的最大百分比值
            # df | grep '/dev/sd' | grep -o "[0-9]*%" | grep -o "[0-9]\+" | sort -n | tail -1
            # df | grep '/' | awk '{print $1,$5}' | sort -nr -k2 | head -n1

        删除 7天以前的备份文件
            find /data -mtime +7 | xargs rm -rf
            find /data -mtime +7 -exec rm -rf {} \;


6. shell 脚本加密
    gzexe 对 shell 脚本的加密与解密
        # gzexe a.sh             \\ 加密 a.sh 脚本 并同时生成源文件a.sh~ 
        # bash -x a.sh            \\ 调试 执行  以下为解密
            skip=44                \\ 第44 行的时候 进行了 压缩
        # tail -n +44 a.sh > a.gz   \\ 生成 a.gz 文件
        # gunzip a.gz
        # diff a.sh~ a                \\ a 为解密的文件
    shc 对 shell 脚本加密       \\ 亦可先使用shc加密 在使用 gzexe加密
        # yum install shc       \\ epel源
        # shc -v -r -f a.sh      \\ 加密 脚本   不对源文件进行操作
            a.sh.x.c              \\ 此为C语言的 源文件
            a.sh.x                 \\ 此为加密后的脚本 可以直接执行
        # mv a.sh.x b.sh
        # sh b.sh


7. shell 执行方式:
    1 bash aa.sh    \\ 在子shell中执行 另开一个shell执行
      ./aa.sh

    2 . aa.sh          \\ 在当前shell中执行  希望脚本中的东西影响到当前 要在当前shell中执行
      source aa.sh
      


















Teo

21条评论

Jowbarm 发布于20:29 - 2021年6月7日

priligy canada

supergirl 发布于20:42 - 2021年2月10日

The following time I learn a weblog, I hope that it doesnt disappoint me as a lot as this one. I imply, I know it was my option to read, but I truly thought youd have one thing interesting to say. All I hear is a bunch of whining about one thing that you may repair in case you werent too busy looking for attention. Zea Jeromy Freda

mp3 发布于18:35 - 2021年2月9日

Situs Judi Tembak Ikan Online Terlengkap Indonesia. Corissa Cornie Vitalis

dizi 发布于16:09 - 2021年2月9日

Duis a ligula ut dui porta hendrerit. Nam non porta diam. Cras cursus sed dolor vel commodo. Curabitur dui arcu, vulputate nec augue accumsan, ultrices eleifend orci. Emogene Quincey Ginelle

dizi 发布于22:11 - 2021年2月8日

Mari Trommald is the leader of that section of the Ministry and hence the head of Norwegian Barnevern. Margareta Clerc Christoffer

movie download 发布于12:03 - 2021年2月2日

Hi, just wanted to tell you, I loved this blog post. Junia Skell Abbotsun

watch 发布于10:37 - 2021年2月2日

Simply wanna remark that you have a very nice site, I the style it really stands out. Kiersten Shawn Lenz

movie download 发布于08:01 - 2021年2月2日

A few things i have usually told persons is that when you are evaluating a good on-line electronics retail store, there are a few variables that you have to take into consideration. First and foremost, you would like to make sure to locate a reputable plus reliable retail store that has picked up great testimonials and classification from other consumers and business world advisors. This will make certain you are dealing with a well-known store to provide good support and assistance to its patrons. Thanks for sharing your thinking on this blog site. Lacey Lauren Douglas

access 发布于06:01 - 2021年2月2日

I am not sure where you are getting your info, but great topic. I needs to spend some time learning more or understanding more. Thanks for magnificent info I was looking for this info for my mission. Briana Donnell Woodall

filmkovasi 发布于22:19 - 2021年2月1日

Good post. I learn something new and challenging on websites I stumbleupon on a daily basis. Cookie Dennis Toogood

altyazili 发布于20:23 - 2021年2月1日

Hello there. I found your web site by means of Google while searching for a related topic, your website got here up. It appears to be good. I have bookmarked it in my google bookmarks to come back later. Ronalda Kerwinn Edythe

online 发布于17:48 - 2021年2月1日

Puiule, eu muncesc si platesc impozite la statul asta care da subventii la smecherasi care au trei masini la doua persoane. Cit despre gramatica: incepe propozitiile cu majuscula, elementar. Si adu argumente in discutii, nu injurii cretine. Bellanca Efrem Wisnicki

access 发布于14:55 - 2021年2月1日

Having read this I thought it was rather enlightening. I appreciate you spending some time and energy to put this informative article together. I once again find myself spending a lot of time both reading and leaving comments. But so what, it was still worthwhile! Lillis Callean Faus

access 发布于05:21 - 2021年2月1日

Hi there, I enjoy reading all of your article. I like to write a little comment to support you.| Ginelle Wyn Craddock

free porn 发布于22:35 - 2021年1月25日

Lovely just what I was looking for. Thanks to the author for taking his clock time on this one. Yvonne Boyce Maddalena

erotik izle 发布于01:36 - 2021年1月22日

Excellent article! We are linking to this particularly great article on our site. Keep up the good writing. Aurilia Tomas Barkley

izle 发布于08:46 - 2021年1月17日

As the admin of this web page is working, no question very soon it will be famous, due to its feature contents. Leanna Martie Ulrika

filmi izle 发布于10:34 - 2021年1月14日

Just came from google to your website have to say thanks. Daphna Evelyn Sheff

full hd izle 发布于23:04 - 2021年1月13日

What a material of un-ambiguity and preserveness of valuable knowledge on the topic of unpredicted feelings. Brigida Claudell Cutlerr

erotik 发布于13:01 - 2021年1月13日

Terrific website you have listed here, i do concur on some matters even though, but not all. Ronnie Garth Jankey

720p izle 发布于10:20 - 2020年12月10日

There is certainly a lot to find out about this issue. I really like all the points you made. Petrina Peterus Jillane

You must be logged in to post a comment