脚本应以#!/usr/bin/env bash开头并设置set -euo pipefail和LC_ALL=C;函数需单一职责、动词命名、参数传值;配置与逻辑分离,敏感信息走环境变量;错误处理须显式判断并清理资源。

脚本开头必须声明解释器和编码
不写 #!/bin/bash 或写错路径(比如 #!/usr/bin/env bash 但系统没装 env),会导致脚本在不同环境执行行为不一致,甚至静默失败。中文注释或变量名含中文时,没加 set -u 和 LC_ALL=C 可能触发 locale 相关的截断或排序异常。
- 统一用
#!/usr/bin/env bash,兼容多数容器和开发机 - 紧随其后加
set -euo pipefail:提前暴露未定义变量、命令失败、管道错误 - 显式设置
LC_ALL=C避免sort、grep等命令因 locale 导致行为漂移
函数划分按「单一职责 + 动词命名」组织
把所有逻辑堆在 main 里,或用 func1、do_something 这类模糊名,会极大增加后续定位成本。真实运维中,你常需要快速判断“哪个函数负责清理临时文件”或“哪里读取了配置”,名字和职责必须一眼对应。
- 函数名用小写+下划线,以动词开头:如
load_config、validate_input、cleanup_temp_files - 每个函数只做一件事:
parse_args不该同时校验参数值,校验交给check_required_flags - 函数内部避免直接引用全局变量,优先通过参数传入;必要时用
local声明局部变量
配置与逻辑分离,用 config.sh 或环境变量注入
把数据库地址、超时时间、日志路径等硬编码在主脚本里,每次换环境都要改源码,极易漏改、误改。更糟的是,测试环境误用生产配置,可能直接删库。
- 提取为独立
config.sh,用source ./config.sh加载,且该文件应被.gitignore - 敏感项(如密码)不进脚本,走环境变量:
DB_PASSWORD="${DB_PASSWORD:-}",运行前DB_PASSWORD=xxx ./deploy.sh - 提供默认值但允许覆盖:
LOG_DIR="${LOG_DIR:-/var/log/myapp}",兼顾灵活性与健壮性
错误处理不能只靠 || echo "fail"
这种写法掩盖真实退出码,让上游调用方无法判断成败;更危险的是,它不会中断执行,后续命令可能在前序失败状态下继续运行,造成数据污染或状态混乱。
- 用
if显式判断:if ! cp "$src" "$dst"; then log_error "Failed to copy $src to $dst" exit 1 fi
- 关键路径操作后加
[[ -f "$dst" ]] || { log_error "Expected file missing: $dst"; exit 1; } - 捕获信号并清理:
trap 'rm -f "$TMPFILE"; exit 1' INT TERM
,避免 Ctrl+C 留下脏数据










