Python调用Shell脚本时如何捕获所有嵌套子脚本的退出码?
解决嵌套Shell脚本退出码无法捕获的方案
核心问题分析
set -ea并非在所有场景下都能传递子脚本错误,比如子脚本调用处于条件判断、命令替换或管道中时,set -e可能失效;另外如果子脚本自身未启用错误检测,即使它执行失败,也会返回退出码0给父脚本。以下是具体修复方案:
1. 升级父脚本的严格模式
将set -ea替换为更严格的set -euo pipefail,覆盖更多错误场景:
#!/bin/bash # e: 命令执行失败立即退出;u: 未定义变量直接报错;o pipefail: 管道中任一命令失败则整个管道退出码为失败 set -euo pipefail # 直接调用子脚本,错误会被自动传递 ./child_1.sh
2. 给所有子脚本添加错误检测
确保child_1.sh也启用严格模式,避免它执行失败却返回0:
#!/bin/bash set -euo pipefail # 调用不存在的child_2.sh时,脚本会直接退出,退出码为127 ./child_2.sh
3. 处理管道/条件判断中的子脚本调用
如果父脚本中用管道或条件语句调用子脚本,需显式检查退出码:
- 管道场景(无
pipefail时):
./child_1.sh | grep "log" # 检查管道中第一个命令(子脚本)的退出码 if [[ ${PIPESTATUS[0]} -ne 0 ]]; then exit ${PIPESTATUS[0]} fi
- 条件判断场景:
# 不用if包裹直接调用,或显式判断后退出 if ! ./child_1.sh; then exit $? fi
4. Python端确保正确捕获退出码
Python的subprocess.run会直接返回父脚本的退出码,只要父脚本正确传递子脚本错误,就能拿到真实失败码:
import subprocess result = subprocess.run(["./parent.sh"], stderr=subprocess.PIPE, text=True) print(f"脚本退出码: {result.returncode}") print(f"错误信息: {result.stderr}")
内容的提问来源于stack exchange,提问作者friggler
相关产品推荐
相关产品推荐

