Shell编程——开发规范

开发规范

1、Shell脚本基本规范

在Shell脚本里,第一行通常用于指定脚本解释器,该行内容为:

bash 复制代码
#! /bin/bash

或:

bash 复制代码
#! /bin/sh

而在Shell脚本的开头处解释器代码后,最好加上版本版权等信息,如下:

bash 复制代码
#Date:    16:29 2012-3-30
 #Author: Created by oldboy
 #Mail:       31333741@qq.com
 #Function:This scripts function is.....
 #Version: 1.1

说明:可在修改~/.vimrc配置文件时自动加上以上信息的功能。此项在Linux系统场景下不是必须的,属于优秀规范和习惯。

此外,Shell脚本中尽量不要用中文注释,应用英文注释,以防止本机或切换系统环境后出现中文乱码的困扰。如果非要加中文,请根据自身的客户端对系统进行字符集调整,如:export LANG="zh_CN.UTF-8",并在脚本中重新定义字符集,使其和系统一致。

Shell脚本命名应以".sh"为扩展名。例如:script-name.sh

Shell脚本应存放在固定的路径下,例如:/server/scripts。

以下则是代码书写技巧。

  • 成对的符号应尽量一次写出来,然后退格在符号里增加内容,以防止遗漏。这些成对的符号包括:

    bash 复制代码
    {}、[]、''、``、""
  • 中括号(​​)两端至少要有1个空格,因此,键入中括号时即可留出空格 ​,然后再退格键入中间的内容,并确保两端都至少有一个空格。即:先键入一对中括号,然后退一个格,输入两个空格,再退一个格,双中括号(​​\[​​]​)的写法也是如此。

  • 对于流程控制语句应一次将格式写完,再添加内容。

    比如,if语句的格式一次完成应为:

    bash 复制代码
    if 条件内容
      then
        内容
    fi

    for循环语句的格式一次完成应为:

    bash 复制代码
    for
    do
        内容
    done

    提示:while和until、case等语句也是一样。

  • 通过缩进让代码更易读,比如:

    bash 复制代码
    if条件内容
      then
        内容
    fi
  • 字符串赋值给变量时应加双引号,并且等号前后不能有空格。例如:

    bash 复制代码
    OLDBOY_FILE="test.txt"
  • 脚本中的单引号、双引号及反引号,必须为英文状态下的符号,其实所有的Linux标准字符及符号都应该是英文状态下的符号,这一点需要特别注意。

2、Shell脚本变量命名及引用变量规范

2.1、全局变量定义

全局变量也称环境变量,它的定义应全部大写,如APACHE_ERR或APACHEERR,名字对应的语义要尽量清晰,能够正确表达变量内容的含义,对于过长的英文单词可用前几个字符代替。多个单词间可用"_"号连接,全局变量的定义一般放在系统的全局路径中,并且最好采用export来定义,全局变量一般可以在任意子Shell中直接使用(特殊情况除外,例如:定时任务执行Shell时就最好在Shell里重新定义这些全局变量,否则可能会出现问题)​。

范例:全局变量的定义示例。

bash 复制代码
[root@oldboy scripts]# tail -1 /etc/profile
export APACHEERR="hello"
[root@oldboy scripts]# source /etc/profile
[root@oldboy scripts]# echo $APACHEERR
hello

2.2、局部变量定义

局部变量也称为普通变量,在常规脚本中,普通变量的命名也要尽可能统一,可以使用驼峰语法,即第二个单词的首字母大写,如oldboyTraining,或者每个单词首字母大写,如CheckUrl,当然也有网友喜欢采用全部大写或全部小写的方式,例如:CHECK、check,选一种适合你的即可,或者跟着本书的规范走。

Shell函数中的变量可以使用local方式进行定义,使之只在本函数作用域内有效,防止函数中的变量名称与外部程序中的变量相同,从而造成程序异常。下面是在函数中定义变量的例子。

范例:实现函数内的变量定义。

bash 复制代码
function TestFunc(){
    local i
    for((i=0; i<n; i++))
    do
        echo 'do something'
    done
}

2.3、变量的引用规范

在引用变量时,若变量前后都有字符,则需要使用 A P A C H E E R R (加大括号的方式)引用变量,以防止产生歧义;当变量内容为字符串时,需要使用 " {APACHE_ERR}(加大括号的方式)引用变量,以防止产生歧义;当变量内容为字符串时,需要使用" APACHEERR(加大括号的方式)引用变量,以防止产生歧义;当变量内容为字符串时,需要使用"{APACHE_ERR}"(外面加双引号的方式)引用变量;当变量内容为整数时,则最好直接使用$APACHE_ERR来引用变量。全局变量、局部变量、函数变量、数组变量等都是如此。

说明:对于需要环境变量的Java程序脚本等,在写脚本之前,最好通过export重新声明环境变量,以免在定时任务等场合的使用中出现问题。

3、Shell函数的命名及函数定义规范

Shell函数的命名可采用单词首字母大写的形式,如CreateFile(),并且语义要清晰,比如,使用CreateFile()代替CFile(),也可以使用小写形式,如createfile()。

可以加前后缀,如后缀为Max则为最大值,为Min则表示最小值,前缀Is为判断型函数,Get为取值函数,Do则为处理函数,这也有益于对函数功能的理解,使函数名更直观、更清晰。

范例:对操作系统函数库脚本的函数名进行定义。

bash 复制代码
#/etc/init.d/functions
# Check whether file $1 is a backup or rpm-generated file and should be ignored
is_ignored_file() {  #<==这里系统的函数名并没有大写,除了大小写之外,还是比较规范的。
    case "$1" in
        *~ | *.bak | *.orig | *.rpmnew | *.rpmorig | *.rpmsave)
            return 0
            ;;
    esac
    return 1
}

