这周不太想写长文章,先翻译一篇充充数


原文:Shell Script Best Practices

本文是个人这些年写 shell 脚本积累的经验法则,以飨读者。

规则

1、使用 bash

使用 zsh、fish 将使得其他人难于理解和合作。在所有的 shell 中,bash 在可移植性和 DX(?) 之间取得了一个比较好的平衡。

2、第一行写 #!/usr/bin/env bash,即使没有放开脚本文件的可执行权限

进入 bash 执行环境。

3、使用 .sh / .bash 作为脚本文件扩展名

不给脚本设置扩展名可能会显得比较花哨,但除非你在目前的场景中明确需要这样,你可能仅仅是想做点聪明事。聪明事通常难以理解。

4、脚本开头写上 set -o errexit

作用是当某一行命令失败时,脚本会直接退出,而不会继续执行剩余的命令。

5、首选使用 set -o nounset

你可能有很好的理由不这样写,但我的观点是最好写上。

  • 当脚本访问了未设置的变量时,执行失败。保障不会陷入由于变量名拼写错误导致的预期外的可怕结果中;
  • 当需要访问一个可能未设置的变量时,使用 “${VARNAME-}” 代替 “$VARNAME”

6、使用 set -o pipefail

作用是保障管道命令中任何一个命令失败,管道的结果就是失败。

7、使用 set -o xtrace,伴随一个对 $TRACE 环境变量的检查

  • 对于 copy-paste 模式:if [[ “${TRACE-0}” == “1” ]]; then set -o xtrace; fi.
  • 对 debug 脚本很有帮助;
  • 现在支持开启 debug 模式,只要在运行时使用 TRACE=1 ./script.sh 代替 ./script.sh

8、使用 [[ ]] 作为 if/while 中的条件判断语句代替 [ ]test

[[ ]] 是一个比 []test 更强大的关键字。

9、访问变量时用双引号括起来

  • 当变量位于 [[ ]] 中判断条件的左侧时可以不采用双引号括起来,但即使这种场景,我也建议括起来;
  • 当需要不括起来的使用方式时,采用 bash 数组会更好。

10、在方法中使用 local 声明变量

11、支持多种用户求助方式或提供友好响应

  • 保障脚本的第一个参数是 -h–helphelph、甚至 -help 时,能打印帮助并退出;
  • 请为未来的自己着想一下。

12、错误消息重定向到 stderr

使用 echo ‘发生了未预期的事情’ >&2

13、只要可能,就使用长的选项命名方式(如使用 –silent 代替 -s)

这种命名方式有助于显式说明命令用途。

不过请注意,某些系统上提供的命令——比如 macOS,并不总是有长命名方式。

14、合适的话,在脚本正式开始工作之前将工作路径切换到脚本所在的路径下

  • 其实总是合适的;
  • 使用 cd “$(dirname “$0″)”,大部分情况下都有效 。

15、 使用 shellcheck. 注意它的告警提示。

模板

#!/usr/bin/env bash

set -o errexit
set -o nounset
set -o pipefail
if [[ "${TRACE-0}" == "1" ]]; then
    set -o xtrace
fi

if [[ "${1-}" =~ ^-*h(elp)?$ ]]; then
    echo 'Usage: ./script.sh arg-one arg-two

This is an awesome bash script to make your life better.

'
    exit
fi

cd "$(dirname "$0")"

main() {
    echo do awesome stuff
}

main "$@"

结论

我尽力遵守这些规则,至少这样让我的生活更美好了。不幸的是,我并不总是能完全遵守自己总结的这些规则。So,也许写下来也对我有所帮助。

分类: CODE

0 条评论

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注