How to Run Commands as Non-Root User in Root-Permission Script

bashscriptssudo

The problem
In a bash script, I am using the command…

sudo -u node bash

.. to switch from root to a non-sudo user, and this is failing.

The context
I am writing a provision.sh script for Vagrant, to set up a server running Ubuntu 16.04.3 with all the packages required to deliver an app with Meteor 1.6.

One required step is to install nvm as a non-root user. After nvm is installed, you need to log out and log back in again in order to activate nvm. I therefore create a non-sudo user named meteor, and want to switch to that when I download and install nvm.

Subsequently, I want to switch back to being root and log in gain immediately as meteor, in order to start using nvm to install Node.js.

You'll find a heavily commented script below. Vagrant runs this script each time I call vagrant reload --provision.

What command should I be using instead of 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

Best Answer

If you start your script with root permissions but need to run certain commands as a specific non-root user you can use sudo with the -u option to either run a single command with e.g.

sudo -u USERNAME whoami # outputs USERNAME's user name

or start a subshell and run your commands in it, e.g.:

sudo -u USERNAME bash -c 'whoami;echo $USER' # outputs USERNAME's user name twice

The line in your script doesn't fail actually, you just run only bash as user meteor, and as bash has nothing to do it just exits and the original root shell runs the rest of the script. What you actually want to do (I suppose) is:

…
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"
…

Another way to achieve the same is a here document:

…
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"
…
Related Question