Shell批量脚本可靠性取决于失败应对机制:需用set -e或检查$?,配合nullglob、引号包裹、find替代for、显式错误处理、mv -vn防覆盖、ssh -t处理TTY、参数校验及安全输入。

Shell批量操作脚本不是写得越长越可靠,而是每一步都得有明确的失败应对——没加 set -e 或没检查 $? 的脚本,跑得越顺越危险。
如何让 for 循环真正“批量”而不是“盲目执行”
常见错误是直接用 for file in *.log 处理文件,但一旦当前目录没有匹配项,*.log 会原样传给循环体,导致命令对字面量 *.log 执行,报错或误删。
- 用
shopt -s nullglob让未匹配的 glob 展开为空,避免空循环或误匹配 - 处理前加判断:
[[ -n "$file" ]] || continue(尤其在旧 shell 中) - 路径含空格时,必须用双引号包裹变量:
cp "$file" /backup/,否则my file.log被拆成两个参数 - 如果目标是遍历子目录,优先用
find ... -exec而非for dir in */,后者不递归且跳过隐藏目录
批量执行命令时怎么捕获并区分成功与失败
只靠 && 连接命令掩盖了中间步骤的真实退出码;而全靠 set -e 又会让某些预期失败(如 grep 找不到内容)直接中断脚本。
- 关键命令后立刻检查:
if ! systemctl restart nginx; then echo "nginx 启动失败" >&2; exit 1; fi - 用
$?获取上一条命令真实返回值,比单纯看 stdout 更可靠 - 批量重命名或移动时,用
mv -vn(-v 显示动作,-n 防覆盖),避免静默覆盖已有文件 - 远程批量执行(如用
ssh)时,注意ssh默认不继承终端,sudo可能因缺少 TTY 拒绝执行,加-t或改用sudo -n
脚本里怎么安全地处理用户输入和配置参数
把 $1 直接当路径用、不校验是否存在,或者用 read 读密码却没关回显,都是典型事故源头。
- 参数校验优先级高于逻辑:用
[[ -d "$1" ]] || { echo "错误:$1 不是有效目录"; exit 1; } - 密码类输入用
read -s -p "输入密码: " passwd,-s 关闭回显 - 配置项建议提取到开头的变量区,并加注释说明用途,例如:
BACKUP_DIR="/data/backup",而非散落在各处的硬编码路径 - 避免在脚本中写死 IP 或域名,改用环境变量或外部配置文件:
source ./config.env,且确保该文件权限为600
真正难的不是写出能跑的批量脚本,而是让它在目录突然变空、磁盘突然写满、SSH 连接中途断开时,不删错数据、不卡死进程、还能留下可读的日志线索。别省那几行 || echo "step X failed" 和 set -u。

















