# 学习shell脚本

  • shell脚本是利用shell的功能所写的一个【程序(program)】,这个程序是使用纯文本文件,将一些shell的语法与命令(含外部命令)写在里面,搭配正则表达式、管道命令余数据流重定向等功能,以达到我们所想要的处理目的。

  • shell脚本用在系统管理上面是很好的一项工具,但是用在处理大量数值运算上,就不够好了。因为shell脚本的速度较慢,且使用的CPU资源较多,会造成主机资源的分配不良。

  • 在shell脚本的文件中,命令是从上而下、从左而右地分析与执行。

  • shell脚本的执行,至少需要有r的权限;若需要直接执行命令,则需要拥有r与x的权限。

  • 良好的程序编写中,第一行要声明shell(#!/bin/bash),第二行起声明程序的用途、版本、作者等信息。

  • #!/bin/bash
    # 用户在家目录下建立bin文件且bin文件具有rx的权限,那么可以直接输入脚本即可执行。
    # 例如
    PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
    export PATH
    echo -e "Hello World! \a \n"
    exit 0
    
    # 此文件地址为:用户家目录/bin/hello.sh
    # 在用户目录下任意地址输入:hello.sh
    # 即可得到 Hello World!
    
  • 良好的脚本编写习惯,需要在脚本头记录好以下内容

    • 脚本的功能。
    • 脚本的版本信息。
    • 脚本的作者与联络方式。
    • 脚本的版权声明方式。
    • 脚本的History(历史记录)。
    • 脚本内较特殊的命令,使用【绝对路径】的方式来执行。
    • 脚本运行时需要的环境变量预先声明与设置。
  • 交互式脚本可用read命令完成,下面是具体实例。

  • #!/bin/bash
    PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
    export PATH
    read -p "please input your name: " name
    echo -e "\n Your name is: ${name}"
    
  • 要每次执行脚本都有不同结果的数据,可使用date命令利用日期完成,下面是具体实例。

  • #!/bin/bash
    # 例如日志文件,每天的日志文件名为log-XXXX-XX-XX.log(年月日),仅后缀年月日不同。
    PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
    export PATH
    # 让使用者输入文件名称,并取得fileuser变量
    echo -e "I will use 'touch' command to create 3 files."
    read -p "Please input your filename: " fileuser
    # 为了避免使用者随意按Enter,利用变量分析文件名是否设置
    filename=${fileuser:-"filename"}
    # 利用date命令来获取所需的文件名
    date1=$(date --date='2 days ago' +%Y%m%d) ## 前两天的日期
    date2=$(date --date='1 days ago' +%Y%m%d) ## 前一天的日期
    date3=$(date +%Y%m%d)
    file1=${filename}${date1}
    file2=${filename}${date2}
    file3=${filename}${date3}
    # 建立文件
    touch "${file1}"
    touch "${file2}"
    touch "${file3}"
    
  • 脚本若以source来执行,代表在父程序的bash内执行之意。

    # 直接执行方式来执行脚本,脚本内容会在子进程运行,而子进程的变量等不会传回父进程中。
    # 例如,执行脚本,此时脚本中设置的变量,在最外层的命令行中无法获取。
    sh showname.sh # 假设脚本中,设置了name变量
    echo ${name} # name变量不存在
    
    # 利用source就可以让脚本在父进程中运行了,不开辟子进程。
    source showname.sh # 假设脚本中,设置了name变量
    echo ${name} # yuhongjing
    
  • 若需要进行判断式,可使用test或中括号([ ])来处理。

    • test命令例子,测试/demo是否存在:test -e /dmtsai && echo "exist" || echo "Not exist"

    • 还可以使用中括号进行判断,例如${Home}变量是否为空:[ -z "{Home}" ]; echo $?

      • 中括号[]内的每个组件都需要空格分隔

      • 中括号内的变量,最好都以双引号包裹起来。

      • 中括号内的常量,最好都以单或双引号包裹起来。

      • # 假设『口』为空格,那么空格例子如下
        [ "$HOME" == "$MAIL" ]
        # 等于
        ["$HOME"=="$MAIL"]
        
  • 在脚本内,$0、$1、$2....$@是有特殊意义的。

  • # 除了read可以获取用户输入的参数之外。
    # 我们可以直接在命令行后面输入参数,然后通过$0、$1来获取参数
    # 例如
    /etc/init.d/network restart
    # $0为/etc/init.d/network  $1为restart
    
    # 其使用方式如下几类
    # 1. $#:代表后接的参数【个数】,具体指第N个参数。
    # 2. $@:代表【"$1", "$2", "$3", .....】所有参数的意思,每个变量独立的(用双引号包裹起来)。
    # 3. $*:代表【"$1c$2c$3c$4"】,其中c为分隔字符,默认为空格。
    
  • shift表示偏移参数。其功能如下:

  • # 命令如下
    # 其参数为:[a b c d e f]
    /etc/init.d/network a b c d e
    
    shift
    # 此时参数为:[b c d e f]
    
    shift 3
    # 此时参数为:[e f]
    
  • 条件判断式可使用if...then来判断,若是固定变量内容的情况下,可使用case $var in ... esac来处理。

  • # if...then 语法
    if [ 条件判断式一 ]; then
      语句一
    elif [ 条件判断式二 ]; then
      语句二
    else
      语句三
    fi
    
    # case $var in ... esac 语法
    case $变量名称 in
      "第一个变量内容")
         程序段
         ;;
      "第二个变量内容")
         程序段
         ;;
      *)
         程序段
         exit 1
         ;;
    esac
    
  • 循环主要分为不定循环(while与until)以及固定循环(for),配合do、done来完成所需任务。

  • # while do done 语法——不定循环
    while [ condition ] # 当条件成立,就开始循环
    do
    	程序段落
    done
    
    # until do done 语法——不定循环
    until [ condition ] # 当条件成立,就终止循环
    do
    	程序段落
    done
    
    # for...do...done 语法——固定循环
    for var in con1 con2 con3 ... # 对于数字可以 $ (seq 1 100)
    do
      程序段落
    done
    
    # for...do...done 语法——固定循环 第二种表达方式 数值处理
    for ((初始值; 限制值; 赋值运算))
    do
    	程序段
    done
    
  • 函数function,需要写在程序最前面,且函数也支持$0$1,表示函数名、参数1、参数2....

  • # 语法
    function fname() {
      程序段
    }
    
  • 我们可使用sh -x script.sh来进行程序的debug。

    • -n:不执行脚本,仅查询语法问题。
    • -v:在执行脚本前,先将脚本文件的内容输出在屏幕上。
    • -x:将使用到的脚本内容显示在屏幕上。
最近更新时间: 2020/9/6 11:30:38