it-swarm.com.de

Führen Sie ein Shell-Skript in der aktuellen Shell mit Sudo-Berechtigung aus

Um ein Shell-Skript in der aktuellen Shell auszuführen, benötigen wir einen Punkt . oder einen source Befehl. Aber warum funktioniert es nicht mit einer Sudo-Erlaubnis?

Ich habe ein Skript mit Ausführungsberechtigung namens setup.sh. Wenn ich eine Periode benutze, bekomme ich Folgendes:

$ Sudo . ./setup.sh 
Sudo: .: command not found

Der Quellbefehl erzeugt auch einen ähnlichen Fehler. Verpasse ich etwas? Was muss ich tun, um das Skript mit Sudo-Berechtigung in derselben Shell auszuführen?

Danke im Voraus..

34
shar

Was Sie zu tun versuchen, ist unmöglich. Ihre aktuelle Shell läuft unter Ihrer regulären Benutzer-ID (d. h. ohne root würde Ihnen der Zugriff Sudo geben), und es gibt keine Möglichkeit, root-Zugriff zu gewähren. Sudo erstellt einen neuen * sub * -Prozess, der als root ausgeführt wird. Der Unterprozess kann nur ein reguläres Programm sein (z. B. führt Sudo cp ... das Programm cp in einem Root-Prozess aus) oder es kann sich um eine Root-Subshell handeln, aber kann nicht ist die aktuelle Shell.

(Dies ist sogar noch unmöglicher, da der Sudo-Befehl selbst als Unterprozess der aktuellen Shell ausgeführt wird - was bedeutet, dass es in gewissem Sinne bereits zu spät ist, um irgendetwas in der "aktuellen Shell" zu tun, weil das nicht der Fall ist es führt aus.)

25
Gordon Davisson

Ich bin mir nicht sicher, ob das irgendwelche Regeln verletzt 

Sudo bash script.sh

scheint für mich zu arbeiten. 

85
JaseC

Ich denke, Sie sind verwirrt über den Unterschied zwischen der Beschaffung und Ausführung eines Skripts.

Wenn Sie ein Skript ausführen, müssen Sie einen neuen Prozess erstellen und das Programm ausführen. Das Programm kann ein Shell-Skript oder ein beliebiges anderes Programm sein. Da es sich um einen Unterprozess handelt, wirken sich alle im Programm geänderten Umgebungsvariablen nicht auf die Shell aus.

Das Sourcing eines Skripts kann nur mit einem Bash-Skript verwendet werden (wenn Sie Bash ausführen). Es fügt die Befehle so ein, als ob Sie sie getan hätten. Dies ist nützlich, da ein Skript Umgebungsvariablen in der Shell ändern kann.


Das Ausführen eines Skripts ist einfach. Geben Sie einfach den Pfad zum Skript ein. . ist das aktuelle Verzeichnis. ./script.sh führt die Datei script.sh im aktuellen Verzeichnis aus. Wenn der Befehl eine einzelne Datei ist (z. B. script.sh), überprüft er alle Ordner in der PATH-Variablen, um das Skript zu finden. Beachten Sie, dass sich das aktuelle Verzeichnis nicht in PATH befindet. Daher können Sie keine Datei script.sh im aktuellen Verzeichnis ausführen, indem Sie script.sh ausführen. Sie müssen ./script.sh ausführen (es sei denn, das aktuelle Verzeichnis befindet sich in PATH. Sie können beispielsweise ls ausführen, während Sie sich in befinden der /bin dir).

Das Beschaffen eines Skripts verwendet den PFAD nicht, sondern sucht nur nach dem Pfad. Beachten Sie, dass source kein Programm ist. Andernfalls können Umgebungsvariablen in der aktuellen Shell nicht geändert werden. Es ist eigentlich ein bash-Befehl. Suchen Sie /bin und /usr/bin - dort finden Sie kein source-Programm. Um eine Datei script.sh im aktuellen Verzeichnis zu finden, verwenden Sie einfach source script.sh


Wie interagiert Sudo damit? Nun, Sudo nimmt ein Programm und führt es als root aus. Beispiel: Sudo ./script.sh führt script.sh in einem Unterprozess aus, läuft jedoch als root.

Was macht Sudo source ./script.sh jedoch? Denken Sie daran, dass source kein Programm ist (eher eine eingebaute Shell)? Sudo erwartet jedoch einen Programmnamen und sucht daher nach einem Programm mit dem Namen source. Es findet keine und schlägt fehl. Es ist nicht möglich, eine als root ausgeführte Datei zu erstellen, ohne einen neuen Unterprozess zu erstellen, da der Läufer eines Programms (in diesem Fall bash) nach dem Start nicht geändert werden kann.

Ich bin mir nicht sicher, was Sie eigentlich wollten, aber hoffentlich wird das für Sie klarer.


Hier ist ein konkretes Beispiel. Machen Sie die Datei script.sh in Ihrem aktuellen Verzeichnis mit dem Inhalt:

