Wie führe ich einen 'sudo'-Befehl in einem Skript aus?

84

Um einen Patch manuell auszuführen, muss ich diesen Befehl eingeben

sudo ./playback_delete_data_patch.sh 09_delete_old_data_p.sql  

Es gibt ein Leerzeichen kurz vor dem 09:

sudo ./playback_delete_data_patch.sh [space] 09_delete_old_data_p.sql

Wie kann ich das in einem Skript ausführen?

Es gibt auch mehrere andere Befehle, aber dieser gibt Probleme.

user251948
quelle
2
Gib es einfach in das Skript ein, was ist das Problem?
Lie Ryan
6
@LieRyan - das sudo Passwort - das Skript kann nicht vollständig ausgeführt werden, wenn niemand da ist, um es einzugeben.
Wilf
Mein System führt sie einfach ohne Aufforderung aus. Ubuntu 16.04 im Oktober 2017. Sie haben Ihr sudoersSetup durcheinander gebracht . Keine große Sache. Es muss nur behoben werden.
SDsolar
1
@ SDsolar Ihr System ist dasjenige, das durcheinander gebracht wurde. Es ist eine geringfügige Sicherheitslücke, nicht zur Eingabe des Kennworts aufzufordern (macht Benutzer anfälliger für bestimmte Arten von Social-Engineering-Angriffen).
wizzwizz4

Antworten:

107

Es ist selten eine gute Idee, sudoInsider-Skripte zu haben . Entfernen Sie stattdessen das sudoaus dem Skript und führen Sie das Skript selbst aus mit sudo:

sudo myscript.sh

Auf diese Weise werden alle Befehle im Skript mit Root-Rechten ausgeführt, und Sie müssen das Kennwort beim Starten des Skripts nur einmal eingeben. Wenn Sie einen bestimmten Befehl innerhalb des Skripts benötigen, um ohne sudoBerechtigungen ausgeführt zu werden, können Sie ihn als regulärer Benutzer mit ausführen (danke Lie Ryan ):

sudo -u username command 

Das Leerzeichen ist irrelevant, es sollte nichts beeinflussen, es gibt immer ein Leerzeichen zwischen einem Befehl und seinen Argumenten.

terdon
quelle
30
Möglicherweise enthält das Skript Befehle, für die das Root-Privileg nicht erforderlich ist. Sie können das Root-Privileg für diese Befehle vorübergehend löschen, indem Sie sudo -u username
Lie Ryan
48
Viele Skripte, die ich schreibe, führen eine ganze Reihe von Benutzerinteraktionen und / oder Fehlerprüfungen durch. Dann muss ein Befehl am Ende - so etwas wie rsync - als root ausgeführt werden. Warum sollte ich das Ganze in die Höhe treiben und mich für viele Codezeilen öffnen, die schwerwiegende Fehler oder Schwachstellen beim Root-Zugriff enthalten könnten - insbesondere beim Debuggen -, wenn nur ein oder wenige Befehle diesen Zugriff erfordern?
Joe
2
@ Joe fair genug. Die "nie eine gute Idee" wurde in "selten" geändert.
terdon
10
@ Joe hat hier einen wirklich guten Punkt. Auch wenn man sagt, dass man das nicht tun soll , wäre es schön zu wissen, warum das so ist oder zumindest in welchem ​​Kontext ich das nicht tun sollte und warum
arainone
10
@terdon Du hörst nicht zu. Ich weiß, wenn Sie das Skript als root ausführen , werden Sie niemals zur Eingabe von sudo aufgefordert. Ich vergleiche das damit, dass das Skript nicht als root ausgeführt wird und stattdessen explizite sudoAufrufe in das Skript eingefügt werden, da das Erhöhen des gesamten Skripts zum root eine schreckliche Idee sein kann, wenn es nur eine Handvoll eingeschränkter Aktionen gibt, die root benötigen. In diesem Zusammenhang habe ich speziell auf Ihren Kommentar geantwortet: "Vor allem, weil Sie das Skript nicht automatisch ausführen können, da Sie das Kennwort jedes Mal eingeben müssen, wenn Sie dazu aufgefordert werden."
BeeOnRope
41

Sie könnten möglicherweise die sudoersDatei ändern .

Rennen sudo visudo.

Fügen Sie einen Eintrag für Ihren Benutzernamen und das Skript hinzu, das Sie ausführen möchten, ohne nach einem Kennwort gefragt zu werden.

username ALL=(ALL) NOPASSWD: /path/to/script
Klaus-Dieter Warzecha
quelle
2
Hat bei mir nicht funktioniert, aber danke, gut zu wissen, dass es das gibt. Vielleicht habe ich die Syntax falsch verstanden.
Chris K
5
Nicht sicher, ob jemand darauf hingewiesen hat, aber Sie müssen alle Anmeldesitzungen dieses Benutzers beenden, nachdem Sie die sudoersDatei bearbeitet haben .
Escape-llc
1
Nur um dies zu verdeutlichen, ist es nicht das Skript, das die Zeile "sudo ./playback_delete_data_patch.sh 09_delete_old_data_p.sql" enthält, das in der sudoers-Datei angegeben werden sollte, sondern das Playback_delete_data_patch.sh-Skript oder einen beliebigen anderen Befehl, den Sie für diesen Benutzer und / oder dessen Benutzer benötigen Skripte, um sudo ohne Angabe eines Passworts durchlaufen zu können.
MttJocy
19

Sie könnten versuchen, etwas wie:

