Shell脚本最佳实践

0. 编码、缩进、文件命名和权限设置等

使用utf-8编码;

统一使用tab缩进或空格缩进,不要混用;

文件名以.sh结尾,并且统一风格;

添加可执行权限:

chmod +x [bash_script.sh]

最后,在所有输出完毕后,添加一个空行。

1. 指定默认解释器

也就是不要省略脚本第一行的shebang,一般默认是bash:

#!/bin/bash

或者更为通用一些:

#!/usr/bin/env bash

本机可用的shell解释器,可以通过以下命令查看:

cat /etc/shells

2. Shell环境设置

设置命令回显:

set -x

shell默认设置不够友好,我们希望予以加强。

# 遇到未声明的变量则报错停止
set -u
# 遇到执行错误则停止
set -e

由于set -e对管道命令无效,管道命令其中一步失败则中止,需要使用:

set -o pipefail

我们将这三条合并,构成 bash strict mode,添加在bash脚本的开始位置:

set -euo pipefail

因为这里都是shell环境设置,所以也可以在执行脚本的时候来使用:

bash -euo pipefail [bash_sctipt.sh]

3. 条件判断。

使用 [[ ]] 并在每个变量和运算符以及和括号之间加入一个空格,例如:

if [[ $# > 1 ]] || [[ $# == 1 && $1 != 'PC' && $1 != 'server' ]]; then
echo 'Invalid commandline arguments, you should use `./run.sh` or `./run.sh PC` or `./run.sh server`'
exit 1
fi

其中,$#用于获取命令行参数个数,$N用于获取第N个命令行参数,参数$0指的是脚本文件名。

相比单方括号,双方括号的优势在于可以直接使用比较运算符>``<``==``!=等,而不是必须使用-gt``-lt``-eq``-ne;此外双方括号可以使用&&``||来表达与和或,而不用必须写-a``-o这种难以记忆的写法。

4. 使用文件之前判断是否存在,并进行异常处理。

# 判断普通文件存在
if [[ ! -f 'a.txt' ]]; then
touch 'a.txt'
fi
# 判断文件夹存在
if [[ ! -d 'src' ]]; then
echo 'src dir not found'
exit 1
fi

注意cp -r命令,在文件夹不存在时回创建文件夹并复制,而当文件夹存在时,会复制到子文件夹内。

5. 循环语句。

提倡使用for-in循环

# C风格
for (( i=0; i<10; i++)); do
// echo $i
done
# for-in
for i in $(seq 0 9); do
// echo $i
done

和 if 语句的 then 一样,for 语句的 do 也紧跟在语句后面,不单独占一行,这样显得比较紧凑。同样不要忘记加分号。

6. 总是使用main函数包裹执行体

main() {
func1()
func2()
}
main "$@"

与python类似,shell不需要函数入口,可以从第一条指令开始执行。但是为了可读性和方便调试,我们总是写一个命名为main的函数来作为全局入口。

7. 变量

1)环境变量的设置和取消:

# 设置环境变量
export SKIP_BFS=1
# 取消环境变量
unset SKIP_BFS

2)局部变量

shell变量默认全局作用域,这一点与JavaScript类似,函数内声明局部变量,应该添加local关键字。

3)使用变量时,总是用双引号把变量包起来,例如:

# 带空格的路径
cp -r "$src_dir" "$dest_dir"

路径有空格会导致很严重的bug,用"$var"这种写法,避免了这个问题。

8. 使用$()而不是反引号获取表达式的值

如for-in:

# 建议使用 $(seq lb ub) 而不是 `seq lb ub` 获取范围
for i in $(seq 0 10) do
echo $i
done

9. 使用 /dev/null 过滤输出信息

[expr] > /dev/null 2>&1

命令解释:重定向到空设备,并把标准错误输出stderr也重定向为stdout。

注意,2>&1应该总是放在命令的末尾。

10. case语句等

TBD

更多细节,参考Google Bash风格指南

