2016
Nov
17

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",设定如下:

/etc/sudoers
  1. Defaults env_reset
  2.  
  3. Defaults env_keep = "COLORS DISPLAY HOSTNAME HISTSIZE INPUTRC KDEDIR LS_COLORS"
  4. 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 的环境变数,再执行后序的工作。



回應 (Leave a comment)