chmod +x script.sh脚本要能 ./script.sh 运行,先得有可执行位。
约 1269 字大约 4 分钟
2026-05-14
把一串敲过的命令存进文件,就成了脚本。它的价值是“把一次性的操作变成可重复、可交接的流程”。但 Shell 脚本也有不少陷阱——变量没引号、找错执行目录、错误被悄悄忽略。这篇从能跑、能读、能交接的角度讲怎么起步。
掌握 shebang、变量、条件、循环这些基本骨架,写出能跑、可读、别人也能接手的 Shell 脚本。
chmod +x script.sh脚本要能 ./script.sh 运行,先得有可执行位。
bash -n script.sh不执行,只查语法错误,写完先过一遍。
bash -x script.sh打印每一行实际执行的命令,调试脚本利器。
shellcheck script.sh自动揪出没加引号、用错变量等常见坑,强烈建议常用。
一个脚本的标准开头:
#!/usr/bin/env bash
# 这一行叫 shebang,告诉系统用哪个解释器来跑这个脚本为什么要写它:脚本被 ./script.sh 执行时,系统看 shebang 决定用 bash 还是 sh 还是别的。不写就依赖默认,换台机器可能就被 sh 执行、语法报错(原理见 Shell 是什么)。写脚本第一行永远是 shebang。
两种运行方式:
chmod +x script.sh && ./script.sh # 加执行权限后直接跑,用 shebang 指定的解释器
bash script.sh # 显式指定 bash 来跑,不依赖执行权限和 shebangname="shuo"
echo "Hello, $name" # 引用要加 $
greeting="Hi, ${name}!" # 名字和后面文字连着时用 ${} 界定最重要的一条习惯:引用变量永远加双引号 "$name"。不加引号,变量值里只要有空格就会被拆成多个参数——这是 Shell 脚本最高频的 bug 来源(详见 引号、转义与通配符)。
if [ -f "/etc/hostname" ]; then
echo "文件存在"
elif [ -d "/tmp" ]; then
echo "是个目录"
else
echo "都不是"
fi[ ] 里是测试表达式,常用的:-f 文件存在、-d 目录存在、-z 字符串为空、-n 非空、= 字符串相等、-eq 数字相等。注意 [ 前后、表达式各部分之间都要有空格——[$x] 是错的,[ $x ] 才对。
# 遍历文件
for f in *.log; do
echo "处理 $f"
done
# 按行读文件
while read -r line; do
echo "$line"
done < input.txtfor 适合遍历一组已知的东西;while read 适合逐行处理文件或命令输出。注意 read -r 的 -r——不加它,反斜杠会被特殊处理,几乎总是该加上。
Shell 能写出非常精炼但没人看得懂的“天书”。脚本是要给人维护的(包括三个月后的你自己),所以:
backup_dir 比 d 好脚本会忠实地执行错误,写完先 dry-run
脚本最危险的地方是它不会犹豫——你写错的 rm -rf "$dir/",在 $dir 为空时就成了 rm -rf /。安全习惯:① 写完先 bash -n 查语法、shellcheck 过一遍;② 涉及 rm、mv、覆盖文件的脚本,先把危险命令换成 echo 跑一遍,确认它实际会执行什么;③ 在测试目录、测试机上验证,再用到真实环境;④ 关键变量先判断非空再用(配合 set -euo pipefail 的 set -u)。
| 误区 | 更稳妥的做法 |
|---|---|
| 脚本不写 shebang | 第一行写 #!/usr/bin/env bash,别依赖默认解释器 |
| 变量引用不加引号 | 一律 "$var",否则含空格的值会被拆开 |
[ ] 里不留空格 | [ $x = y ] 各部分都要有空格 |
| 写完直接拿去真实环境跑 | 先 bash -n、shellcheck,危险命令先 echo 预览,测试环境验证 |
版权归属:Shuo Liu