echo "PASSWORD" | sudo -S ./playback_delete_data_patch.sh 09_delete_old_data_p.sql

Dies ist nicht die sicherste Vorgehensweise, da Sie ein Sudoer-Kennwort im Nur-Text-Format schreiben. Um die Sicherheit zu erhöhen, können Sie eine Variable erstellen und das sudo-Passwort in die Variable einlesen. Anschließend können Sie den Befehl wie folgt ausführen:

echo $PASSWORD | sudo -S ./playback_delete_data_patch.sh 09_delete_old_data_p.sql

Wenn Sie nichts dagegen haben, dass alle Befehle als root ausgeführt werden, können Sie Ihr Skript einfach mit ausführen sudo, wie zuvor vorgeschlagen.

sudo ./myscript
Jibbers
quelle
Passwort sicher in Variable einlesen:read -s PASSWORD
Tobias Uhmann
10

Diese Antwort ähnelt der Antwort von Terdon . Ich würde auch vorschlagen, das Hauptskript mit sudoauszuführen, damit das Skript ausgeführt werden kann, ohne während der Ausführung nach dem Kennwort des Benutzers fragen zu müssen.

Wenn Sie jedoch Root-Berechtigungen für einige Befehle löschen und diese als der tatsächliche Benutzer ausführen möchten, mit dem der Befehl aufgerufen wurde sudo, können Sie überprüfen, ob die $SUDO_USERVariable den ursprünglichen Benutzer ermittelt hat.

Dies ist ein Beispielskript, wie Sie dies erreichen können:

#!/bin/bash

# ref: https://askubuntu.com/a/30157/8698
if ! [ $(id -u) = 0 ]; then
   echo "The script need to be run as root." >&2
   exit 1
fi

if [ $SUDO_USER ]; then
    real_user=$SUDO_USER
else
    real_user=$(whoami)
fi

# Commands that you don't want running as root would be invoked
# with: sudo -u $real_user
# So they will be run as the user who invoked the sudo command
# Keep in mind if the user is using a root shell (they're logged in as root),
# then $real_user is actually root
# sudo -u $real_user non-root-command

# Commands that need to be ran with root would be invoked without sudo
# root-command
Dan
quelle
4

Es gibt tatsächlich einen viel einfacheren Weg, dies zu tun. Aus Gründen der Portabilität ist dies meine Implementierung, Sie können sie jedoch jederzeit an Ihre Anforderungen anpassen.

Geben Sie Ihr sudo-Passwort als Parameter ein, wenn Sie das Skript starten, erfassen Sie es und wiederholen Sie es mit jedem Befehl, der Sie zur Eingabe des sudo-Passworts auffordert.

#!/bin/bash

PW=$1
echo $PW | ./playback_delete_data_patch.sh 09_delete_old_data_p.sql  
./command_wo_sudo.sh <param>
echo $PW | ./other_command_requires_sudo.sh <param>

Sie können eine Eingabeaufforderung hinzufügen und wie folgt erfassen, nachdem das Skript gestartet wurde:

echo "enter the sudo password, please"
read PW

Aber wenn jemand anderes überwacht, was auf dem Knoten läuft; hat Zugriff auf die von ihm erstellten Protokolle; oder prüft nur nach dem Zufallsprinzip, wann Sie einen Test durchführen, der die Sicherheit gefährden könnte.

Dies funktioniert auch bei der Ausführung von Befehlen / Skripten, für deren Fortsetzung ein Ja erforderlich ist:

echo $PW | yes | ./install.sh

Das Echo reagiert auf eine Eingabeaufforderung, sodass Sie alles verwenden können, was Sie benötigen, wenn Sie andere Skripts ausführen, die nacheinander nach dem Fortschritt fragen. Stellen Sie sicher, dass Sie diese Reihenfolge kennen, da sonst schlimme Dinge passieren können.

csworenx
quelle
Das ist so viel eleganter und einfacher, ich bin froh, dass ich den ganzen Weg nach unten gescrollt habe! BEARBEITEN: Warten Sie, dies wird das Passwort zu meinem Terminal-Verlauf hinzufügen
Job
1
So fragen Sie nach Benutzername / Passwort mit read: ryanstutorials.net/bash-scripting-tutorial/bash-input.php Das sollte dieses Problem vermeiden
Job
3
#!/bin/bash
# this declares that current user is a sudoer
sudo tee /etc/sudoers.d/$USER <<END
END

# write the content of your script here
sudo npm install hexo-cli -g
mkdir Untitled
sudo apt-get install python

# then to remove the sudo access from the current user
sudo /bin/rm /etc/sudoers.d/$USER
sudo -k
Sanyam Jain
quelle
0

Sie können versuchen, den Benutzer, der das Skript ausführt, zur sudoers-Datei hinzuzufügen:

#give permissions to the file
sudo chmod 700 /etc/sudoers.d/useradm

sudo visudo /etc/sudoers.d/useradm

#add the following text, changing "user" but your desired user
user ALL=(ALL)NOPASSWD:ALL

#return the right permissions to the file
sudo chmod 440 /etc/sudoers.d/useradm
evinhas
quelle
Im Allgemeinen ist dies eine schlechte Methode. Wenn Sie NOPASSWD-Sudo-Regeln hinzufügen möchten, insbesondere für Konten, auf denen Automatisierung ausgeführt wird, sollten Sie sie mindestens auf den genauen Befehl beschränken, der ausgeführt wird (und nicht auf ALL)
Christopher Hunter,