更新时间:2025-05-28 14:33点击:11
(拍大腿)哎我说各位,有没有遇到过这种情况——写了个牛哄哄的脚本,运行到一半突然退出了,留你在风中凌乱?上周我徒弟写的自动备份脚本,就因为退出方式不对,把整个硬盘给清空了!今儿咱就掰开了揉碎了聊聊,这shell脚本到底该怎么优雅退出!
先整明白个事儿,shell脚本退出可不是敲个Ctrl+C那么简单。去年某公司数据库迁移脚本,因为没正确处理退出状态,导致1TB数据损坏。三个必须知道的真相:
举个真实案例,我去年写的日志分析脚本,忘记在退出时关闭文件描述符,结果把32G内存吃光了——服务器直接宕机两小时!
记住这个口诀:0表成功非0错,状态码要按规矩来。举个栗子:
bash复制#!/bin/bash if [ ! -f \"data.txt\" ]; then echo \"文件不存在\" >&2 exit 1 fi # 正常操作 exit 0
重点来了:千万别学某些教程用exit 2表示警告,标准约定1-255都是错误,具体数字最好自己定义个文档说明。
(挠头)这个问题连老鸟都常搞混。简单说:
看个对比案例:
bash复制function test() { return 5 echo \"这行不会执行\" } test echo $? # 输出5 exit 3 echo \"这行也不会执行\"
教你们个绝活——trap命令。上周我写的下载脚本,就靠这个实现了CTRL+C时的断点续传:
bash复制trap \'cleanup; exit 130\' SIGINT cleanup() { echo \"正在保存进度...\" rm -f tmp_* }
记住常见信号:
(敲黑板)这个太重要了!推荐使用finally模式:
bash复制finally() { # 关闭数据库连接 # 删除临时文件 # 释放内存资源 } trap finally EXIT
遇到调用其他脚本的情况,记得检查$?:
bash复制./sub_script.sh if [ $? -ne 0 ]; then echo \"子脚本跪了\" >&2 exit 100 fi
(摸下巴)这个坑我踩过!一定要收尾:
bash复制python worker.py & pid=$! trap \"kill $pid; exit\" EXIT
用timeout命令最省事:
bash复制timeout 300 ./long_script.sh || { echo \"超时强制退出\" exit 201 }
推荐使用tee命令双写日志:
bash复制exec > >(tee -a output.log) exec 2>&1
见过最蠢的操作:
bash复制tmpfile=$(mktemp) exit 0 # 临时文件永远留在系统里
正确姿势应该放在trap里清理!
(伸懒腰)干了十年运维,见过太多脚本退出引发的惨案。我的原则是:宁可多写三行清理代码,也不留一个隐患。最近发现个新趋势,用Go重写关键shell脚本能避免很多退出问题,不过学习成本有点高。你们有啥独门绝技?评论区唠唠呗!不过说好了啊,发现好用的套路可别藏着掖着~