Führen Sie eine Befehlszeile mit einem Sudo aus

21

Wenn ich zum Beispiel eine Datei erstellen und Text in einer Zeile eingeben möchte, kann ich die Ausgabe mithilfe des >Operators in eine Datei umleiten :

echo "something" > /path/foobar

Aber wenn ich keinen Zugriff auf den Ordner habe /path/und Sudo-Berechtigungen benötige, wie kann ich denselben Befehl wie ein normaler Benutzer mit Sudo-Rechten ausführen?

Ich habe es versucht

sudo echo "something" > /path/foobar

aber das geht nicht, denn das sudo zählt nur für den edit, nicht aber für den richtigen teil
des sudo>

Klar, ich könnte vorher mit root werden sudo suoder teestattdessen verwenden:

echo "something" | sudo tee /path/foobar

Ich würde aber gerne eine Lösung finden, bei der ich mit der letzten Zeile als Ersatz über arbeiten kann

sudo !!

Gibt es nicht eine Möglichkeit, die letzte Zeile zu "recyceln" und einfach voranzustellen sudo?

rubo77
quelle
Dies ist kein Duplikat. Ich extrahierte die echte Frage und änderte den Titel. Jetzt ist es das, wonach ich wirklich suche
rubo77
Es sicherlich war ein Duplikat, aber es ist nun etwas anders. Es sieht für mich so aus, als hättest du die Frage im Lichte von Boogys Antwort umgeschrieben, was in Ordnung ist - das ist eine gute Antwort. Ich habe meine enge Abstimmung zurückgezogen, aber es ist immer noch unvermeidlich (Leute stimmen oft automatisch ab, wenn eine Frage in der engen Warteschlange steht, ohne auf das Problem zu achten): adressiere einen Kommentar @goldilocks, wenn sie geschlossen wird und ich stimme für die Wiedereröffnung . Sie können Ihren Fall auch im Chat vertreten, sobald dies geschieht.
Goldlöckchen
Siehe auch Wie kann ich alias sudo !!?
Gilles 'SO - hör auf, böse zu sein'

Antworten:

13

Sie können nicht einfach sudovor einem Shell-Befehl bleiben, sondern müssen eine Shell aufrufen, um diesen Befehl erneut auszuwerten (z. B. Variablen erweitern, Dateien für Umleitungsoperatoren öffnen usw.). So das ist

sudo bash -c !!

außer dass dies nicht ganz funktioniert, weil !!der Text des vorherigen Befehls, Sonderzeichen und alles interpoliert. Sie müssen den Text des Befehls als Zeichenfolge abrufen und als Argument an übergeben sh. Glücklicherweise bash fcbuiltin können Sie that¹ tun.

sudo bash -c "$(fc -ln -1)"

Oder, um sicherzugehen, dass Sie dieselbe Version von bash aufrufen, die gerade ausgeführt wird:

sudo "$BASH" -c "$(fc -ln -1)"

Beachten Sie, dass der Befehl, da er in einem separaten Shell-Prozess ausgeführt wird, Umgebungsvariablen (nur diejenigen, sudodie mind beibehalten), aber keine internen Shell-Variablen erbt . Shell-Optionen (z. B. kshglob) und andere Einstellungen beginnen ebenfalls mit der Standardeinstellung.

Der gleiche Befehl² funktioniert in zsh und ksh, obwohl ATT ksh93 die Übergabe von firstund lastnumber an fc³ erfordert (was auch in bash, zsh und pdksh / mksh funktioniert):

sudo zsh -c "$(fc -ln -1)"
sudo ksh -c "$(fc -ln -1 -1)"
sudo "$0" -c "$(fc -ln -1 -1)"

Das Festlegen $0der ausführbaren Datei der laufenden Shell funktioniert nur, wenn die Shell über $ PATH aufgerufen wurde und sich $ PATH nicht geändert hat oder über einen absoluten Pfad.

Hier ist eine andere Methode in zsh, die etwas klarer, aber länger ist:

sudo zsh -c $history[$[HISTCMD-1]]

Ein letzter Warnhinweis: bezieht sudosich auf potenziell gefährliche Befehle. Mach es dir nicht zu einfach, es zu benutzen!

