1. 程式人生 > >普通使用者可以執行,sudo提示command not found的問題分析——修改sudo命令的環境變數

普通使用者可以執行,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"