pip在使用sudo时不遵循PIP_INDEX_URL
根据文档,我可以让pip使用我自己的私有pypi仓库,而不是官方的那个:
For pip this can be done by setting the environment variable PIP_INDEX_URL in your .bashrc/.profile/.zshrc:
export PIP_INDEX_URL=http://localhost:8080/simple/
所以我在我的Debian服务器上,把我的私有仓库(比如说 http://pypi.mycompany.com/simple
)添加到了 /etc/profile
文件里。但是pip还是报错:
john@server:~$ sudo pip install ipython
Downloading ...
Cannot fetch index base URL https://pypi.python.org/simple/
...
看起来pip没有识别我设置的环境变量 PIP_INDEX_URL
。这是为什么呢?
更新:
按照@Ivo的指示,我发现我的Python根本没有看到这个变量:
john@server:~$ sudo python -c "import os; print(os.getenv('PIP_INDEX_URL'))"
None
2 个回答
Sudo会通过重置大部分环境变量来清理安全环境。默认情况下,它会重置所有不在保留列表中的变量。Sudo有三类环境变量:检查、重置和保留。默认情况下,它会重置所有不在保留列表中的变量。
可用选项:
如前所述,你可以通过
-E
或--preserve-env
全局传递所有环境变量。这会带来安全问题。传递环境变量可能会污染或影响在(安全)环境中的执行。比如
$LD_PRELOAD
或$IFS
的问题。-E
和--preserve-env
支持一个变量列表作为参数,以保留除了默认变量之外的其他变量:sudo --preserve-env=PIP_INDEX_URL pip install python
你可以通过命令行将环境变量显式传递给 ssh 命令:
sudo -e PIP_INDEX_URL=${PIP_INDEX_URL} pip install ipython
${PIP_INDEX_URL} 会在传递给
sudo
之前被命令行解析。这是一个实用的命令行技巧,适用于
ssh
以及其他需要直接将参数和环境传递给子进程的情况。在
sudoers
配置文件中修改你的 sudo 配置,以扩展允许传递给子进程的环境变量列表。可以查看env_keep
选项。DEFAULT env_keep+=PIP_INDEX_URL
我认为这个选项是最干净的,特别是在多个用户需要使用相同 pip 选项的系统上。
你的
sudoers
文件的最后一行可能包含一个#includedir
指令。如果有的话,可以把你的修改放在那个目录下的文件中,比如/etc/sudoers.d/pip_environment
,并为PIP_INDEX_URL
、PIP_TRUSTED_HOST
、PIP_EXTRA_INDEX_URL
和其他配置所需的选项添加保留选项。
参考资料:
sudoers 配置: man 5 sudoers
sudo 选项: man 8 sudo
pip 环境变量的命名格式为
PIP_
后面跟着完整命令行标志的大写拼写。请参见: pip 配置文件文档你可以通过以 root 身份运行
sudo -V
来查看检查、重置和保留列表:% sudo sudo -V # ... Environment variables to check for sanity: TZ TERM # ... Environment variables to remove: *=()* # ... Environment variables to preserve: MAIL HOME
找到了。其实很简单:出于安全考虑,sudo
默认情况下不会使用环境变量。要让 sudo
保留环境变量,可以使用 -E
这个选项,比如:
sudo -E pip install ipython