Linux 下 sudo $HOME 改变问题解决

from–https://little-star.love/posts/d3a9d9ff/

 

在 RedHat 与 Debian 下使用 sudo 执行脚本,变量 $HOME 不一致问题探讨

背景

由于项目自动化部署需求,脚本需要适配当前所有主流的 Linux 操作系统。脚本中某些操作需要使用 sudo 权限执行,但是又有一部分内容需要在当前用户 $HOME 目录下执行。脚本是在 Arch Linux 下开发的,之前使用的环境是基于 Debian 的银河麒麟。脚本运行无异常,之前也没在 CentOS 上测试过非 root 运行,也就没发现这个问题。

现在使用普通用户运行脚本后会把原本应该写入到当前用户的 HOME 目录下的文件写入到 root 用户的 HOME 目录下,这就很难受了。

测试

测试环境:

  • CentOS: 7.5.1804
  • Ubuntu: 16.04

创建测试用户 test 并通过 visudo 命令添加如下内容

/etc/sudoers
1
test    ALL=(ALL)       ALL

仅添加如上内容后,su - test 切换到测试用户

命令行测试

  • CentOS 下通过命令行打印 HOME
    shell
    1
    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
    shell
    1
    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 执行脚本查看结果。脚本内容如下:

sample.sh
1
2
3
4
5
6
7
#!/usr/bin/env bash

set -x

printenv HOME

echo $HOME
  • CentOS 下通过脚本打印 HOME
    shell
    1
    2
    3
    4
    5
    [test@centos7 ~]$ sudo bash sample.sh
    + printenv HOME
    /root
    + echo /root
    /root
  • Ubuntu 下通过脚本打印 HOME
    shell
    1
    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 文件即可

  1. 注释掉 Defaults always_set_home
  2. 添加 Defaults env_keep += "HOME"
  3. 保存并退出
  4. 新建一个终端,再次执行 sudo bash sample.sh 测试,可以看到已经能够在 sudo 下获取到当前用户的 HOME 目录
    shell
    1
    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" 是所有用户全局生效的,如果服务器上有多个用户,且该需求仅个别用户需要使用到建议使用如下修改方式:

/etc/sudoers
1
2
3
4
5
6
...
# Defaults    always_set_home
...
Defaults         env_keep -= "HOME"
Defaults:test    env_keep += "HOME"
...

限制仅 test 用户在 sudo 时替换目标用户的 HOME 值

参考文章:

上一篇
下一篇