在平时的Linux运维工作中,Shell脚本是自动化部署、监控告警、批量操作的核心工具,每个运维牛马都必须要掌握的,掌握了Shell,你才能有基础往高处走,学习python、perl之类的语言。
Shell脚本执行后的退出状态码(简称退出码),是实现脚本流程控制的关键技术。今天就简单聊下Shell脚本退出码的使用技巧,大佬请绕路。
什么是退出码?在Linux Shell环境中,每执行一条命令或一个脚本后,系统都会返回一个0~255之间的整数值,这个值就是退出码。它的核心作用是向Shell反馈命令/脚本的执行状态,后续操作可根据该状态决定执行逻辑(比如执行成功则继续,失败则回滚)。
退出码会临时存储在特殊环境变量$?中,通过简单命令即可查看上一条命令的执行结果。
echo $?# 输出0,代表命令成功结束# 输出非0值,代表命令执行失败
Linux系统定义了一系列标准退出码,掌握这些常用码的含义,能快速定位问题根源:
退出码 | 含义描述 | 典型场景 |
0 | 命令成功结束 | 正常执行的ls、cp、mkdir等命令 |
1 | 一般性未知错误 | 语法正确但执行逻辑出错(如脚本中变量未定义) |
2 | 不适合的shell命令 | 命令参数错误或选项不合法 |
126 | 命令无法执行 | 文件存在但无执行权限(如chmod -x 脚本.sh后执行) |
127 | 未找到命令 | 命令名拼写错误(如将ls写成lss)或命令未在PATH路径中 |
128 | 无效的退出参数 | exit命令后跟随非数字参数(如exit "error") |
128+x | 与Linux信号x相关的严重错误 | 128+2=130(代表通过Ctrl+C终止命令)、128+9=137(代表进程被kill -9强制终止) |
130 | 通过Ctrl+C终止的命令 | 执行脚本时手动按Ctrl+C中断 |
255 | 正常范围之外的退出状态码 | 自定义退出码超出0~255范围时的默认返回值 |
默认情况下,Shell脚本执行完毕后,会以脚本中最后一条命令的退出码作为整个脚本的退出码。但实际工作中,需要输出指定的退出码,这就需要用到exit内置命令。exit命令的基础用法有两种:
第一种是退出并返回指定退出码,语法格式为:
exit n # n为0~255的整数,代表脚本的退出码
第二种是退出并沿用前一条命令的退出码,语法格式为:
exit # 无参数时,使用上一条命令的退出码作为脚本退出码
使用exit命令时需要注意两点:一是退出码必须在0~255范围内,若指定大于255的值(如exit 300),系统会自动取该值除以256的余数作为实际退出码(300÷256=1余44,最终退出码为44);二是脚本中执行exit命令后,脚本会立即终止,后续代码不再执行,需合理控制exit的执行时机。
退出码的实际应用场景 在自动化脚本中,可通过判断前一步命令的退出码,决定是否继续执行后续操作。比如部署应用时,先执行部署命令,再校验退出码判断部署结果:
#!/bin/bash# 部署应用docker run -d --name app app:v1# 校验部署是否成功(退出码0为成功)if [ $? -eq 0 ]; then echo "应用部署成功" # 继续执行健康检查等后续操作 curl http://localhost:8080/healthelse echo "应用部署失败" exit 1 # 部署失败,脚本退出并返回错误码fi
当多个脚本协同工作时(如脚本A调用脚本B),可通过退出码传递执行状态。比如主脚本调用备份脚本,只有备份成功才继续执行同步脚本:
# 脚本A(主脚本)#!/bin/bashecho "执行数据备份脚本..."./backup.sh# 若备份脚本返回0(成功),则执行同步脚本if [ $? -eq 0 ]; then echo "备份成功,执行数据同步..." ./sync.shelse echo "备份失败,终止执行" exit 1fi
还可以结合退出码记录错误日志,并触发告警机制(如邮件、钉钉通知)。比如数据库备份失败时,记录日志并发送告警:
#!/bin/bash# 数据库备份mysqldump -u root -p123456 db > db_backup.sqlif [ $? -ne 0 ]; then # 记录错误日志 echo "$(date) 哦豁!数据库备份失败" >> /var/log/backup_error.log # 触发钉钉告警(调用告警脚本) ./dingtalk_alert.sh "数据库备份失败,快去瞄一眼啦" exit 1fi
脚本中主动设置退出码很有必要,关键业务步骤(如备份、部署、数据同步)执行后,主动用exit n返回状态码,能大幅提升问题定位效率。
要避免过度依赖默认退出码,默认情况下脚本以最后一条命令的退出码为准,若最后一条命令是“无关命令”(如echo),可能掩盖真实执行结果,建议在脚本末尾主动指定exit 0或exit 1。
当脚本可能被手动中断(如Ctrl+C)时,可通过捕获信号量(如SIGINT),返回特定退出码(如130),便于日志分析。
如果是大公司,运维工程师有一堆人的,那么可自定义退出码规则(如100=配置错误、101=网络异常、102=权限不足),自己人一眼看出什么问题,在客户面前尽情的装X。同时也能有效提升脚本的可读性和可维护性,当然这不存在,我写的脚本怎么可能让下任看得懂??(全文完)