#!/bin/bash    
export NEW_VAR="hello"
whoami
echo "Some text"

Machen Sie es mit chmod +x script.sh ausführbar.

Nun beobachte was mit bash passiert:

> ./script.sh
david
Some text
> echo $NEW_VAR

> Sudo ./script.sh
root
Some text
> echo $NEW_VAR

> source script.sh
david
Some text
> echo $NEW_VAR
hello
> Sudo source script.sh
Sudo: source: command not found
29
David Miani

Grundsätzlich erwartet Sudo, dass eine ausführbare Datei (Befehl) folgt und Sie einen . angeben.

Daher der Fehler.

Versuchen Sie es auf diese Weise $ Sudo setup.sh 


5
loxxy

Selbst die erste Antwort ist absolut genial, Sie möchten wahrscheinlich nur unter Sudo ein Skript ausführen.

Sie müssen den absoluten Pfad wie folgt angeben:

Sudo /home/user/example.sh
Sudo ~/example.sh

(beide arbeiten)

Das funktioniert nicht!

Sudo /bin/sh example.sh
Sudo example.sh

Es wird immer zurückkehren

Sudo: bin/sh: command not found
Sudo: example.sh: command not found
0
Martin Kovaľ

Wenn Sie wirklich wollen "ExecuteRufen Sie ein Shell-Skript in der aktuellen Shell mit Sudo-Berechtigung auf "Sie können exec verwenden, um ...

Ersetzen Sie die Shell durch ein bestimmtes Programm (Ausführung, nicht als neuer Prozess)

Ich bestehe darauf, "Ausführen" durch "Anrufen" zu ersetzen, weil Ersteres eine Bedeutung hat, die das Erstellen eines neuen Prozesses und einer neuen ID umfasst, wobei letzteres mehrdeutig ist und Raum für Kreativität lässt, von der ich voll bin. 

Betrachten Sie diesen Testfall und betrachten Sie pid 1337 genau.

# Don't worry, the content of this script is cat'ed below
$ ./test.sh -o foo -p bar

User ubuntu is running...
 PID TT       USER     COMMAND
 775 pts/1    ubuntu   -bash
1408 pts/1    ubuntu    \_ bash ./test.sh -o foo -p bar
1411 pts/1    ubuntu        \_ ps -t /dev/pts/1 -fo pid,tty,user,args

User root is running...
 PID TT       USER     COMMAND
 775 pts/1    ubuntu   -bash
1337 pts/1    root      \_ Sudo ./test.sh -o foo -p bar
1412 pts/1    root          \_ bash ./test.sh -o foo -p bar
1415 pts/1    root              \_ ps -t /dev/pts/1 -fo pid,tty,user,args

Take 'exec' out of the command and this script would get cat-ed twice. (Try it.)

#!/usr/bin/env bash

echo; echo "User $(whoami) is running..."
ps -t $(tty) -fo pid,tty,user,args

if [[ $EUID > 0 ]]; then
    # exec replaces the current process effectively ending execution so no exit is needed.
    exec Sudo "$0" "[email protected]"
fi

echo; echo "Take 'exec' out of the command and this script would get cat-ed twice. (Try it.)"; echo
cat $0

Hier ist ein weiterer Test mit Sudo -s

$ ps -fo pid,tty,user,args; ./test2.sh
  PID TT       USER     COMMAND
10775 pts/1    ubuntu   -bash
11496 pts/1    ubuntu    \_ ps -fo pid,tty,user,args

User ubuntu is running...
  PID TT       USER     COMMAND
10775 pts/1    ubuntu   -bash
11497 pts/1    ubuntu    \_ bash ./test2.sh
11500 pts/1    ubuntu        \_ ps -fo pid,tty,user,args

User root is running...
  PID TT       USER     COMMAND
11497 pts/1    root     Sudo -s
11501 pts/1    root      \_ /bin/bash
11503 pts/1    root          \_ ps -fo pid,tty,user,args

$ cat test2.src
echo; echo "User $(whoami) is running..."
ps -fo pid,tty,user,args

$ cat test2.sh
#!/usr/bin/env bash

source test2.src

exec Sudo -s < test2.src

Und ein einfacherer Test mit Sudo -s

$ ./exec.sh
bash's PID:25194    user ID:7809
systemd(1)───bash(23064)───bash(25194)───pstree(25196)

Finally...
bash's PID:25199    user ID:0
systemd(1)───bash(23064)───Sudo(25194)───bash(25199)───pstree(25201)

$ cat exec.sh
#!/usr/bin/env bash

pid=$$
id=$(id -u)
echo "bash's PID:$pid    user ID:$id"
pstree -ps $pid

# the quoted EOF is important to prevent Shell expansion of the $...
exec Sudo -s <<EOF
echo
echo "Finally..."
echo "bash's PID:\$\$    user ID:\$(id -u)"
pstree -ps $pid
EOF
0
Bruno Bronosky