shell编程规范:引用

Shell代码规范

做   者: 毕小朋
用   途: 规范Shell代码书写,方便查看与修改
博   客: http://blog.csdn.net/wirelessqa
参   考: 
http://www.ohlinux.com/archives/191/
http://kodango.com/shell-script-style

关于注释

 

程序头应加注版本与功能说明的注释。但程序第一行不能汉字。linux

程序体中应包含必要的注释,注释说明以下:ios

单行注释,能够放在代码行的尾部或代码行的上部;程序员

多行注释,用于注解复杂的功能说明,能够放在程序体中,也能够放在代码块的开始部分redis

代码修改时,对修改的内容要加必要版本注释及功能说明。shell

命名约定

1.本文档的命名约定是系统配置文件、脚本文件;

2.文件名、变量名、函数名不超过20个字符;

3.命名只能使用英文字母,数字和下划线,只有一个英文单词时使用全拼,有多个单词时,使用下划线分隔,长度较长时,能够取单词前3~4个字母。

4.文件名所有以小写命名,不能大小写混用(经过U盘交换文件时,大小写可能会丢失,即:大写文件名可能会所有变成小写文件名);

5.避免使用Linux的保留字如true、关键字如PWD等(见附表);

6.从配置文件导出配置时,要注意过滤空行和注释

函数约定

函数名称应该采用小写的形式,而且有一个很好的意义。函数名称应该容易让人理解,好比f1这个名称虽然容易输入可是对调试和其它人阅读代码形成了很大的困难,它说明不了任何东西。好的函数名称能够帮助说明代码,而不须要额外的注释。vim

一个或多或少有趣的是:若是你无心这样作,不要把函数名称命名为常见的命令名,新手每每比较容易将脚本或者函数名命名成test,这样就和UNIX的test命令冲突了。安全

  • 除非绝对必要,仅使用字母、数字和下划线做为函数名称。bash

  • 每一个函数控制在50-100行,超出行数建议分红两个函数less

  • 屡次反复调用的程序最好分红函数,能够简化程序,使程序条理更清楚编辑器

  • 全部函数定义应该在脚本主要代码执行以前,这样能够给人全局的印象,而且确保全部函数在使用以前它是已知的。

  • 你应该使用可移植性高的函数定义形式,即不带function关键字的形式。

代码开头约定

一、第一行通常为调用使用的语言

二、下面要有这个程序名,避免更改文件名为没法找到正确的文件

三、版本号

四、更改后的时间

五、做者相关信息

六、该程序的做用,及注意事项

七、版权与是否开放共享GNU说明

八、最后是各版本的更新简要说明

以下面的例子:

#!/bin/bash
# -------------------------------------------------------------------------------
# Filename:    check_mem.sh
# Revision:    1.1
# Date:        2009/02/10
# Author:      Ajian
# Email:       ajian521#gmail.com
# Website:     www.ohlinux.com
# Description: Plugin to monitor the memory of the system
# Notes:       This plugin uses the "" command
# -------------------------------------------------------------------------------
# Copyright:   2009 (c) Ajian
# License:     GPL
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty
# of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# you should have received a copy of the GNU General Public License
# along with this program (or with Nagios);
#
# Credits go to Ethan Galstad for coding Nagios
# If any changes are made to this script, please mail me a copy of the changes
# -------------------------------------------------------------------------------
#Version 1.0
#The first one , can monitor the system memory
#Version 1.1
#Modify the method of the script ,more fast

缩进

因为Shell没有很好的编辑环境,因此,建议用四个空格为基数进行缩进,好处在不一样的环境下TAB可能表明的空格数不一样,形成代码的错乱。用TAB他的优势是速度快方便,能够在编辑的时候也用TAB,但须要转换。

能够在更改编辑器,Windows的就不说了,主要是VIM

:set softtabstop=4

注意不要使用 :set tabstop=4 上面那个是同时把这一个TAB转换为四个空格,而这一条是定义TAB为四个空格,若是到其它编辑器上就会看到默认8个空格的状况,那就会不美观了。

另外将原有的TAB转换为空格,:retab

若是想让刚才的配置永久生效须要改动vim的配置文件 vim ~/.vimrc,更多详细的有用的配置见“VIM配置总结”

分隔长行

每行不要超过80字,若是超出,建议用“\”折行,有管道的命令行除外。

若是须要分隔过长的代码,你可使用下面的任意一种方法:

1) 使用与命令宽度相同的缩进

activate some_very_long_option \
         some_other_option

2) 使用2个空格缩进

activate some_very_long_option \
  some_other_option

从我的的角度来讲,除非有特别的须要,我更倾向于第一种形式,由于它突出“上下两行的内容是一块儿的”这一联系。

分离复合命令

译者注:其实这里的复合命令就是指块语句,例如for/while循环, if分支结构等等。

HEAD_KEYWORD parameters; BODY_BEGIN
  BODY_COMMANDS
BODY_END

我习惯于:

  • 将HEAD_KEYWORD和初始化命令或者参数放在第一行;
  • 将BODY_BEGIN一样放在第一行;
  • 复合命令中的BODY部分以2个空格缩进;
  • BODY_END部分独立一行放在最后;
1)if/then/elif/else分支语句

if ...; then
  ...
elif ...; then
  ...
else
  ...
fi
2)for循环

