问题
在 bash 脚本中,我使用命令...
sudo -u node bash
..从 root 切换到非 sudo 用户,但失败了。
上下文
我正在provision.sh
为 Vagrant 编写一个脚本,用于设置一个运行 Ubuntu 16.04.3 的服务器,该服务器包含使用 Meteor 1.6 交付应用程序所需的所有软件包。
nvm
一个必需的步骤是以非 root 用户身份安装。nvm
安装后,您需要注销并重新登录才能激活nvm
。因此,我创建了一个名为 的非 sudo 用户meteor
,并希望在下载和安装 时切换到该用户nvm
。
随后,我想切换回root
并立即以 身份登录meteor
,以便开始使用nvm
安装 Node.js。
您将在下面找到一个注释很深的脚本。每次我调用时,Vagrant 都会运行此脚本vagrant reload --provision
。
我应该使用什么命令来代替sudo -u node bash
?
echo "# whoami" && whoami && echo "^^^^ root expected"
echo "As root, create non-sudo user meteor:"
pass=$(perl -e 'print crypt($ARGV[0], "password")' $password)
useradd -m -p $pass meteor
echo "User meteor created. ls -al /home/meteor:"
ls -al /home/meteor
echo "Install curl as root:"
apt-get install -y curl
echo "Trying sudo -u meteor bash"
sudo -u meteor bash #### THIS IS THE LINE THAT FAILS ###
echo "$ whoami" && whoami && echo "^^^^^^ meteor expected"
curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.33.6/install.sh | bash
echo "ls -al /home/meteor/.nvm # should be populated"
ls -al /home/meteor/.nvm
echo "ls -al /root/.nvm # should not exist"
ls -al /root/.nvm
echo "command -v nvm will fail silently until we log out and back in again"
#command -v nvm
exit
#### Because the script is still running as root, it halts here ####
echo "# whoami" && whoami && echo "^^^^ should be root"
sudo -u meteor bash
echo "$ whoami" && whoami && echo "^^^^^^ should be meteor"
echo "command -v nvm should work now"
command -v nvm
答案1
如果你使用 root 权限启动脚本,但需要以特定的非 root 用户身份运行某些命令,你可以使用sudo
以下-u
选项运行单个命令,例如
sudo -u USERNAME whoami # outputs USERNAME's user name
或者启动一个子 shell 并在其中运行命令,例如:
sudo -u USERNAME bash -c 'whoami;echo $USER' # outputs USERNAME's user name twice
脚本中的这一行实际上并没有失败,你只是bash
以用户身份运行meteor
,并且 asbash
没有任何操作,它只是退出,原始 root shell 运行脚本的其余部分。你真正想要做的(我想)是:
…
echo "Trying sudo -u meteor bash"
sudo -u meteor bash -c '\
echo "$ whoami" && whoami && echo "^^^^^^ meteor expected"
curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.33.6/install.sh |\
bash
'
echo "ls -al /home/meteor/.nvm # should be populated"
…
实现相同目的的另一种方法是这里的文件:
…
echo "Trying sudo -u meteor bash"
sudo -u meteor bash <<EOF
echo "$ whoami" && whoami && echo "^^^^^^ meteor expected"
curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.33.6/install.sh |\
bash
EOF
echo "ls -al /home/meteor/.nvm # should be populated"
…
答案2
如果你在容器环境中,戈苏项目可能会引起人们的兴趣。它旨在解决 su 和 sudo 具有非常奇怪且经常令人讨厌的 TTY 和信号转发行为的问题。
gosu 项目的 README.md 中提到了一些不错的替代方案:
chroot --userspec
可能已经安装su-exec
https://github.com/ncopa/su-execsetpriv
来自 (Debian) util-linux 包https://manpages.debian.org/buster/util-linux/setpriv.1.en.html
答案3
#! /bin/bash
# (GPL3+) Alberto Salvia Novella (es20490446e)
execute () {
function="${1}"
command="${2}"
error=$(eval "${command}" 2>&1 >"/dev/null")
if [ ${?} -ne 0 ]; then
echo "${function}: $error"
exit 1
fi
}
executeAsNonAdmin () {
function="${1}"
command="${2}"
eval setPasswordAsker="SUDO_ASKPASS=/usr/libexec/openssh/ssh-askpass"
run="runuser ${SUDO_USER} --session-command=\"${setPasswordAsker}\" --command=\"${command}\""
execute "${function}" "${run}"
}
executeAsNonAdmin "" "${@}"