Shell 中有三种常用的命令连接符:&&、|| 和 ;,它们的执行逻辑完全不同。
三种连接符对比
| 连接符 |
执行条件 |
示例 |
说明 |
&& |
前面成功才执行后面 |
cmd1 && cmd2 |
AND 逻辑 |
| ` |
|
` |
前面失败才执行后面 |
; |
无条件执行后面 |
cmd1 ; cmd2 |
顺序执行 |
实例分析
问题示例
1
| python -m A.py && python /tmp/A.py ; python -m B.py && python /tmp/B.py
|
执行流程
执行 python -m A.py
- 成功 → 执行
python /tmp/A.py
- 失败 → 跳过
python /tmp/A.py
无论上一步结果如何,执行 python -m B.py(因为 ;)
- 成功 → 执行
python /tmp/B.py
- 失败 → 跳过
python /tmp/B.py
场景测试
场景 1:A.py 成功,B.py 失败
1 2 3 4 5 6 7 8
|
实际执行: 1. python -m A.py ✓ 2. python /tmp/A.py ✓ 3. python -m B.py ✗ 4. python /tmp/B.py (跳过)
|
场景 2:A.py 失败,B.py 成功
1 2 3 4 5 6 7 8
|
实际执行: 1. python -m A.py ✗ 2. python /tmp/A.py (跳过) 3. python -m B.py ✓ 4. python /tmp/B.py ✓
|
常用模式
确保全部成功
失败时执行备选
1 2 3 4 5
| cmd1 || cmd2
wget https://example.com/file || curl -O https://example.com/file
|
无条件顺序执行
组合使用
1 2
| rm -rf /tmp/cache || true ; make build
|
在 K8s 中使用
Pod 启动脚本
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| apiVersion: v1 kind: Pod metadata: name: init-demo spec: containers: - name: app image: python:3.9 command: ["/bin/sh", "-c"] args: - | python -m setup && \ python -m migrate && \ python -m app
|
容错启动
1 2
| python -m load_config || python -m init_default_config ; python -m start
|
退出码说明
Shell 通过退出码判断命令成功失败:
查看上一个命令的退出码:
设置脚本在任何命令失败时退出:
1 2 3 4 5
| #!/bin/bash set -e
cmd1 cmd2
|
实用技巧
确保关键步骤成功
1 2 3 4 5 6 7 8 9
| #!/bin/bash set -e
git pull && \ npm install && \ npm run build && \ npm test
echo "所有步骤成功完成"
|
日志记录
1 2
| cmd && echo "✓ cmd succeeded" || echo "✗ cmd failed"
|
超时控制
1 2
| timeout 5 long_running_cmd && echo "完成" || echo "超时或失败"
|
注意事项
set -e 模式下,|| 和 && 会影响脚本是否退出
- 管道命令
| 默认只检查最后一个命令的退出码,使用 set -o pipefail 检查所有
- 在脚本中建议使用
set -euo pipefail 组合提高安全性
参考示例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| #!/bin/bash set -euo pipefail
mkdir -p /tmp/build && cd /tmp/build
git clone https://github.com/example/repo.git || { echo "Git clone failed" exit 1 }
cd repo && \ npm install && \ npm run build && \ npm test
echo "构建成功"
|