大多数开发者"了解" Bash 的方式就像他们"了解" Git 一样:仅够应付。记住几个命令,从 Stack Overflow 复制脚本,按下回车前默默祈祷。
但 Bash 不仅仅是 Linux 爱好者或 DevOps 人员的胶水语言。它是自动化、调试、部署、数据处理以及无数日常任务背后的隐形力量。慢速开发者和高效开发者之间的差异,往往取决于他们对 shell 的掌握程度。
本文不是关于记忆晦涩的参数。而是关于实用的 Bash 脚本技巧——小想法带来巨大影响。这些技巧让你的脚本更安全、更整洁、更易维护。这些是你希望多年前就有人告诉你的东西。
让我们磨练你的终端直觉。
大多数 Bash 脚本会静默失败。这很危险。
每个开发者都应该知道的第一个技巧是在脚本顶部启用严格模式:
set -euo pipefail这一行代码的作用:
-e:命令失败时立即退出-u:将未设置的变量视为错误-o pipefail:如果管道中任何命令失败则失败没有这个设置,你的脚本可能执行到一半就出错了,但还会继续运行,就像什么都没发生一样。有了严格模式,失败会立即且明显——这正是自动化中你想要的。
可以把它理解为将 Bash 的运行时错误转变为编译时错误。
如果你的脚本接受参数,这个细节可以为你节省数小时的调试时间。
始终使用:
"$@"而不是:
$*为什么?因为 "$@" 保留参数边界。空格保持完整。文件名不会被拆分成碎片。当用户传递带引号的字符串时,你的脚本会正确运行。
这是那些看起来很迂腐的 Bash 规则之一——直到它在生产环境中破坏了重要的东西。
Bash 没有类型,但命名是你的安全网。
不好的做法:
x=10
y="file.txt"更好的做法:
MAX_RETRIES=10
INPUT_FILE="file.txt"为什么用大写?因为 Bash 约定将大写变量视为常量或配置。这也有助于避免与环境变量或命令名称冲突。
好的变量名将脆弱的脚本转变为可读的程序。
如果你还在使用反引号,是时候放弃它们了。
旧写法:
files=`ls`现代写法:
files=$(ls)使用 $(...) 进行命令替换的优势:
这不仅仅是语法偏好。这关乎编写随着增长而不会与你作对的 Bash 代码。
当出现问题时,你的脚本应该说明原因。
不要让 Bash 神秘地失败,而是这样做:
command || {
echo "❌ Failed to run command"
exit 1
}或者更好的做法,将其包装在函数中:
die() {
echo "Error: $1" >&2
exit 1
}现在你的脚本不仅会失败——它们还会沟通。未来的你会感谢现在的你提供的这种清晰度。
许多开发者避免在 Bash 中使用函数,认为这太过了。
其实不然。
函数让你能够:
示例:
cleanup() {
rm -rf /tmp/my_app
}你不需要面向对象的 Bash。你只需要结构。函数是最简单的胜利。
你是否曾在按下 Ctrl+C 后,脚本留下了半成品文件?
那是因为你没有捕获信号。
trap cleanup EXIT INT TERM这确保即使脚本意外退出,清理逻辑也会运行。
信号捕获对以下场景至关重要:
它们将脚本从"希望不出错"转变为"为混乱做好准备"。
在 Bash 中,未引用的变量就像地雷。
不好的做法:
rm $file好的做法:
rm "$file"如果 $file 包含空格、通配符或为空,未引用的变量可能导致数据丢失。
一个好的经验法则:如果是变量,就引用它。虽然有例外——但初学者不应该依赖它们。
这个单一习惯可以防止一些可以想象到的最糟糕的 shell bug。
Bash 支持数组。使用它们。
不要这样:
files="a.txt b.txt c.txt"而是这样:
files=("a.txt" "b.txt" "c.txt")数组保留结构,安全处理空格,并且行为可预测。
循环变得更安全:
for file in "${files[@]}"; do
echo "$file"
done一旦你正确使用数组,你就再也不想回去了。
这是一个经典陷阱。
错误做法:
for line in $(cat file.txt); do正确做法:
while IFS= read -r line; do
echo "$line"
done < file.txt正确的方法:
它看起来冗长,但这是唯一安全的方式。
当脚本行为异常时,猜测没有帮助。
打开执行跟踪:
set -xBash 会在运行每个命令之前打印它。这对以下情况非常有价值:
你甚至可以临时启用它:
set -x
# debug section
set +x这是 Bash 的内置调试器。使用它。
旧式测试表达式很脆弱。
使用:
if [[ "$a" == "$b" ]]; then而不是:
if [ "$a" = "$b" ]; then为什么?
[[ ... ]] 是 Bash 最好的升级之一。充分利用它。
当脚本开始嵌入 SQL、配置文件或大型文本块时,可读性会受损。
Here-docs 可以解决这个问题:
cat <<EOF > config.yaml
port: 8080
env: production
EOF它们非常适合:
可读的 Bash 就是可维护的 Bash。
添加 --help 标志。
认真的。
if [[ "$1" == "--help" ]]; then
echo "Usage: script.sh [options]"
exit 0
fi即使是简短的使用说明也能极大提高可用性——对队友和未来的你都是如此。
专业的脚本会自我解释。
这是最大的技巧。
大多数 Bash 脚本失败不是因为 Bash 不好——而是因为我们把脚本当作一次性代码。
做这些事情:
Bash 奖励纪律。忽视它,它会反咬你一口。
Bash 脚本不是关于成为终端高手。Bash 脚本是关于让你的工作生活无摩擦。通过 Slack 发送消息。将随机笑话下载到你的消息中。找到随机图片包含在你的消息中。
你不必成为 Bash 所有方面的专家。你只需要一些好习惯和运用它们的信心。
终端是命令执行的地方,但它也是杠杆所在的地方。