如何在Bash中对stdout执行source操作以导出环境变量
问题原因
- 子shell执行差异:bash默认管道的每一个命令环节都会在独立子shell中运行,使用
| . /dev/fd/0写法时,source命令在子shell中执行,设置的环境变量仅在子shell生命周期内有效,父shell无法读取。zsh默认配置下管道最后一个命令会在当前shell执行,因此可以正常拿到变量。 - 断管错误根因:macOS默认自带的bash 3.2是发布于2006年的老旧版本,对进程替换
<()的处理存在缺陷:source命令读取完输入内容后会立即关闭对应的文件描述符,此时Python进程还未完成stdout的写入操作,管道被提前关闭就会抛出BrokenPipeError,Python2的报错也是相同逻辑导致的。
修复方案
- 通用兼容方案:直接用
eval捕获脚本输出,在当前shell执行,该方案不需要修改配置、不需要升级bash,所有常见shell版本都可正常运行:
# 直接执行该命令即可完成环境变量导出 eval "$(python env.py)" # 验证变量 echo $TEST_ME
注意仅对自己可控的脚本输出使用eval即可,避免执行不可信内容产生安全问题。
- 进程替换兼容方案:通过homebrew安装4.0及以上版本的bash,新版已修复进程替换的相关缺陷,安装后切换到新版bash即可正常运行
. <(python env.py)写法。
内容的提问来源于stack exchange,提问作者Andy
相关产品推荐
相关产品推荐

