bash脚本最佳实践

二维码
| Mar 26, 2019 | 译文 - 原文

我最近在tweet上发布了几年来我学到的一些最佳实践,并且反馈不错。我决定把它们全部整理到一篇博客文章中,如下:

1. 脚本参数选项使用较长命名( logger --priority 对比 logger -p)。如果您使用的是cli,缩写对于效率是有意义的。但是,当您编写可复用的脚本时,使用完整的参数选项可读性会好很多,并且也可以避免将来该脚本在被你或者你的用户使用时由于参数选项简写查手册。

2. 在脚本里可以使用 set -o errexit(也称 set -e )使脚本里命令在执行失败时使脚本退出。

3. 在允许失败的命令中添加|| true

4. 使用 set -o nounset(也称 set -u ),如果设置了此变量,当脚本中使用了未声明的变量,脚本会退出。

5. 使用 set -o xtrace(也称 set -x )可以追踪脚本执行的内容。在Debug调试脚本时非常有用。

6. 在脚本中使用set -o pipefail 捕获 mysqldump 执行失败错误,例如:mysqldump | gzip。该语句在执行由管道组成的多条命令时,会返回最后一条命令的错误非0值。

7. #!/usr/bin/env bash 声明比#!/bin/bash 兼容性更好。

8. 避免使用 #!/usr/bin/env bash -e (相对的是 set -e ),因为如果运行你的脚本是 bash ./script.sh 方式,那么脚本运行出错退出的设置将会不起作用。

9. 使用花括号({})包围变量。否则,bash将尝试访问 /srv/$environment_app 中的 $environment_app 变量,而您实际上可能希望是:/srv/${environment}_app

10. 判断变量是否相等,使用一个等号而不是两个:if [ "${NAME}" = "Kevin" ]

11. 把变量放在双引号 "" 中,如:if [ "${NAME}" = "Kevin" ],如果 ${NAME} 变量声明,那么BASH会报语法错误(参见:nounset )。

12. 使用 :- 来测试是否一个变量是否被声明过。如:if [ "${NAME:-}" = "Kevin" ] 如果 ${NAME} 变量未声明则会变为空字符,你也可以设置为其他默认值,例如:如果不存在,默认值设为:nonameif [ "${NAME:-noname}" = "Kevin" ]

13. 在脚本文件头部设置一些常用的魔术变量,比如当前的文件路径、文件名、文件所在目录等,这将为之后编写脚本提供一些便利。

最后汇总如下:

#!/usr/bin/env bash
# Bash3 Boilerplate. Copyright (c) 2014, kvz.io

set -o errexit
set -o pipefail
set -o nounset
# set -o xtrace

# Set magic variables for current file & dir
__dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
__file="${__dir}/$(basename "${BASH_SOURCE[0]}")"
__base="$(basename ${__file} .sh)"
__root="$(cd "$(dirname "${__dir}")" && pwd)" # <-- change this as it depends on your app

arg1="${1:-}"