如何在以 root 权限启动的脚本中以非 root 用户身份运行命令?

如何在以 root 权限启动的脚本中以非 root 用户身份运行命令?

问题
在 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 中提到了一些不错的替代方案:

  1. chroot --userspec可能已经安装
  2. su-exec https://github.com/ncopa/su-exec
  3. setpriv来自 (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 "" "${@}"

相关内容