如果需要区别一些常规的字符串,可在函数名前加上function关键字,例如:

bash 复制代码
function CreateFile(){
}

显示函数返回值时,可在函数的结尾内容中包含return语句,并跟上返回值。即使是不关心返回值的函数,也可能在后续调用时无意识地去判断它的返回值并进行一系列动作,使用return语句不会带来多少负担,但确实能让函数的逻辑变得更加清晰和严谨。

范例:为操作系统函数库脚本函数定义return返回值。

bash 复制代码
# Log a warning
warning() {
    local rc=$?
    #if [ -z "${IN_INITLOG:-}" ]; then
    #    initlog $INITLOG_ARGS -n $0 -s "$1" -e 1
    #fi
    [ "$BOOTUP" ! = "verbose" -a -z "${LSB:-}" ] && echo_warning
    return $rc
}

4、Shell脚本(模块)高级命名规范

  • 1)常规Shell脚本使用统一的后缀:.sh,例如oldboy.sh
  • 2)模块的启动和停止脚本统一命名为start_模块名.sh和stop_模块名.sh。
  • 3)监控脚本通常以*_mon.sh为后缀。
  • 4)控制脚本一般以*_ctl.sh为后缀。

5、Shell脚本的代码风格

5.1、代码框架

易变的信息(如报警的收件人、机器名、端口、用户名密码、URL等)最好都定义为变量或使用特殊位置的参数,这会使开发的脚本更具通用性。

把Shell的通用变量以配置文件的形式单独存放,以"功能.cfg"来命名,例如nginx.conf,并放入conf目录下;引用时通过在脚本开头使用source conf/nginx.conf的形式来加载。

将程序的功能分段、分模块采用函数等来实现,并存放到单独的函数文件里,如果是通用的公共函数可以存放于/etc/init.d/functions下,调用时采用source文件全路径即可。

把脚本中的功能和配置明确分开,主脚本只用于实现程序主干,加载配置及加载函数等功能实现应尽量封装在子函数中。

规范代码树如下。

bash 复制代码
[root@oldboy scripts]# tree
.
|-- bin
|    `-- ipsecctl
|-- conf
|    `-- ipsec.cfg
`-- func
    `-- functions
3 directories, 3 files

5.2、缩进规范

在使用条件语句时,每进行一层循环或是循环内部的操作时,就使用一个缩进,缩进一般用TAB键或加空格,本书推荐采用4个空格缩进。

范例:写出脚本缩进规范。

bash 复制代码
if [ -d oldboy_dir ]
  then
    cd oldboy_dir
    if [ -f oldboy_file ]
      then
        echo "DoSth"
    fi
    cd ..
fi

范例:给出系统脚本函数的缩进示例。

bash 复制代码
# Confirm whether we really want to run this service
 confirm() {
   [ -x /usr/bin/rhgb-client ] && /usr/bin/rhgb-client --details=yes
   while : ; do
       echo -n $"Start service $1 (Y)es/(N)o/(C)ontinue? [Y] "
       read answer
       if strstr $"yY" "$answer" || [ "$answer" = "" ] ; then
           return 0
       elif strstr $"cC" "$answer" ; then
           rm -f /var/run/confirm
           [ -x /usr/bin/rhgb-client ] && /usr/bin/rhgb-client --details=no
           return 2
       elif strstr $"nN" "$answer" ; then
           return 1
       fi
   done
 }

提示:可调整vim实现自动缩进,建议缩进4个空格。

6、Shell脚本的变量及文件检查规范

脚本中要检查配置项是否为空、是否可执行等,尤其是对于一些重要的、会影响下面脚本正常运行的配置项,必须要进行是否为空等的检查,避免配置文件中出现遗漏等问题。

范例:针对字符串变量进行判断。

bash 复制代码
if [ -n "${FILE_PATH}" ]
  then
    echo "Do something"
fi

范例:给出HTTP脚本变量的定义方式。

bash 复制代码
httpd=${HTTPD-/usr/sbin/httpd}
 prog=httpd
 pidfile=${PIDFILE-/var/run/httpd.pid}
 lockfile=${LOCKFILE-/var/lock/subsys/httpd}
相关推荐
Shadow(⊙o⊙)1 小时前
epoll三大接口到内核+正确认识应用层与内核的联系(6000字)
linux·服务器·网络
皓月盈江1 小时前
Linux系统使用VSCode搭建GO开发环境
linux·vscode·ubuntu·golang·debian
ShiXZ2131 小时前
SSH 客户端常用指令与配置速查手册
运维·ssh
pt10431 小时前
Cisco Splunk for AI Operations:AIOps机器学习
运维·网络·人工智能·机器学习
CHHH_HHH1 小时前
【Linux系统篇】进程间通信揭秘:从管道到共享内存
linux·服务器·c语言·开发语言·后端·ubuntu
.冰块.1 小时前
华为云计算服务学习笔记|ECS + 镜像 IMS + 弹性伸缩 AS 完整踩坑实录
linux·华为云·ims·as·ecs·弹性云服务器·计算类云服务
putItInYourHand1 小时前
Docker Compose 部署 Mosquitto MQTT Broker 完整实战指南
运维·docker·容器
Larru-Sun2 小时前
Nginx + Vue Router 基础:SPA History 部署、反向代理与请求分流
运维·vue.js·nginx
考虑考虑10 小时前
cmd局部设置java变量
运维·后端·自动化运维