for f in /etc/*; do
  ...
done
3) while/until循环

while [[ $answer != [YyNn] ]]; do
  ...
done
4) case分支语句

case $input in
  hello)
    echo "You said hello"
  ;;
  bye)
    echo "You said bye"
    if foo; then
      bar
    fi
  ;;
  *)
    echo "You said something weird..."
  ;;
esac

几点注意的地方:

  • 若是不是100%须要,匹配部分左右的括号不须要写(译者注:例如写成hello)而不是(hello));
  • 匹配模式与分支的终止符号;;位于同一缩进级别
  • 分支内部的命令多缩进一层;
  • 尽管是可选的,这里仍是把最后一个分支的终止符号也写上了;

参数展开

除非你知道本身作的事情,请在参数展开的地方使用双引号

固然,也有一些地方并不须要使用双引号,例如:

  • [[ ]]测试表达式内部是不会展开的;
  • 在case $WORD in语法中WORD也不会展开的;
  • 在变量赋值var=$WORD的地方也是不会展开的 可是在这些地方使用引号并不会出错,若是你习惯于在每一个可能展开参数的地方使用引号,你写得代码会很安全。

若是你要传递一个参数做为一个单词列表,你能够不使用引号,例如:

list="one two three"

# you MUST NOT quote $list here
for word in $list; do
  ...
done

命令替换

正如文章the article about command substitution [Bash Hackers Wiki]中说起的,你应该使用$( .. )形式。

不过,若是可移植性是一个问题,你可能必须使用反引号的形式...

在任何状况,若是其它展开或者单词分隔并非你指望的,你应该将命令替换用双引号引发来。

环境变量

变量:所有是大写字母

变量引用:所有以变量名加双引号引用,如”$TERMTYPE”,或“${TERMTYPE}”,若是变量类型是数值型不引用,如:

若是须要从配置文件导出变量,则在变量前加一大写字母,以识别导出变量与自定义环境变量的区别,如:

变量值的引用尽可能以$开头,如$(ls inst_.sh),避免使用`ls inst_。sh`

循环控制变量能够命名为单个字母, 好比 i、j等。 也能够是更有意义的名称, 好比 UserIndex。

环境变量和全局变量 在脚本开头定义。

函数中使用较多的文件,以环境变量的形式在文件开头定义,仅函数中使用的变量在函数开头定义

配置变量

在这里,我将这一类变量——能够被用户更改的——叫作配置变量。

让这类变量容易找到,通常放在脚本的头部,给它们有意义的名称而且加上注释说明。正如上面说的,仅当你知道你为何这么作的时候,才用大写的变量名形式,不然小写形式更加安全。

语句

if 语句

if/then/else 语句中最可能被执行的部分应该放在 then 子句中, 不太可能被执行的部分应该放在 else 子句中。

若是可能, 尽可能不要使用一连串的 if 语句, 而应该以 case 语句替代。

不要使 if 语句嵌套超过5层以上, 尽可能以更清楚的代码替代。

case 语句

概要

case 语句中的单个子句应该以 case 常数的数字顺序或字母顺序排列。 子句中的执行语句应该尽可能保持简单, 通常不要超过4到5行代码。 若是执行语句过于复杂, 应该将它放置在独立的函数中。

case 语句的 *) 子句应该只在正常的默认状况或检测到错误的状况下使用。

格式

case 语句遵循一样的缩进和命名约定。

while 语句

使用 Exit 过程退出 while 循环是很差的; 若是可能, 应该只使用循环条件来结束循环。

while 循环的全部初始化代码应该紧贴在进入 while 循环以前, 不要被其余无关语句分隔开。

循环结束后的处理应该紧跟在循环以后。

for 语句

若是须要执行肯定次数的增量循环, 应该用 for 语句替代 while 语句。

脚本的基本结构

一个脚本的基本结构是这样的:

#!SHEBANG

CONFIGURATION_VARIABLES

FUNCTION_DEFINITIONS

MAIN_CODE
Shebang

若是可能,请不要忘记shebang。

请当心使用/bin/sh做为shebang,在Linux系统中,/bin/sh就是Bash这是一个错误的观点。

于我而言,shebang有两个目的:

  • 说明直接执行时以哪一个解释器来执行;
  • 明确该脚本应该以哪一个解释器来执行;

脚本行为和健壮性

当脚本检测到问题时尽早退出,以避免执行潜在的问题; 若是你须要用到的命令可能并无安装在系统上,在脚本执行的时候最好检查命令是否存在而且提醒用户缺乏什么; 采用有意义的脚本返回值,例如0代码成功,1代码错误或者失败;

其它

输出内容

if the script is interactive, if it works for you and if you think this is a nice feature, you can try to save the terminal content and restore it after execution;(译者注:不理解这一点是什么意思) 在屏幕中输出简单易理解的消息; 使用颜色或者特别的前缀区分错误和警告信息; 输出正常的内容到STDOUT,而输出错误、警告或者诊断的信息到STDERR; 在日志文件中输出全部详细的信息;

输入

不要盲目地假设任何事情,若是你但愿用户输入一个数字,请在脚本中主动检查它是否真得是一个数字,检查头部是否包含0,等等。咱们都应该知道这一点,用户仅仅是用户而不是程序员,他们会作他们想要的,而不是程序想要的。