¹ Am Anfang steht ein zusätzliches Leerzeichen, und die Befehlsersetzung entfernt am Ende Zeilenumbrüche, aber die Syntax der Shell kümmert sich nicht darum.
² Ich glaube nicht, dass zsh oder ksh so etwas wie bashs haben $BASH. $0Funktioniert nur, wenn es sich um einen absoluten Pfad handelt oder wenn er keinen Schrägstrich enthält und sich der Befehlssuchpfad nicht geändert hat.
³ ist ein Alias ​​für in ATT ksh, aber das ist genauso gut. fchist

Gilles 'SO - hör auf böse zu sein'
quelle
9

Wenn Sie den gleichen Befehl mit sudo wiederholen möchten !! Nach einem Befehl wie diesem:

echo "something">/path/file

Mit der globalen Ersetzungssyntax rufen Sie den Befehl auf:

!!:gs/>/|sudo tee -a /

Verwenden Sie ein Leerzeichen nach dem Parameter -a .

Dies ist das Äquivalent zu sudo !! Dies hilft Ihnen jedoch, die sudo-Einschränkungen für <und> zu umgehen. Weil sudo die Verwendung von [<,>] nicht zulässt.


Um die Sudo-Einschränkungen für Weiterleitungen im Allgemeinen zu umgehen, können Sie sie folgendermaßen verwenden:

echo "something" | sudo tee myfile

Mit dem Befehl tee können Sie von der Standardeingabe lesen und in die Standardausgabe und -dateien schreiben

Wenn Sie den Befehl wiederholen und einen Text an die Datei anhängen möchten, enthält der Befehl tee die Option -a zum Anhängen. So konnte man sich mit an den Befehl erinnern

sudo !!

und der Text wird in der Datei angehängt

Beispiel:

echo "something" | sudo tee -a /path/file
sudo !!
Boogy
quelle
schöne lösung, aber ein bisschen schwer zu merken. Wie kann ich einen Alias ​​für einen Befehl mit !! erstellen ? den letzten Befehl zurückrufen ?
Rubo77
wird das -awirklich gebraucht? >überschreibt eine Datei, tee -awird angehängt, was sein würde>>
rubo77
3

Es scheint so einfach zu sein wie sudo sh -c "!!":

$ cd /
$ echo hello > foo
bash: foo: Permission denied
$ sudo sh -c "!!"
sudo sh -c "echo hello > foo"
$ ls -l foo
-rw-r--r-- 1 root root 6 Jun 20 16:21 foo
Deltab
quelle
3
Wenn der Befehl Anführungszeichen verwendet, ist dies nicht unbedingt gleichbedeutend. Überlegen Sie, aus echo "foo bar"was was werden sh -c "echo "foo bar""würde, und drucken Sie es einfach fooaus foo bar.
Godlygeek
Ich habe sudo sh -c '!!'stattdessen versucht, ob Ihr Befehl, aber das funktioniert auch nicht
Rubo77
Was ist dann, wenn Ihr Befehl sowohl einfache als auch doppelte Anführungszeichen verwendet? Oder doppelte Anführungszeichen und variable Erweiterungen? Wenn der Benutzer dies getan hätte: a=bund dann echo "$a" >fileund dann sudo sh -c '!!'würde es erweitern, um sudo sh -c 'echo $a >file'die eine leere Zeile statt bin zu drucken file.
Godlygeek
Also gibt es vielleicht irgendwie eine noch bessere Lösung?
Rubo77
1
Ich glaube nicht, dass es eine Lösung gibt, die 100% der Zeit funktioniert, ohne dass Sie jemals den Befehl ändern müssen. Das Abrufen sudoeiner Root-Shell und anschließendes Kopieren und Einfügen des Befehls wäre am nächsten, schlägt jedoch fehl, wenn für den Befehl Variablen erwartet wurden, die in Ihrer Nicht-Root-Shell festgelegt wurden. Die Verwendung von sudo sh -c "!!"funktioniert gut für einfache Befehle, ist aber für komplexe voll. Ich denke, der beste Rat ist, nicht zu erwarten, dass es einen Befehl gibt, der 100% der Zeit funktioniert - lernen Sie einige mögliche Lösungen und wenden Sie jeden an, wenn er am besten passt.
Godlygeek