这篇文章是关于我在编写 shell 脚本时使用的一些快速经验法则,多年来我逐渐领会这些法则。很有主见。
举例
-
使用
bash
。使用zsh
orfish
或任何其他,会使其他人难以理解/协作。在所有的shell中,bash
在便携性和DX之间取得了很好的平衡。 -
只需将第一行设为
#!/usr/bin/env bash
,即使您不授予脚本文件可执行权限。 -
为您的文件使用
.sh
(或.bash
)扩展名。没有脚本的扩展名可能很有趣,但除非您的情况明确依赖于它,否则您可能只是想做一些聪明的事情。聪明的东西很难理解。 -
set -o errexit
在脚本的开头使用。- 因此,当命令失败时,
bash
退出而不是继续执行脚本的其余部分。
- 因此,当命令失败时,
-
更喜欢使用
set -o nounset
. 你可能有很好的借口不这样做,但我认为,最好始终设置它。- 当访问未设置的变量时,这将使脚本失败。避免可怕的意外后果,变量名中有拼写错误。
- 当您想要访问可能已设置或未设置的变量时,使用
"${VARNAME-}"
而不是"$VARNAME"
,就可以了。
-
使用
set -o pipefail
。同样,您可能有充分的理由不这样做,但我建议始终设置它。- 这将确保管道命令被视为失败,即使管道中的一个命令失败。
-
使用
set -o xtrace
, 检查$TRACE
环境变量。- 对于复制粘贴:
if [[ "${TRACE-0}" == "1" ]]; then set -o xtrace; fi
。 - 这对调试脚本很有帮助。就像,真的很多。
- 人们现在可以启用调试模式,方法是运行您的脚本
TRACE=1 ./script.sh
而不是./script.sh
.
- 对于复制粘贴:
-
在/语句中使用
[[ ]]
for 条件,而不是or 。ifwhile[ ]test
[[ ]]
是一个内置关键字,比[ ]
or更强大test
。
-
始终用双引号引用变量访问。
- 可以不这样做的一个地方是在条件的左侧
[[ ]]
。但即使在那里,我也建议引用。 - 当您需要未引用的行为时,使用
bash
数组可能会更好。
- 可以不这样做的一个地方是在条件的左侧
-
在函数中使用
local
变量。 -
接受用户寻求帮助和以实物回应的多种方式。
- 检查第一个参数是
-h
or--help
orhelp
justh
还是 even-help
,在所有这些情况下,打印帮助文本并退出。 - 为了未来的自己。
- 检查第一个参数是
-
打印错误消息时,请重定向到 stderr。
- 用于
echo 'Something unexpected happened' >&2
此。
- 用于
-
尽可能使用长选项(比如
--silent
而不是-s
)。这些用于明确记录您的命令。- 但请注意,在某些系统(如 macOS)上发布的命令并不总是有很长的选项。
-
如果合适,切换到靠近脚本开头的脚本目录。
- 它通常总是合适的。
- 使用
cd "$(dirname "$0")"
,这在大多数情况下都有效。
-
使用
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 "$@"
结论
我试着在我的剧本中遵循这些规则,众所周知,它们至少让我自己的生活变得更好。不幸的是,我仍然没有始终如一地遵守自己的规则。因此,也许以这种方式写下它们也能帮助我在这方面进行改进。