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
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.or start a subshell and run your commands in it, e.g.:
The line in your script doesn't fail actually, you just run only
bash
as usermeteor
, and asbash
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:Another way to achieve the same is a here document:
If you're in a container environment, the gosu project could be of interest. It is intended to solve the issue that su and sudo have very strange and often annoying TTY and signal-forwarding behavior.
A few nice alternatives are mentioned in the gosu project's README.md:
chroot --userspec
may already be installedsu-exec
https://github.com/ncopa/su-execsetpriv
from the (Debian) util-linux package https://manpages.debian.org/buster/util-linux/setpriv.1.en.html