You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何用subprocess.Popen调用bash脚本时source方式无法执行?

为什么用subprocess.Popen调用bash脚本时,直接执行正常但source/.调用失败?

先看测试代码和执行输出:

测试文件代码

test_python.py

import sys
import os
import subprocess

os.putenv("testvar", "testvalue")

test = subprocess.Popen("./test_shell.sh", shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE).communicate()
print(test)
test = subprocess.Popen(". test_shell.sh", shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE).communicate()
print(test)
test = subprocess.Popen("source test_shell.sh", shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE).communicate()
print(test)
test = subprocess.Popen("/bin/bash test_shell.sh", shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE).communicate()
print(test)
test = subprocess.Popen("/bin/sh test_shell.sh", shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE).communicate()
print(test)

test_shell.sh

#!/bin/bash

echo "$testvar"

执行输出

('testvalue\n', '')
('', '/bin/sh: .: test_shell.sh: cannot open [No such file or directory]\n')
('', '/bin/sh: .: test_shell.sh: cannot open [No such file or directory]\n')
('testvalue\n', '')
('testvalue\n', '')

原因分析

  1. 默认shell的差异:当subprocess.Popen设置shell=True时,默认调用系统的/bin/sh(多数Linux发行版中sh是dash的软链接),而非脚本指定的bash。source是bash专属内置命令,sh不识别,会自动 fallback 到.命令,但核心问题不在命令本身。
  2. 脚本查找规则不同:
    • 直接执行./test_shell.sh或用/bin/bash test_shell.sh时,要么明确指定了当前目录的相对路径(./),要么bash作为解释器会优先在当前工作目录查找未带路径的脚本,所以能找到文件。
    • 用.命令调用test_shell.sh时,sh会严格按照$PATH环境变量定义的目录查找脚本,当前工作目录默认不在$PATH中,因此提示找不到文件。

解决方法

方法一:指定脚本的相对路径

在.或source命令里给脚本加上./前缀,明确告知shell脚本在当前目录:

test = subprocess.Popen(". ./test_shell.sh", shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE).communicate()
test = subprocess.Popen("source ./test_shell.sh", shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE).communicate()

方法二:强制使用bash作为执行shell

给subprocess.Popen添加executable="/bin/bash"参数,强制用bash执行命令,这样既能正常识别source命令,bash的.命令也会优先在当前目录查找脚本:

test = subprocess.Popen("source test_shell.sh", shell=True, executable="/bin/bash", stdout=subprocess.PIPE, stderr=subprocess.PIPE).communicate()
test = subprocess.Popen(". test_shell.sh", shell=True, executable="/bin/bash", stdout=subprocess.PIPE, stderr=subprocess.PIPE).communicate()

内容的提问来源于stack exchange,提问作者silence_of_the_lambdas

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.16 01:19:54