Shell脚本精读 · S04-01 | 退出状态 `$?`:命令成功与失败

发布时间:2026/6/24 8:14:01
Shell脚本精读 · S04-01 | 退出状态 `$?`:命令成功与失败 模块S04 退出状态与布尔逻辑篇号S04-01 / 42预计阅读35 分钟主线Bash文章目录本篇目标30 秒速览正文1. 退出状态是什么2. $?上一条命令的结果3. 成功与失败谁决定 0 和非 04. true 与 false5. exit结束脚本并返回退出码6. 管道与 $?与 S01-04 呼应7. if 与退出码预告 S068. 与 set -e 的关系预告9. 读脚本检查清单练习判断题实操题改错题下一篇预告本篇目标理解 Shell退出状态exit status每条命令执行后都有退出码0 表示成功非 0 表示失败。会读取$?、使用true/false、用exit结束脚本并返回码。为 S04-02 的/||和 S05S06 的if/test打基础。30 秒速览每条命令、脚本结束后都有一个0255的退出码exit status。$?保存上一条命令的退出码读后会被下一条命令覆盖。0 成功1255 失败含义由命令自定常见 1 为通用错误。exit n结束当前 Shell/脚本退出码为n默认 0。true退出 0false退出 1。if cmd看的是cmd的退出码不是 stdout 输出内容。正文1. 退出状态是什么Shell 不只看命令有没有打印输出而是看进程结束时的exit code退出码常见含义0成功1一般性错误2误用 Shell 内置命令等视情况126不可执行127命令未找到128n被信号 n 终止如 130 常表示 CtrlC脚本被别的程序调用时对方常用退出码判断「脚本是否成功」./backup.shif[$?-eq0];thenecho备份成功fi更常见的写法是if ./backup.sh; thenS06-01。2.$?上一条命令的结果ls/tmpecho$?# 0通常 /tmp 存在且可列ls/no_such_direcho$?# 2 等非 0ls 报错重要$?只反映紧挨着的前一条命令且读后即被刷新falseecho$?# 1echo$?# 0上一条是 echo成功需要保存时立刻赋值greppattern file.txtstatus$?if[$status-eq0];thenecho找到fi3. 成功与失败谁决定 0 和非 0由该命令自身定义Shell 只负责传递命令典型成功典型失败grep找到匹配 → 0未找到 → 1diff相同 → 0不同 → 1test/[条件为真 → 0为假 → 1false无总是 1true总是 0无grep-qerrorapp.logecho$?# 0 表示出现过 error1 表示未出现读日志脚本时不要只看有没有输出要看$?或if grep -q。4.true与false内置命令专门产生固定退出码trueecho$?# 0falseecho$?# 1用途whiletrue;do# 无限循环靠 break 退出S07:doneiffalse;thenecho不会执行fi5.exit结束脚本并返回退出码#!/usr/bin/env bashset-euopipefail do_work||exit1echo只有 do_work 成功才到这里exit0写法含义exit退出码为0成功exit 1失败通用exit 2自定义错误类型退出码超过 255 会被取模exit 300→ 300 % 256 44脚本里一般用0125。在函数里用return n返回码给调用方S08-01exit会结束整个脚本或被 source 时结束当前 Shell。die(){echo错误:$*2exit1}[-f$CONFIG]||die缺少配置文件$CONFIG6. 管道与$?与 S01-04 呼应默认情况下$?是管道最后一个命令的退出码false|trueecho$?# 0true 成功开了set -o pipefail后管道中任一失败则整管道失败S01-04、S09-02。7.if与退出码预告 S06ifgrep-qERRORlog.txt;thenecho有错误行fiif后面跟的是命令Shell 根据该命令退出码是否为 0 决定走then还是else。不是根据grep打印了多少行。iffalse;thenechonoelseechoyes# 走这里fi条件表达式[ ... ]、[[ ... ]]也是命令成功真→ 0S05。8. 与set -e的关系预告set -e任一命令退出码非 0脚本立即退出有例外S01-04。理解$?后读set -e脚本时要分清哪条命令的失败会触发退出。9. 读脚本检查清单判断成功是否用$? -eq 0而不是看有没有输出是否在$?已被下一条命令覆盖后才读grep、diff等「未找到」是否被误当成脚本失败脚本失败时是否exit非 0管道是否结合pipefail理解$?练习判断题命令退出码为 0 表示执行失败。echo $?可以连续两次得到同一条false命令的退出码。exit 0表示脚本成功结束。if cmd; then根据cmd的标准输出是否为空分支。参考答案错。错第一次 1第二次 0。对。错看退出码。实操题grep-qroot/etc/passwdechogrep1$?grep-qno_such_user_xyz/etc/passwdechogrep2$?trueechotrue$?falseechofalse$?记录各$?并说明原因。改错题#!/usr/bin/env bashset-euopipefail ./risky_task.shresult$?if[$result0];thenechookfi./another.shecho上一条 risky 的结果仍是$result说明result在another.sh之后是否仍表示risky_task.sh的结果。参考result仍保存risky_task.sh的退出码$?在./another.sh之后已变但变量result未变。若意图是检查another.sh应在another.sh后立刻result$?。下一篇预告S04-02《逻辑连接符||!与短路求值》— 用退出码串联命令读懂cmd1 cmd2与set -e的配合。