Wie führe ich Befehle als Nicht-Root-Benutzer in einem Skript aus, das mit Root-Berechtigungen gestartet wurde?

8

Das Problem
In einem Bash-Skript verwende ich den Befehl ...

sudo -u node bash

.., um von root zu einem Nicht-Sudo-Benutzer zu wechseln, und dies schlägt fehl.

Der Kontext
Ich schreibe ein provision.shSkript für Vagrant, um einen Server unter Ubuntu 16.04.3 mit allen Paketen einzurichten, die für die Bereitstellung einer App mit Meteor 1.6 erforderlich sind.

Ein erforderlicher Schritt ist die Installation nvmals Nicht-Root-Benutzer. Nach der nvmInstallation müssen Sie sich abmelden und erneut anmelden, um die Aktivierung zu aktivieren nvm. Ich erstelle daher einen Nicht-Sudo-Benutzer mit dem Namen meteorund möchte beim Herunterladen und Installieren darauf wechseln nvm.

Anschließend möchte ich wieder zu Sein wechseln rootund mich sofort als anmelden meteor, um mit nvmder Installation von Node.js zu beginnen.

Unten finden Sie ein stark kommentiertes Skript. Vagrant führt dieses Skript jedes Mal aus, wenn ich anrufe vagrant reload --provision.

Welchen Befehl soll ich anstelle verwenden 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
James Newton
quelle
Sie müssen die Teile in ein anderes Skript extrahieren und darauf sudo aufrufen oder jeden Befehl mit sudo aufrufen (in diesem Fall ist dies nur die Bash nach dem Curl). sudo -u meteor bashStartet einfach Bash als Meteor, es kann nicht einfach den Rest des Skripts übernehmen.
Muru
Verwandte, vielleicht ein Duplikat? Best Practices für die Verwendung von Sudo in einem Bash-Skript
Wjandrea

Antworten:

9

Wenn Sie Ihr Skript mit Root-Berechtigungen starten, aber bestimmte Befehle als bestimmter Nicht-Root-Benutzer ausführen müssen, können Sie sudomit der -uOption entweder einen einzelnen Befehl mit z

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

oder starten Sie eine Subshell und führen Sie Ihre Befehle darin aus, z.

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

Die Zeile in Ihrem Skript schlägt tatsächlich nicht fehl, Sie werden nur bashals Benutzer ausgeführt meteor, und da bashnichts zu tun ist, wird sie einfach beendet und die ursprüngliche Root-Shell führt den Rest des Skripts aus. Was Sie tatsächlich tun möchten (nehme ich an), ist:


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"

Ein anderer Weg, um dasselbe zu erreichen, ist ein Dokument hier :


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"
Dessert
quelle
0

Wenn Sie sich in einer Containerumgebung befinden, könnte das Gosu-Projekt von Interesse sein. Es soll das Problem lösen, dass su und sudo ein sehr seltsames und oft störendes TTY- und Signalweiterleitungsverhalten haben.

Einige nette Alternativen werden in der README.md des Gosu-Projekts erwähnt:

  1. chroot --userspec ist möglicherweise bereits installiert
  2. su-exec https://github.com/ncopa/su-exec
  3. setprivaus dem (Debian) util-linux-Paket https://manpages.debian.org/buster/util-linux/setpriv.1.en.html
Ed Randall
quelle
-1
#! /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 "" "${@}"
Alberto Salvia Novella
quelle