Shell脚本最佳实践的更多相关文章

  1. MySQL安装脚本最佳实践

    MySQL安装脚本最佳实践 2018年9月19日 17:01 #!/bin/bash   export host_ip=192.168.7.206   echo '#1.取master主机ip的后三位 ...

  2. 浅谈自底向上的Shell脚本编程及效率优化

    作者:沐星晨 出处:http://blog.csdn.net/sosodream/article/details/6276758 浅谈自底向上的Shell脚本编程及效率优化 小论文,大家多批评指导:) ...

  3. 编写Shell脚本的最佳实践

    编写Shell脚本的最佳实践 http://kb.cnblogs.com/page/574767/ 需要记住的 代码有注释 #!/bin/bash # Written by steven # Name ...

  4. 编写Shell脚本的最佳实践,规范二

    需要养成的习惯如下: 代码有注释 #!/bin/bash # Written by steven # Name: mysqldump.sh # Version: v1.0 # Parameters : ...

  5. 编写 Shell 脚本的最佳实践

    转自:http://kb.cnblogs.com/page/574767/ 前言 由于工作需要,最近重新开始拾掇shell脚本.虽然绝大部分命令自己平时也经常使用,但是在写成脚本的时候总觉得写的很难看 ...

  6. 关于shell脚本编程的10个最佳实践

    每一个在UNIX/Linux上工作的程序员可能都擅长shell脚本编程.但大家解决问题的方式却不尽相同,这要取决于对专业知识的掌握程度.使 用命令的种类.看待问题的方式等等.对于那些处在shell脚本 ...

  7. shell脚本编程的10个最佳实践

    摘要:每一个在UNIX/Linux上工作的程序员可能都擅长shell脚本编程.对于那些处在shell脚本编程初级阶段的程序员来说,遵循一些恰当的做法可以帮助你更快.更好的学习这些编程技巧. 每一个在U ...

  8. 编写Shell脚本的最佳实践,规范一

    随着写的SHELL程序越来越多,发现自己每次写都有不同的习惯或者定义了不同的东西,变量名定义得不一样,整个程序缩进不统一,没有注释等问题,等我回过头看这些程序的时候发现很麻烦.所以写了个shell代码 ...

  9. Shell 脚本编程最佳实践

    前言 由于工作需要,最近重新开始拾掇shell脚本.虽然绝大部分命令自己平时也经常使用,但是在写成脚本的时候总觉得写的很难看.而且当我在看其他人写的脚本的时候,总觉得难以阅读.毕竟shell脚本这个东 ...

随机推荐

  1. laravel 资源控制器方法列表

    以 PostController 控制器的每个方法都有对应的请求方式.路由命名.URL.方法名和业务逻辑约定. HTTP请求方式 URL 控制器方法 路由命名 业务逻辑描述 GET post inde ...

  2. jmeter之断言复制过来的内容也会失败

    今天遇到个很纳闷的事儿,就决定记下来,在做jmeter断言的时候,明明我是从相应文本中拷贝出来的内容,但是依旧会断言失败,差了很多资料无果,最终请教了大佬才发现是特殊字符的问题 jmeter断言中不会 ...

  3. Seaborn基础1

    import seaborn as sns import numpy as np import matplotlib.pyplot as plt # # 折线图 def sinplot(flip = ...

  4. MySQL在同一个表上,删除查询出来的结果

    背景 有一个程序员员工表(code_user),包含用户id.姓名.掌握的语言. 表数据如下: +---------+-----------+----------+ | user_id | user_ ...

  5. PHP mysqli_set_charset() 函数

    设置默认客户端字符集: <?php 高佣联盟 www.cgewang.com // 假定数据库用户名:root,密码:123456,数据库:RUNOOB $con=mysqli_connect( ...

  6. 【NOI2001】方程的解数 题解(dfs+哈希)

    题目描述 已知一个方程 k1*x1^p1+k2*x2^p2……+kn*xn^pn=0. 求解的个数.其中1<=x<=150,1<=p<=6; 答案在int范围内 输入格式 第一 ...

  7. 入门python有什么好的书籍推荐?纯干货推荐,你值得一看 python基础,爬虫,数据分析

    Python入门书籍不用看太多,看一本就够.重要的是你要学习Python的哪个方向,或者说你对什么方向感兴趣,因为Python这门语言的应用领域比较广泛,比如说可以用来做数据分析.机器学习,也可以用来 ...

  8. Java基础—继承

    继承是面向对象的核心特征之一,是由已有类创建新类的机制.利用继承机制,可以先创建一个具有共性的一般类,然后根据该一般类创建具有特殊性的新类,新类继承一般类的属性和方法,并根据需要增加自己的新属性和方法 ...

  9. object detection 总结

    1.基础 自己对于YOLOV1,2,3都比较熟悉. RCNN也比较熟悉.这个是自己目前掌握的基础2.第一步 看一下2019年的井喷的anchor free的网络3.第二步 看一下以往,引用多的网路4. ...

  10. XCTF-WEB-新手练习区(5-8)笔记

    5:disabled_button X老师今天上课讲了前端知识,然后给了大家一个不能按的按钮,小宁惊奇地发现这个按钮按不下去,到底怎么才能按下去呢? 删除disable="" 字段 ...