我正在尝试在 /home 之外的目录中创建一个与系统环境不同的 Python 环境(使用 virtualenv),因为我需要使用它来构建其他必须可供多个用户访问的软件。我可以创建并激活 virtualenv,但是当我执行sudo
某些命令(例如,制作或编译其他软件)时,使用的是系统 Python(我可以通过可用的模块判断)。
因为在 Ubuntu 上,使用根用户,有没有办法告诉sudo
我使用虚拟环境?或者这不是正确的方法,我应该进行全新的 Python 安装?
我正在使用 64 位版本的 Ubuntu 12.04(和 python 2.7)。
答案1
问题几乎肯定是当您运行时sudo
,virtualenv 环境变量、别名、函数等不会被延续。
解决方案是使用 明确运行虚拟环境的 Python 可执行文件sudo
。例如,如果您的虚拟环境是 ./AwesomeProject,那么您可以运行sudo ./AwesomeProject/bin/python <script>
以使用具有 root 权限的虚拟环境脚本。
答案2
根据您的具体用例,这可能会或可能不会解决您的问题,但这里尚未提及。假设您想要运行安装在虚拟环境中的 Python 脚本,并且您需要setuid(0)
它,即您想要以超级用户身份运行它。假设您的脚本名为myscript.py
,那么您可以这样做:
(.venv) $ sudo -E env PATH=$PATH ./myscript.py
解释
(.venv) $
是 shell 的提示符,您不需要输入它,它只是表明您当前正在使用某个虚拟环境,并且您不是特权用户。
sudo -E
会告诉sudo
您在启动进程时,需要从当前 shell 环境中复制环境变量。因此,如果您在.venv/bin/activate
脚本中定义了任何额外变量,它们应该在您启动时保留下来root
。
env PATH=$PATH
使用时sudo -E
并非所有环境变量都会被保留,具体来说,最重要的是,PATH
可能会删除。此行为的细节取决于您的 sudoers 文件。但是,这将绕过 sudoers 文件中写入的任何内容,因为它会将明确复制到为新进程创建的PATH
环境中。这很重要,因为当您的系统解析中的 shebang 注释时,它将查看变量,并且将使用第一个符合解释器要求的目录。另一方面,以这样的方式设置 shell 环境,即包含所选 Python 解释器的符号链接的目录首先出现,从而导致系统在系统路径上的任何其他 Python 之前找到所需的 Python。sudo
myscript.py
PATH
venv
答案3
有时您需要更新 $PATH,因为脚本运行其他程序。例如,pypi-install 需要 PATH 中的 py2dsc-deb。此命令有效:sudo sh -c ". venv/bin/activate ; pypi-install $PACKAGE"
答案4
我想添加我的答案,因为我现在偶然发现了同样的问题。但是我为 repo 创建了一个 shell 脚本,因此我不想使用硬编码路径。以下是我现在正在做的事情:
- 输入您的 venv:
source /path/to/your/venv/bin/activate
- 无需 sudo 即可获取 venv 的 python3 二进制文件的路径:
PYTHON3_VENV_PATH=$(which python3)
- 现在您可以使用 sudo 和 python3 二进制文件运行脚本:
sudo $PYTHON3_VENV_PATH path/to/your/script.py