工具 Linux
一行串起多条命令:Linux 中 ;、&& 与 || 的执行语义详解
有的时候执行一些简单指令,总不想分好几次输入。利用 Shell 的命令串联能力可以方便地一次执行多个命令,但
;、&&、||三种写法在出错时的行为完全不同,用错了轻则白跑,重则脏数据。这篇文章用同一个例子把三者的语义讲清楚。
前置知识:命令的退出码
要理解三种分隔符,先要知道 Linux 下每条命令执行完都有一个退出码(exit code):0 表示成功,非零表示失败。可以用 echo $? 查看上一条命令的退出码。
;、&&、|| 的区别,本质上就是根据前一条命令的退出码,决定后面还跑不跑。
连续不中断执行:;
用 ; 分隔的命令会依次全部执行,中间出错也不会中断后面的命令:
bash
mkdir test; mkdir test; rmdir test第一次执行时:
mkdir test成功,创建目录;mkdir test报错(目录已存在),但没关系;rmdir test照常执行,把目录删掉。
最终结果:命令全部跑完,test 目录不存在。
适用场景:几个互不依赖的操作打包执行,比如批量清理、一系列互不影响的查询。
出错即停止:&&
用 && 分隔的命令,前面的成功才继续,一旦出错立即中止:
bash
mkdir test && mkdir test && rmdir test这回在第二个 mkdir test 处就中止了,rmdir 不会执行,test 目录残留。
适用场景:步骤之间有依赖关系的流水线,最经典的就是「编译成功才部署」:
bash
make && make install这是 && 最重要的价值——防止上一步失败时,下一步在错误状态上继续执行。
一次成功即停止:||
用 || 分隔的命令,前面的失败才继续,直到有一次成功立即停止:
bash
mkdir test || mkdir test || mkdir test- 第一次执行:第一条就成功,后面两条不执行;
- 换成
mkdir test || mkdir test || mkdir test || mkdir test并在test已存在时执行:前两条都报错,第三条也报错,最后一条才成功(如果前面的命令已把目录建好,逻辑同理)。
适用场景:提供备选方案(fallback),典型的例子是「目录不存在才创建」:
bash
test -d /data/logs || mkdir -p /data/logs以及「本地没有配置文件就复制一份默认的」:
bash
cp config.local.yml config.yml 2>/dev/null || cp config.example.yml config.yml三者对比速查
| 分隔符 | 前面成功时 | 前面失败时 | 典型用途 |
|---|---|---|---|
; | 继续执行 | 继续执行 | 无依赖操作打包 |
&& | 继续执行 | 停止 | 有依赖的流水线 |
| ` | ` | 停止 |
组合使用也很常见,比如「成功打日志、失败打告警」:
bash
./run_job.sh && echo "job done" || echo "job failed"写在后面
这套语义在脚本里还可以用 set -e(出错即退出整个脚本)进一步收口,但交互式命令行里,; / && / || 依然是最常用的三件套。理解「退出码驱动」这个本质,比背案例更重要——任何分隔符的行为,都可以从前一条命令的退出码推导出来。