使用sudo执行Python subprocess时,bash -x的PS4变量为何异常?
问题原因与解决方案
这个问题的核心是sudo默认会重置大部分用户环境变量,导致你在Python脚本里设置的PS4没有被传递给sudo启动的bash进程。
为什么会这样?
Ubuntu 16.04的sudo默认启用了env_reset配置(在/etc/sudoers里可以看到),这个配置会清除普通用户的环境变量,只保留少数被认为安全的系统变量。当你用sudo执行脚本时,Python里设置的os.environ['PS4']会被sudo的环境重置机制清空,bash启动时就会使用默认的PS4值(也就是+),而不是你设置的aaa。
而普通用户执行时没有这个环境重置,所以bash能正确读取到你设置的PS4变量。
解决方法
这里有几个可行的方案,你可以根据需求选择:
1. 使用sudo -E保留用户环境
-E选项会让sudo保留当前用户的环境变量,这样你设置的PS4就能被传递给bash:
sudo -E ./test.py
2. 在subprocess.Popen里显式传递环境变量
不要依赖全局的os.environ,而是直接把环境变量作为参数传递给Popen,这样即使sudo重置了外部环境,subprocess启动的bash依然能拿到指定的PS4:
修改你的test.py代码:
#!/usr/bin/python import subprocess import os # 复制当前环境并修改PS4 env = os.environ.copy() env['PS4'] = "aaa " res=subprocess.Popen(['bash', '-x', '1.sh'], stderr = subprocess.PIPE, env=env) print res.stderr.readlines()
3. 修改sudoers配置(谨慎操作)
如果你需要长期保留PS4变量,可以编辑sudoers文件,让sudo允许保留PS4:
- 执行
sudo visudo打开编辑界面(一定要用visudo,避免语法错误导致sudo失效) - 添加一行配置:
Defaults env_keep += "PS4" - 保存退出后,再执行
sudo ./test.py就会生效了。
内容的提问来源于stack exchange,提问作者Yves
相关产品推荐
相关产品推荐

