普通用户可以执行,sudo提示command not found的问题分析——修改sudo命令的环境变量

以下所有操作均在Centos6.10上进行

今儿在一台新虚拟机上安装pip之后,用pip安装包,需要root权限,但执行sudo pip就提示command not found

经过查阅资料发现,出于安全方面的考虑,使用sudo执行命令将在一个最小化的环境中执行,环境变量都重置成默认状态。所以PATH这个变量又不包括pip的执行目录了

可以使用printenv这个命令,检查当前的PATH变量

pritnenv PATH
sudo printenv PATH

!!注意!!

为什么要这么设计,因为$PATH变量是一个很危险的环境变量,例如下面这篇文章就讲了黑客如何利用$PATH变量获得root权限

http://www.52bug.cn/%E9%BB%91%E5%AE%A2%E6%8A%80%E6%9C%AF/5034.html

《UNIX&LINUX大学教程》这本书里也提到,如果$PATH变量中包括了一些谁都有权限读写的目录,黑客可以通过撰写名为cd、ls之类的脚本,这样原来的系统命令就被替换为了黑客命令

因此不推荐修改sudo的环境变量,推荐使用方法四来执行命令,如果非要修改,可以参考方法三方法八,其他的方法都是失败的尝试

方法一:修改/etc/profile(失败)

在/etc/profile中加入pip执行目录并source /etc/profile之后,sudo pip依然不能执行

其实我的pip安装到了/usr/local/bin下面,一般的$PATH已经有了这个目录

方法二:直接用root用户执行(成功)

不使用sudo,直接使用su切换到root用户执行,缺点是麻烦,没事用root用户还很危险

方法三:修改/etc/sudoers文件的secure_path(成功)

打开/etc/sudoers文件,查看secure_path这一项配置,这就是用sudo命令时的环境变量,可以通过修改这一设置

使用visudo命令,就可以打开/etc/sudoers文件进行修改,在secure_path后面加入pip的执行路径,我这里是/usr/local/bin,保存即可生效

我本来想把$PATH这个变量直接写上,但是并不起作用

方法四:把路径写完整(成功)

直接sudo /usr/local/bin/pip,嗯,肯定是成功的

方法五:修改/etc/sudoers文件的env_reset(失败)

网上很多方法说,修改env_reset这一项,这样执行sudo的时候就不会重置环境变量了

在/etc/sudoers文件中找到这一段,可以读出来env_reset是控制环境变量是否重置的选项,给他关掉,改成下面这句

Defaults !env_reset

试了一下,并没有变化 

用man sudoers查看一下用户手册

 提炼出有效信息

  1. env_reset开启时,会用/etc/environment这个文件来初始化环境变量,另外env_check和env_keep选项也可以控制环境变量的保留,类似一个白名单的作用
  2. env_reset关闭时,没有被env_check和env_delete过滤掉的环境变量都会保留,类似一个黑名单的作用
  3. 用root用户执行sudo -V时,可以查看sudo命令允许和拒绝的环境变量设置
  4.  env_file选项可以设置一个初始化环境变量的文件

先用sudo -V看一看,记得要用root用户,由于这个输出很长,我们过滤一下和PATH有关的信息,可以看到PATH被强制修改

 

另外,根据这个网页https://www.sudo.ws/alerts/env_add.html所说,env_reset关闭对于1.8.5版本以上的sudo命令来说是无效的,所以就不再尝试了

方法六 修改/etc/environment文件(失败)

就算成功了这个方法也不是十分稳妥,/etc/environment这种文件还是不要改

在里面添加PATH是没有用的,其他变量倒是有用,估计用/etc/environment初始化之后还做了别的操作

在/etc/environment文件里添加两行

export PATH=$PATH:/usr/local/bin
export test=hello
printenv test
sudo printenv test
printenv PATH
sudo printenv PATH

由上可见,其他的环境变量还是可以通过/etc/environment传递给sudo的 

这个跟env_reset选项似乎无关,都可以起作用

方法七 sudo命令参数(失败)

继续阅读sudo的手册,看到这段关于环境变量的描述

也就是说可以把环境变量作为一个变量传递给sudo

另外-E选项也可以保留当前的环境变量

但是试下来,下面两个命令都是失败的= =

sudo -E pip
sudo $PATH=PATH pip

https://unix.stackexchange.com/questions/83191/how-to-make-sudo-preserve-path有人说像第二条那种命令形式,只会把PATH传递给sudo本身,而不会在这个目录查找命令

方法八 env命令(成功)

env命令可以在定义的环境中执行指令

sudo env PATH=$PATH pip

如果为了方便,可以设置别名

alias sudo="sudo env PATH=$PATH"

猜你喜欢

转载自blog.csdn.net/jiangxuege/article/details/82592258
今日推荐