from–https://little-star.love/posts/d3a9d9ff/
背景
由于项目自动化部署需求,脚本需要适配当前所有主流的 Linux
操作系统。脚本中某些操作需要使用 sudo
权限执行,但是又有一部分内容需要在当前用户 $HOME
目录下执行。脚本是在 Arch Linux 下开发的,之前使用的环境是基于 Debian 的银河麒麟。脚本运行无异常,之前也没在 CentOS 上测试过非 root 运行,也就没发现这个问题。
现在使用普通用户运行脚本后会把原本应该写入到当前用户的 HOME
目录下的文件写入到 root
用户的 HOME
目录下,这就很难受了。
测试
测试环境:
- CentOS: 7.5.1804
- Ubuntu: 16.04
创建测试用户 test
并通过 visudo
命令添加如下内容
1 | test ALL=(ALL) ALL |
仅添加如上内容后,su - test
切换到测试用户
命令行测试
- CentOS 下通过命令行打印
HOME
shell1 2 3 4 5 6 7
[test@centos7 ~]$ printenv HOME /home/test [test@centos7 ~]$ echo $HOME /home/test [test@centos7 ~]$ sudo echo $HOME [sudo] password for test: /home/test
- Ubuntu 下通过命令行打印
HOME
shell1 2 3 4 5 6 7
test@ubuntu16:~$ printenv HOME /home/test test@ubuntu16:~$ echo $HOME /home/test test@ubuntu16:~$ sudo echo $HOME [sudo] password for test: /home/test
可以看到此时 CentOS 与 Ubuntu 下 echo
和 sudo echo
下均打印出了 env
下变量 HOME
的值,即当前用户的 HOME 目录。
脚本测试
把我们在命令行测试的命令写入到脚本 sample.sh
中,通过 sudo
执行脚本查看结果。脚本内容如下:
1 2 3 4 5 6 7 | #!/usr/bin/env bash
set -x
printenv HOME
echo $HOME |
- CentOS 下通过脚本打印
HOME
shell1 2 3 4 5
[test@centos7 ~]$ sudo bash sample.sh + printenv HOME /root + echo /root /root
- Ubuntu 下通过脚本打印
HOME
shell1 2 3 4 5
test@ubuntu16:~$ sudo bash sample.sh + printenv HOME /home/test + echo /home/test /home/test
这儿我们就可以看出差异了,在 CentOS
上打印出来的是 root 的 HOME
目录,但是在 Ubuntu
下却是当前执行 sudo
命令的用户的 HOME
目录🤔
原因
根据查阅资料得知,不同的操作系统、不同的 sudo
版本(sudo -V
可查询)在编译时所带的参数不一样,编译出来的二进制文件中默认值也不一样。 但是,也不是不能改,我们可以通过编辑 /etc/sudoers
文件来做对应的调整(通过 root
用户直接运行 visudo
命名即可编辑)。
相关配置项:
env_keep
:确定保留哪些环境变量。使用Defaults env_keep += "HOME"
保留调用者的HOME
环境变量或Defaults env_keep -= "HOME"
将其删除(和目标用户的主目录替换)。env_reset
:确定是否完全重置环境变量。重置环境变量对于允许运行特定命令的规则通常是必需的,但是对于仍然允许运行任意命令的规则没有直接的安全优势。always_set_home
:如果已设置,则HOME
即使env_reset
被禁用或包含HOME
在env_keep
列表中而被保留,也会导致被覆盖。如果HOME
仍未保留,则此选项无效。set_home
:类似于always_set_home
,但仅适用于sudo -s
,不适sudo
用于使用显式命令进行调用的情况。
修改 sudoers
接下来我们测试修改 CentOS 上 sudoers
配置,使用 visudo
直接编辑 sudoers 文件即可
- 注释掉
Defaults always_set_home
- 添加
Defaults env_keep += "HOME"
- 保存并退出
- 新建一个终端,再次执行
sudo bash sample.sh
测试,可以看到已经能够在sudo
下获取到当前用户的HOME
目录shell1 2 3 4 5 6
[test@centos7 ~]$ sudo bash sample.sh [sudo] password for test: + printenv HOME /home/test + echo /home/test /home/test
需要注意的是,设置 Defaults env_keep += "HOME"
是所有用户全局生效的,如果服务器上有多个用户,且该需求仅个别用户需要使用到建议使用如下修改方式:
1 2 3 4 5 6 | ...
# Defaults always_set_home
...
Defaults env_keep -= "HOME"
Defaults:test env_keep += "HOME"
... |
限制仅 test
用户在 sudo
时替换目标用户的 HOME
值
参考文章: