美文网首页Linuxshell基础Linux学习之路
shell基础(六)脚本规范及Linux信号知识

shell基础(六)脚本规范及Linux信号知识

作者: 一名IT小学生 | 来源:发表于2018-11-21 14:16 被阅读3次

    一、shell脚本规范事项

    1.脚本第一行加脚本解释器:#!/bin/bash 或 #!/bin/sh
    2.若脚本中有中文,则需要在系统中加"export LANG="zh_CN.UTF-8"",并且在脚本中重新定义字符集,使其和系统中的字符集一致
    3.shell脚本以.sh结尾,并且放到制定位置:例如"/server/scripts"
    4.所以成对的符号,和循环语句的关键词,要一次性写完,防止遗漏
    5.全局变量全部大写,局部变量可以全部小写或者使用驼峰语法进行书写,例如:"myBook"
    6.函数命名可采用首字母大写,并且语义要清晰,例如:"createFile"
    7.尽量在函数最后加上返回值,有些不会用到返回值的也一样

    二、高级命名规范:

    1.常规shell用.sh结尾:例如:shell.sh
    2.模块的启动和停止脚本统一命名为start_模块名.sh和stop_模块名.sh
    3.监控脚本一般以_mon.sh结尾
    4.控制脚本一般以
    _ctl.sh为后缀

    三、shell脚本的变量和文件检查规范

    在脚本中要检查配置项是否为空、是否可执行等,尤其是对于一些重要的、会影响下面脚本正常运行的配置项,需要进行是否为空的检查。

    字符子串的特殊用法:
    ${变量:-word}:若变量值为空或未赋值,则返回word字符串并代替变量的值
        用于:如果变量未定义,则返回备用值,防止因为变量未定义或为空而导致异常
    ${变量:=word}:若变量值为空或未赋值,则设置这个变量的值为word,并且返回其值,位置变量和特殊变量不适用
        用于:基本上同第一个,只是在第一个的基础上又额外给了“变量赋值”
    ${变量:?word}:若变量值为空或未赋值,则word字符串将被作为标准错误输出,否则输出变量的值
        用于:捕捉由于变量未定义而导致的错误,并退出程序
    ${变量:+word}:若变量值为空或未赋值,则什么也不做,否则word字符串将代替变量的值
    
    注:
      若将":"去掉,则将定义中的"若变量值为空或未赋值"改为"未赋值",用于测试变量是否赋值
    
    例一:
    [centos@mycentos ~]$ echo $test #变量为空
    [centos@mycentos ~]$ res=${test:-UNSET}
    [centos@mycentos ~]$ echo $res        #打印res变量,返回UNSET,因为test没有赋值 
    UNSET
    [centos@mycentos ~]$ echo $test  #test仍然没有值
    
    对于${test:-UNSET},当test变量没有值时,就返回变量结尾设置的UNSET字符串,有值时就返回test的值。
    
    例子二:
    [centos@mycentos ~]$ unset test  #test为空
    [centos@mycentos ~]$ unset res   #res为空
    [centos@mycentos ~]$ echo $res
    
    [centos@mycentos ~]$ res=${test:=UNSET}  #对res变量进行赋值
    [centos@mycentos ~]$ echo $res      #因为test为空,所以打印UNSET
    UNSET
    [centos@mycentos ~]$ echo $test     #此处test被赋值,原来是没有定义的,与例一有所不同
    UNSET
    结论:
    ${变量:=word}
    当变量(res)和变量(test)值没有定义时,会给变量(res)赋值":="后面的内容,同时会把":="后面的内容赋值给变量test,此方法可以解决变量没有定义的问题,确保没有定义的变量始终有值
    
    例子三:
    [centos@mycentos ~]$ echo ${key:?not defined}
    -bash: key: not defined
    [centos@mycentos ~]$ key=1
    [centos@mycentos ~]$ echo ${key:?not defined}
    1
    [centos@mycentos ~]$ unset key
    [centos@mycentos ~]$ echo ${key:?not defined}
    -bash: key: not defined
    
    ${变量:?word}此例可以用于设置变量未定义二报错的具体内容,如"not defined"
    
    
    例子四:
    [centos@mycentos ~]$ oldboy=${oldgirl:+word}
    [centos@mycentos ~]$ echo $oldboy  #oldgril没有赋值,所以打印变量oldboy为空
    
    [centos@mycentos ~]$ oldgirl=19 
    [centos@mycentos ~]$ oldboy=${oldgirl:+word} #此处需要重新定义
    [centos@mycentos ~]$ echo $oldboy               #oldgirl有值后,打印出来":+"后面的内容
    word
    此例可用于测试变量(oldboy位置)是否存在,若oldboy的值为word,则证明oldgirl变量有值存在
    

    在系统脚本中看防止变量为空的应用:

    在apache1服务启动脚本/etc/init.d/httpd中
      1 #!/bin/bash
      2 #
      3 # httpd        Startup script for the Apache HTTP Server
      4 #
      5 # chkconfig: - 85 15
      6 # description: The Apache HTTP Server is an efficient and extensible  \
      7 #              server implementing the current HTTP standards.
      8 # processname: httpd
      9 # config: /etc/httpd/conf/httpd.conf
     10 # config: /etc/sysconfig/httpd
     11 # pidfile: /var/run/httpd/httpd.pid
     12 #
     13 ### BEGIN INIT INFO
     14 # Provides: httpd
     15 # Required-Start: $local_fs $remote_fs $network $named
     16 # Required-Stop: $local_fs $remote_fs $network
     17 # Should-Start: distcache
     18 # Short-Description: start and stop Apache HTTP Server
     19 # Description: The Apache HTTP Server is an extensible server 
     20 #  implementing the current HTTP standards.
     21 ### END INIT INFO
     22 
     23 # Source function library.
     24 . /etc/rc.d/init.d/functions
     25 
     26 if [ -f /etc/sysconfig/httpd ]; then
     27         . /etc/sysconfig/httpd
     28 fi
     29 
     30 # Start httpd in the C locale by default.
     31 HTTPD_LANG=${HTTPD_LANG-"C"}  #若HTTPD_LANG变量没有赋值(没有定义),则将HTTPD_LANG值变,此处为":"省略的情况
        
     33 # This will prevent initlog from swallowing up a pass-phrase prompt if
     34 # mod_ssl needs a pass-phrase from the user.
     35 INITLOG_ARGS=""
     36 
     37 # Set HTTPD=/usr/sbin/httpd.worker in /etc/sysconfig/httpd to use a server
     38 # with the thread-based "worker" MPM; BE WARNED that some modules may not
     39 # work correctly with a thread-based MPM; notably PHP will refuse to start.
     40 
     41 # Path to the apachectl script, server binary, and short-form for messages.
     42 apachectl=/usr/sbin/apachectl
     43 httpd=${HTTPD-/usr/sbin/httpd} #若HTTPD没有赋值(没有定义):则将httpd赋值为"/usr/sbin/httpd"
     44 prog=httpd
    
    注:
      1.在企业中,针对目录路径情况等的处理就可以采用上述变量不存在的方式,防止因目录不存在而导致的异常
    

    实战一:删除7天前的过期数据备份

    [centos@mycentos shell]$ cat 1.sh 
    #!/bin/bash
    sudo find ${path-/tmp} -name "*.tar.gz" -type f -mtime +7 |xargs rm -f
    
    1.如果忘记了定义path路径变量,又不希望其为空,就可以定义/tmp代替path空值返回值.
    2.若忘记了定义path路径变量,还没有做特殊变量定义,此条命令会出现异常
    

    补充:http脚本变量的定义方式:

    httpd=${HTTPD-/usr/sbin/httpd}
    prog=httpd
    pidfile=${PIDFILE-/var/run/httpd/httpd.pid}
    lockfile=${LOCKFILE-/var/lock/subsys/httpd}
    
    此定义方式可以防止出现空值
    

    四、shell调试技巧

    1、使用dos2unix命令处理在Windows下开发的脚本
    #!/bin/bash
    i=1
    sum=0
    while((i<=100))
    do
        let i++
        ((sum+=i))
    done
    使用dos2unix进行格式化,会去除一些Windows的一些格式(例如空格)错误
    ---------------------------------------------------------------------------------------
    2.bash命令调试
    
    sh [-nvx] scripts.sh
    -n :不会执行脚本,仅仅检查语法是否有问题,并且给出错误提示
    -v :在执行脚本时,先将脚本的内容输出到屏幕上,然后执行脚本,如果有错误,也会给出错误提示
    -x :将执行的脚本内容输出显示到屏幕上。
    
    printf "totalsum is $sum"
    export PS4='+${LINENO}' #此命令可以使追踪命令显示每行的行号
    
    

    五、vim编辑器的配置

    1.编辑vim相关文件

    .viminfo     用户使用vim的操作历史记录
    .vimrc       当前用户的配置文件
    /etc/vimrc   系统全局vim的配置文件
    /usr/share/vim/vim74/colors 配色魔板文件存放路径
    
    注:
          1.当配置/etc/vimrc文件时,所有用户的vim均会受影响
          2.当编辑个人用户家目录下的隐藏文件.vimrc,则只有此用户的vim编辑受影响。
    

    以下是个人的vim的配置,直接复制到家用户目录下的.vimrc即可

    set nocompatible
    set history=100
    filetype on
    filetype plugin on
    filetype indent on
    set autoread
    set mouse=a
    syntax enable
    set nofen
    set fdl=0
    set expandtab
    set tabstop=4
    set shiftwidth=4
    set softtabstop=4
    set smarttab
    set ai
    set si
    set wrap
    set sw=4
    set wildmenu
    set nu
    set cmdheight=1
    set lz
    set backspace=eol,start,indent
    set whichwrap+=<,>,h,l
    set magic
    set noerrorbells
    set novisualbell
    set showmatch
    set mat=2
    set hlsearch
    set ignorecase
    set encoding=utf-8
    set fileencodings=utf-8
    set termencoding=utf-8
    set smartindent
    set cin
    set showmatch
    set guioptions-=T
    set guioptions-=m
    set vb t_vb=
    set laststatus=2
    set pastetoggle=<F9>
    set background=dark
    highlight Search ctermbg=black ctermfg=white guifg=white guibg=black
    
    autocmd BufNewFile *.py,*.cc,*.sh,*.java exec ":call SetTitle()"
    
    func SetTitle()
        if expand("%:e") == 'sh'
            call setline(1, "#!/bin/bash")
            call setline(2, "#Auther:itboy")
            call setline(3, "#Time:".strftime("%F %T"))
            call setline(4, "#Name:".expand("%"))
            call setline(5, "#Version:V1.0")
            call setline(6, "#Description:this is a test script.")
        endif
    endfunc
    

    2.vim的高级命令

    ngg :调到n行
    0 :到行开头
    $ :到行结尾
    L :移动到当前窗口最后一行 == G ,然后点"o",开始下一行编辑
    H :移动到当前窗口最前面一行 ==gg 
    
    命令行模式下:"ctrl+:"后
    /old  :从上向下找"old"
    %s/A/B/g :A全部替换为B "/"可以换成"#或@"
    n1,n2 w filename : 将n1到n2行的内容保存到filename文件里
    n1,n2 co n3 : 将n1到n2行的内容复制到n3的位置下
    n1,n2 m n3 : 将n1到n2行的内容剪切到到n3的位置下
    ! “命令”  :暂且退出vi,执行“命令”
    vs filename  : 竖直分屏显示filename ,q!退出分屏
    
    
    1.多行注释:
      1). 首先按esc进入命令行模式下,按下Ctrl + v,进入列(也叫区块)模式;
      2). 在行首使用上下键选择需要注释的多行;
      3). 按下键盘(大写)“I”键,进入插入模式;
      4). 然后输入注释符(“//”、“#”等);
      5). 最后按下“Esc”键。 注:在按下esc键后,会稍等一会才会出现注释,不要着急~~时间很短的
     
    2.删除多行注释:
      1). 首先按esc进入命令行模式下,按下Ctrl + v, 进入列模式;
      2). 选定要取消注释的多行;
      3). 按下“x”或者“d”. 注意:如果是“//”注释,那需要执行两次该操作,如果是“#”注释,一次即可
    
    3.多行删除
      1).首先在命令模式下,输入“:set nu”显示行号;
      2).通过行号确定你要删除的行; 
      3).命令输入“:32,65d”,回车键,32-65行就被删除了,很快捷吧
          如果无意中删除错了,可以使用‘u’键恢复(命令模式下)
          也可以用"del"在可视化中全删选择的内容
    
    4.多行缩进
      1). 首先按esc进入命令行模式下,按下Ctrl + v,进入列(也叫区块)模式;
      2). 在行首使用上下键选择需要缩进的多行;
      3). 最后按"="即可
    

    六、Linux信号相关知识

    一、现象描述:
    1.当运行shell脚本时,如果按下Ctrl+c 或Ctrl+x(x为其他字符),程序会终止运行。
    2.当不希望shell在运行时被终止,则可以使用屏蔽信号手段,让程序忽略用户输入的信号指令,从而继续运行shell程序。
    二、信号含义:
    信号是由一个整数构成的异步消息,它可以由某个进程发给其他进程,也可以在用户按下特定按键发生某种异常事件时,由系统发给某个进程。

    1.Linux重要信号
    HUP(1)  挂起,通常因终端掉线或用户退出而引发
    INT(2)  中断,通常因为按ctrl + c组合键而引发
    QUIT(3) 退出,通常因为按ctrl + \ 组合键而引发
    ABRT(6)  中止 , 通常因为某些严重的执行错误而引发
    ALRM(14) 报警 , 通常用来处理超时
    TERM(15) 终止 ,通常在系统关机时发送
    TSTP(20) 停止进程的运行,但该信号可以被处理和忽略,通常是Ctrl + z键而引发
    
    注:
        shell脚本中可以用数字来代表信号,也可以用信号的名字代表信号
    
    2.trap命令
    trap命令:
        1.用于在接受到信号后将要采取的行动
        2.常用于在脚本程序被中断时完成清理工作,或者屏蔽用户非法使用的某些信号
    注:
        使用信号名时需要省略前缀"SIG"
    用法:
        trap command signal
        signal是接受到的信号 , command是接收到信号后应该采取的行动
        trap "命令;命令" 信号名      或者 trap "命令;命令" 信号编号
    

    例一:

    处理单个信号:
    [centos@mycentos ~]$ trap "" 2  #若执行动作为空,则可以用来屏蔽与数字对应的Ctrl+c信号
    [centos@mycentos ~]$ trap ":" 2 #此处恢复Ctrl + c 的信号 
    [centos@mycentos ~]$ ^C    #已恢复
    

    例二:

    同时处理多个信号:
    [centos@mycentos ~]$ trap "" 1 2 3 20 #<==执行这些数字信号,什么都不做,即屏蔽这些信号
    [centos@mycentos ~]$ trap ":" 1 2 3 20 #<==执行这些信号,恢复对应的功能
    [centos@mycentos ~]$ ^C
    [centos@mycentos ~]$ trap "" HUP INT QUIT TSTP #<==执行这些名称信号,什么都不做,即屏蔽这些信号
    [centos@mycentos ~]$ trap ":" HUP INT QUIT TSTP #<==执行这些名称信号,恢复对应的功能
    [centos@mycentos ~]$ ^C
    [centos@mycentos ~]$ trap "" `echo {1..64}` #<==屏蔽1-64所有的数字信号
    

    实战二:
    开发脚本实现触发信号后清理文件功能(信号触发后就会执行将新建的文件删除命令)

    #!/bin/bash
    #Auther:itboy
    #Time:2018-11-20 10:09:42
    #Name:3.sh
    #Version:V1.0
    #Description:this is a test script.
    
    #<==捕获ctrl+c 键后即执行find删除命令,后退出脚本
    trap "find /tmp -type f -name "old_*" | xargs rm -f && exit" INT
    
    while true
    do
        touch /tmp/old_$(date +%F-%T) #<==在/tmp创建文件
        sleep 5     #<==休息3秒
        ls -la /tmp/old*    #<==查看文件创建情况
    done
    

    实战三:
    开发脚本,练习QUIT、TSTP、INT

    #!/bin/sh
    #捕获ctrl+c信号时,执行echo命令
    trap 'echo "you are typing ctrl-c ,sorry,script will not terminate"' INT
    #捕获Ctrl+\信号,执行echo
    trap 'echo "you are typing ctrl-\ ,sorry,script will not terminate"' QUIT
    #捕获ctrl+z信号,就会执行echo命令 (实测此处没有执行echo命令)
    trap 'echo "you are typing ctrl-z ,sorry,script will not terminate"' TSTP
    while true
    do
        echo "now , test signal $(date)"
        sleep 5
    done
    

    效果如图:

    [root@mycentos ~]# sh 2.sh 
    now , test signal Tue Nov 20 11:02:06 CST 2018
    ^Cyou are typing ctrl-c ,sorry,script will not terminate  #按下ctrl+c执行
    now , test signal Tue Nov 20 11:02:11 CST 2018
    now , test signal Tue Nov 20 11:02:16 CST 2018
    now , test signal Tue Nov 20 11:02:21 CST 2018
    ^\Quit (core dumped)
    you are typing ctrl-\ ,sorry,script will not terminate #按下ctrl+\执行
    now , test signal Tue Nov 20 11:02:25 CST 2018
    now , test signal Tue Nov 20 11:02:30 CST 2018
    ^Z^Z                            #按下ctrl +z 键没有打印提示,但是程序停止运行了
    

    相关文章

      网友评论

        本文标题:shell基础(六)脚本规范及Linux信号知识

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