以root身份运行脚本时,如何获取用户的主目录

36

我有一个需要以root身份运行的sh脚本,但它是由最终用户使用sudo运行的。当在sudo下运行时,如何获取用户主目录,而~/指向/root呢?

7个回答

51

尽量避免使用 eval 函数,特别是在具有根权限时。

你可以这样做:

USER_HOME=$(getent passwd $SUDO_USER | cut -d: -f6)

更新:

这里解释了为什么要避免使用 eval。


我撤销了原始帖子。建议的简化是错误的。 - Michał Šrajer
@downvoter:如果您要点踩,请在评论中说明您认为哪里有问题。否则这是没有建设性的。谢谢。 - Michał Šrajer
我猜想“踩”是因为没有解释如何避免使用 eval 函数的原因?现在我很想知道避免使用它的原因! - user1311766
7
eval 不安全,因为它会在参数展开后执行结果字符串。例如 FOO="bob; ls"; eval "echo $FOO" 只会输出一个单词:"bob",然后执行了 ls 命令。现在把 ls 替换成更危险的命令。 - chepner
3
如果您希望始终如一地运行,无论用户是否在sudo状态下,您可以使用USER_HOME=$(getent passwd ${SUDO_USER:-$USER} | cut -d: -f6) - Chris Watts

31
用户的主目录将会是 ~$SUDO_USER。您可以使用以下方式使用 eval
USER_HOME=$(eval echo ~${SUDO_USER})
echo ${USER_HOME}

2
尽量避免使用eval。请查看我的无需eval的答案。 - Michał Šrajer
这里不需要使用 eval~ 是 shell 扩展,因此 echo ~user 就足够了。 - Craig
2
是的,你需要使用 eval,因为用户存储在一个变量中。 - dogbane
在运行此代码之前,请尝试 SUDO_USER='root; touch /tmp/AllYourBaseAreBelongToUs' - Michał Šrajer
@MichałŠrajer Eval通常被认为是一种代码异味,但在这种情况下应该是安全的 - sudo应该将SUDO_USER设置为安全值(合法用户名),如果某些东西使用已破解的sudo或者没有sudo但是带有一个被攻击的环境运行,那么"你的整个程序都属于黑客了"。 - Petr Skocik

9
$ sudo env |grep USER
USER=root
USERNAME=root
SUDO_USER=glglgl

因此,您可以访问$SUDO_USER并使用getent passwd $SUDO_USER | cut -d: -f6来询问系统的主目录。


4

尝试访问环境变量 $SUDO_USER


4
好的,我会尽力进行翻译,请提供需要翻译的内容。 - l0b0

2

除非我误解了问题,当用户使用sudo运行脚本时,$HOME环境变量不会改变。为了测试,我创建了这个脚本:

#!/bin/bash
#sudo_user.sh
env | grep -e USER -e HOME

...然后运行它:

sudo ./sudo_user.sh

输出:

USER=root
HOME=/home/haiv
USERNAME=root
SUDO_USER=haiv

输出结果告诉我,$HOME 仍然指向用户的主目录(在这种情况下是 /home/haiv)。

这在Debian服务器上是不正确的,$HOME会发生变化。然而,$SUDO_USER将显示实际用户。 - Martin Braun
在Debian服务器上,这是不正确的,$HOME会发生变化。然而,$SUDO_USER可以显示实际的用户。 - undefined

0

你可以使用Hai的不完整答案来非常简单地构建用户的主目录。他和其他人正确地指出,您可以在sudo shell中获取原始用户。您可以使用它来将主目录构建到一个名为user_home(或任何您喜欢的名称)的新变量中:

#user_home="/home/${$SUDO_USER}";

如果用户的主目录不是标准位置怎么办?获取实际的主目录会比猜测它在 /home 下更明智吧? - Tim Stewart

0

对于 eval 解决方案进行了一点改进。

在将用户名变量发送到 eval 之前,先通过用户存在性测试它,这样如果有任意代码,它就无法通过检查。

#? Description:
#?   Get the user's home directory by username regardless of whether is running with `sudo`.
#?   The username is checked, it must exist, to avoid the arbitrary code execution of `eval`.
#?   The returned home directory's existence is not checked.
#?
#? Usage:
#?   @home USERNAME
function home () {
    if id "$1" >/dev/null 2>&1; then
        eval echo "~$1"
    else
        return 255
    fi
}

在 macOS 上运行代码:

$ home root

输出:

/var/root

如果您使用类似以下的方式运行它:
home 'root ; ls'

它不会返回任何内容,而是会出现错误,ls 命令不会被执行。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接