ubuntu sudo执行shell脚本环境变量失效
问题描述
普通用户下,设置并export一个变量,然后利用sudo执行echo命令,能得到变量的值,但是如果把echo命令写入脚本,然后再sudo执行脚本,就找不到变量,未能获取到值,如题情况如下:
1 | $ cat tesh.sh |
原因
sudo运行时,会默认重置环境变量为安全的环境变量,也即,但前面设置的变量都会失效,只有少数配置文件中指定的环境变量能保存下来。
sudo的配置文件是 /etc/sudoers 需要root权限才能读取:
1 | $ sudo sed ‘/^#/d;/^$/d’ /etc/sudoers |
不过可以直接通过sudo -l来查看sudo的限制:
1 | $ sudo -l |
注意看第一行的选项 Defaults env_reset 表示默认会将环境变量重置,这样你定义的变量在sudo环境就会失效,获取不到。
另外有的发行版还有一个Defaults env_keep=”“的选项,用于保留部分环境变量不被重置,需要保留的变量就写入双引号中。
为什么sudo echo $var能获取到变量值?
既然利用sudo执行会重置环境变量,那么为什么还能echo获取到相应的变量呢?
这是由于shell命令行的替换&重组功能,在输入命令,按下回车时,shell会先依据分隔符将命令行切割成字段,对每个字段查找有没有变量或命令替换,再替换完成后,重组成新的命令,再去执行。
所以,命令实际执行是:
1 | $ sudo echo $var # $var => aaa |
因此,sudo环境重置后,并不用去引用$var这个变量,而是直接echo aaa。
解决
sudo -E
简单来说,就是加上-E选项后,用户可以在sudo执行时保留当前用户已存在的环境变量,不会被sudo重置,另外,如果用户对于指定的环境变量没有权限,则会报错。
1 | $ sudo -E bash test.sh # 加上-E参数后就可以获取到变量 aaa |
2. 修改sudo配置文件
在内部测试机器中,安全性要求不高,总是需要加上-E参数来执行脚本,这个安全设定也不是很方便,可以通过visudo命令来修改配置为保留原有的环境变量,具体修改如下
1 | $sudo visudo |
Defaults !env_reset # 修改为不重置环境
3. 手动添加变量
手动在脚本中设置所需的变量,这样看起来比较麻烦,或者在执行sudo脚本前先将所需要的变量写入到要执行的脚本开头.
命令
对于自己安装的软件在sudo提示找不到的命令(没加sudo可以找到),在这个后面添加命令所在的路径
1 | secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin |
visudo编辑模式和退出
执行
1 | $sudo visudo |
找到如下授权,注释
1 | %admin ALL=(ALL) ALL |
修改为新的授权,意思是不需要密码执行
1 | %admin ALL=(ALL) NOPASSWD: ALL |
保存并退出:
保存
执行“Ctrl+O”*