我有一个需要以root身份运行的sh脚本,但它是由最终用户使用sudo运行的。当在sudo下运行时,如何获取用户主目录,而~/指向/root呢?
尽量避免使用 eval 函数,特别是在具有根权限时。
你可以这样做:
USER_HOME=$(getent passwd $SUDO_USER | cut -d: -f6)
更新:
这里解释了为什么要避免使用 eval。
~$SUDO_USER
。您可以使用以下方式使用 eval
:USER_HOME=$(eval echo ~${SUDO_USER})
echo ${USER_HOME}
eval
。请查看我的无需eval
的答案。 - Michał Šrajereval
。~
是 shell 扩展,因此 echo ~user
就足够了。 - Craigeval
,因为用户存储在一个变量中。 - dogbaneSUDO_USER='root; touch /tmp/AllYourBaseAreBelongToUs'
。 - Michał Šrajer$ sudo env |grep USER
USER=root
USERNAME=root
SUDO_USER=glglgl
因此,您可以访问$SUDO_USER
并使用getent passwd $SUDO_USER | cut -d: -f6
来询问系统的主目录。
尝试访问环境变量 $SUDO_USER
除非我误解了问题,当用户使用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)。$HOME
会发生变化。然而,$SUDO_USER
将显示实际用户。 - Martin Braun$HOME
会发生变化。然而,$SUDO_USER
可以显示实际的用户。 - undefined你可以使用Hai的不完整答案来非常简单地构建用户的主目录。他和其他人正确地指出,您可以在sudo shell中获取原始用户。您可以使用它来将主目录构建到一个名为user_home(或任何您喜欢的名称)的新变量中:
#user_home="/home/${$SUDO_USER}";
对于 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
命令不会被执行。
eval
不安全,因为它会在参数展开后执行结果字符串。例如FOO="bob; ls"; eval "echo $FOO"
只会输出一个单词:"bob",然后执行了ls
命令。现在把ls
替换成更危险的命令。 - chepnerUSER_HOME=$(getent passwd ${SUDO_USER:-$USER} | cut -d: -f6)
。 - Chris Watts