Linux 環境裡有個 sudo 的指令,這個指令主要功能是用來提高 User 權限,讓 User 可以執行 root 才能做的事,當我們要用 vim 修改 root 的檔案時,會使用 "sudo vim xxx.log" ,這時原有的 vim syntax 與 bindkey 都會消失,又或者是我們要執行一個軟體 , sudo sh /root/mysqld.sh ,結果卻收到路徑不正確的訊息,不加 sudo 就沒有這些問題,一般來說快速的解法是加上 "sudo -E" , "-E" 代表我要系統載入 User 的環境變數。
有一天公司需要做系統的 Migration ,要求將自動化測試的程式碼搬到米國人新建的環境,先不論這個工作會浪費多少生命,我們平常每天跑的指令如 "node_modules/.bin/protractor protractor.conf
",在新環境中抓不到登入帳號的密碼,原來新環境使用的身分不是 root ,所以沒辦法取得密碼,很自然的我就加上 "sudo node_modules/.bin/protractor protractor.conf
",加完之後,成功的抓到登入密碼了,但是原本的測試只會執行 10 個 Test Cases ,加了 sudo 之後卻自動測試了超過一百個 Test Cases ,找了很久,才發現是環境變數不見了,本來有個環境變數 "group=captcha_api" ,少了這個環境變數 ,測試工具就會執行目錄下的所有 Test Cases,解決方式也很簡單,我直接把環境變數再重新 export 一次給 root 就搞定了 :
sudo bash -c "export group=captcha_api && node_modules/.bin/protractor protractor.conf"
/etc/sudoers 設定
sudo 到底是如何改變環境變數的呢,/etc/sudoers 這個檔案有三個跟環境變數有關的設定 "env_reset", "env_check", "env_keep", "env_delete",設定如下:
- Defaults env_reset
- Defaults env_keep = "COLORS DISPLAY HOSTNAME HISTSIZE INPUTRC KDEDIR LS_COLORS"
- Defaults env_keep += "MAIL PS1 PS2 QTDIR USERNAME LANG LC_ADDRESS LC_CTYPE"
env_reset
如果在 /etc/sudoers 中有設定 env_reset ,那麼當你執行 sudo 時,系統會清掉 User 的環境變數,只包含部分環境變數如: LOGNAME, SHELL, USER, USERNAME, SUDO_* ,我們的系統就是因為這個設定而移除了 group 這個環境變數。
env_keep
如果有打開 env_reset 功能,那麼 env_keep 才會有作用,它的功能是保留指定的 user 環境變數 ,例如我想保留 LC_CTYPE 這個環境變數,那麼我可以用 Defaults env_keep += "LC_TYPE"
。
env_check
env_check 是用來移除 user 環境變數用的,如果變數內容含有不安全的字元 '%' 或 '/' ,那麼系統就會移除該變數 ,很明顯的 env_check 跟系統安全性有關。
env_delete
env_delete 也是用來移除 user 環境變數用的,跟 env_check 有點像,但是 env_check 會去檢查變數的內容,而 env_delete 是不管變數內容直接刪除。
如果不管安全性,那麼直接關掉 env_reset 就可以解決環境變數不見的問題,只要在 /etc/sudoers 加上 Defaults !env_reset
。
另一個簡單的解決方式是加上 -E , sudo -E 可以要系統先載入 User 的環境變數,再執行後序的工作。