Bash, Befehl ausführen, nachdem eine neue Shell aufgerufen wurde

12

Ich versuche ein Skript wie dieses zu erstellen:

#!/bin/bash
sudo -s
something...

Wenn ich es ausführe, erhalte ich eine neue Shell, die jedoch somethingnur ausgeführt wird, wenn ich die von erstellte Shell verlasse sudo -sund nicht darin.

Irgendeine Hilfe?

Matteo
quelle

Antworten:

7

Das Problem ist, dass sudo -sohne Argument eine interaktive Shell für root geöffnet wird.

Wenn Sie nur einen einzelnen Befehl mit ausführen möchten sudo -s, können Sie einfach Folgendes tun:

sudo -s command

Zum Beispiel :

$ sudo -s whoami
root

Oder Sie können hier Zeichenfolgen verwenden:

$ sudo -s <<<'whoami'
root

Wenn Sie mehrere Befehle haben, können Sie hier doc verwenden:

$ sudo -s <<'EOF'
> whoami
> hostname
> EOF
root
something--
heemayl
quelle
1
Es ist nicht gut zu verwenden, sudo -snur für den Fall, dass der rootBenutzer die (eher schlechte) Idee hatte, seine Shell zu ändern. Dies sollte wirklich sein, sudo shwas explizit angibt, welche Shell verwendet werden soll.
Michael Le Barbier Grünewald
7

Eine andere Möglichkeit wäre, einen vollständigen Bash-Befehl an Folgendes zu übergeben sudo:

#!/bin/bash
sudo bash -c 'command1; command2; command3;'

Ein besserer Weg wäre jedoch, stattdessen das Skript mit zu starten sudo. Es ist keine sehr gute Idee, sudodas Skript zu verwenden. Es ist weitaus besser, das gesamte Skript mit Root-Rechten auszuführen ( sudo script.sh). Bei Bedarf können Sie sudoBerechtigungen für bestimmte Befehle löschen. Beispielsweise:

#!/usr/bin/env bash
whoami
echo $HOME
sudo -u terdon whoami  ## drop privileges for specific command.

Das Ausführen des obigen Skripts gibt Folgendes zurück:

$ sudo ~/scripts/a.sh
root
/root
terdon
terdon
quelle
3

Die Bourne-Shell verfügt über ein -cFlag, mit dem Sie ein beliebiges Skript an die Shell übergeben können, damit Sie so etwas schreiben können

sudo sh -c 'something'

Dies ist jedoch nur für die einfachsten Befehle nützlich, da es sehr umständlich ist, das Skript korrekt zu zitieren, und die Unannehmlichkeiten noch größer sind, wenn Sie den Befehl über ssh an einen Remote-Server senden, da das Argument-Skript zweimal nebeneinander analysiert wird Senden des Skripts und einmal auf der Seite, auf der das Skript ausgeführt wird.

Wenn somethinges sich um ein komplexes Skript handelt oder über eine SSH- Zeile übergeben werden muss, ist es üblich, eine Funktion zu schreiben, prepare_something_scriptderen Aufgabe es ist, das Skript 'etwas' auf stdout zu schreiben . In ihrer einfachsten Form kann diese Funktion ein Here-Dokument verwenden, um ihre Ausgabe zu generieren:

prepare_something_script()
{
  cat <<EOF
something
EOF
}

Das von erstellte Skript prepare_something_scriptkann dann lokal mit den von sudo gewährten Berechtigungen wie folgt ausgeführt werden:

prepare_something_script | sudo sh

In dem Szenario, in dem das Skript mit von sudo gewährten Berechtigungen remote ausgeführt werden muss, ist es üblich, das Skript in Base 64 zu codieren, um eine Umleitung der Standardeingabe von ssh wie folgt zu vermeiden :

something64=$(prepare_something_script | base64)
ssh usesr@remote-host "echo ${something64} | base64 --decode | sudo sh"

Wenn Sie diesen Code in einer Funktion verwenden, vergessen Sie nicht , die markieren something64 Variable als lokal . Einige Implementierungen von base64 bieten ein -dFlag zum Dekodieren, das weniger gut unterstützt wird als die ausführliche --decodeVariante. Bei einigen Implementierungen muss -w 0dem Codierungsbefehl ein hinzugefügt werden , um falsche Zeilenumbrüche zu vermeiden.

Michael Le Barbier Grünewald
quelle
0

Sie müssen den Befehl vor sudo -s anstatt in der nächsten Zeile hinzufügen.

sudo -s something...
Soumen
quelle