如何在Python脚本的subprocess中覆盖ansible.cfg变量?
问题根源与差异解析
命令行里的ANSIBLE_DISPLAY_OK_HOSTS=true ansible-playbook ...是Shell的特殊语法:Shell会先解析VAR=value部分,把环境变量临时注入到后续命令的运行环境中,再执行后面的ansible-playbook。
但subprocess.run默认不会启动Shell来解析命令:
- 你第一种写法直接传拼接好的字符串,默认情况下subprocess会把整个字符串当作一个可执行文件的路径查找,自然找不到
ANSIBLE_DISPLAY_OK_HOSTS=true ansible-playbook这个文件 - 第二种写法把带环境变量赋值的部分当作列表第一个元素,subprocess同样会把它当作可执行文件路径,因此报出"No such file or directory"错误
解决办法
有两种可靠的处理方式:
方式一:用env参数传递环境变量(推荐)
这种方式不依赖Shell,更安全(避免Shell注入风险),也符合subprocess的最佳实践:
import os import subprocess # 获取当前环境变量副本,避免修改全局环境 env = os.environ.copy() # 添加临时环境变量 env["ANSIBLE_DISPLAY_OK_HOSTS"] = "true" # 用列表形式传递命令参数(推荐的参数传递方式) command = [ "ansible-playbook", "-i", inventory_path, absolute_playbook_path, "--tag", ansible_tag ] subprocess.run(command, env=env)
方式二:开启shell=True(谨慎使用)
如果一定要用Shell语法解析命令,可以给subprocess.run加上shell=True参数,但需注意:如果inventory_path、ansible_tag等参数来自不可信输入,可能存在Shell注入风险。
command = f"ANSIBLE_DISPLAY_OK_HOSTS=true ansible-playbook -i {inventory_path} {absolute_playbook_path} --tag {ansible_tag}" subprocess.run(command, shell=True)
内容的提问来源于stack exchange,提问作者David Louda
相关产品推荐
相关产品推荐

