Wie löst man "permission denied" bei Verwendung von sudo mit Umleitung in Bash?

115

Wenn sudo verwendet wird, um Änderungen an Dateien zu erlauben, bekomme ich regelmäßig 'permission denied'.

Zum Beispiel ist meine Maus nervös und träge, deshalb möchte ich das Polling deaktivieren:

sudo echo "options drm_kms_helper poll=N">/etc/modprobe.d/local.conf

Ich werde nach einem Passwort gefragt und dann:

bash: /etc/modprobe.d/local.conf: Permission denied

Also habe ich versucht, eine vorübergehende Änderung zu machen, um die Abfrage zu deaktivieren, indem ich Folgendes benutze:

sudo echo N> /sys/module/drm_kms_helper/parameters/poll

Noch einmal antwortete das System mit:

bash: /sys/module/drm_kms_helper/parameters/poll: Permission denied

Irgendwelche Ideen?

    
Jack 19.12.2012, 05:12

6 Antworten

123

Die Ausgabeumleitung (über den Operator > ) erfolgt durch die Shell, nicht durch echo . Sie müssen sich als root anmelden

sudo -i

Dann können Sie die Umleitung verwenden

echo N> /sys/module/drm_kms_helper/parameters/poll

Ansonsten können Sie bash string mit sudo

ausführen
sudo bash -c "echo N> /sys/module/drm_kms_helper/parameters/poll"
    
shantanu 19.12.2012, 05:22
70

Die Ausgabeumleitung erfolgt durch die Shell , von der der Befehl aufgerufen wurde . Also, alles in Stücke zerbrechen, hier was passiert *:

    Die Shell
  • ruft sudo echo "options drm_kms_helper poll=N" auf, wodurch der Befehl sudo mit der Befehlszeile echo "options drm_kms_helper poll=N"

  • ausgeführt wird
  • sudo fragt nach einem Passwort, öffnet die Superuser-Shell und ruft echo "options drm_kms_helper poll=N" auf, wodurch echo command ausgeführt wird und "options drm_kms_helper poll=N"

  • übergeben wird
  • echo, das mit den Berechtigungen root ausgeführt wird, gibt die Zeichenfolge an die Standardausgabe aus.

  • echo -Befehl wird beendet, Superuser-Shell-Exits, sudo terminiert

  • Die Shell, von der der Befehl aufgerufen wurde, sammelt die Ausgabe und versucht, sie an /etc/modprobe.d/local.conf umzuleiten, was nur durch root schreibbar ist. Es wird der Fehler "Berechtigung verweigert" angezeigt.

Wie Sie das beheben können, finden Sie unter @shantanu antwort.

(*) - Während die obige Sequenz hilft zu verstehen, warum der Befehl fehlschlägt, passieren die Dinge in Wirklichkeit etwas außerhalb der Reihenfolge: Die ursprüngliche Shell bemerkt die Umleitung und versucht, die Datei zum Schreiben zu öffnen, bevor sudo ... aufgerufen wird. Befehl. Wenn das Öffnen der Datei fehlschlägt, ruft die Shell nicht einmal den Befehl auf, der in die Datei schreiben sollte (dank @PanosRontogiannis, um dies zu verdeutlichen).

Hier ist ein kurzer Test:

$ touch ./onlyroot.txt
$ sudo chown root:root ./onlyroot.txt
$ sudo bash -c "whoami | tee who.txt" > onlyroot.txt
bash: onlyroot.txt: Permission denied

Im obigen Test wurde whoami | tee who.txt eine Datei namens who.txt erstellen, die das Wort "root" enthält. Wenn jedoch die Ausgabeumleitung in der aufrufenden Shell fehlschlägt, fehlt auch die Datei "who.txt", weil der Befehl nicht aufgerufen wurde.

    
Sergey 19.12.2012 06:19
55

Hinzufügen zu Shantanus Antwort:

... Oder Sie könnten einen tee Befehl wie folgt verwenden:

sudo tee /sys/module/drm_kms_helper/parameters/poll <<<10

oder wenn es die Ausgabe eines Befehls ist:

echo 10 | sudo tee /sys/module/drm_kms_helper/parameters/poll
    
Untitled 19.12.2012 07:50
13

Ein Ansatz, den ich hier nicht erwähnt habe, ist, einfach die gesamte Befehlszeile in einer eigenen Shell auszuführen. Die Hilfeseite sudo selbst gibt ein Beispiel für diesen Ansatz:

  

Um eine Verwendungsliste der Verzeichnisse in der Partition / home zu erstellen. Beachten Sie, dass damit die Befehle in einer Subshell ausgeführt werden, damit die CD- und Dateiumleitung funktioniert.

$ sudo sh -c "cd /home ; du -s * | sort -rn > USAGE"
    
kojiro 19.12.2012 14:53
2

Eine andere Option ist die Verwendung einer temporären Datei. Dies ist nützlich in einem Bash-Skript.

temp=$(mktemp)
echo "Hello, world!" > $temp
sudo cp $temp /etc/wherever
    
user545424 29.07.2014 17:51
2

sudo dd of=

So fügen Sie an:

echo inbytes | sudo dd of=outfile oflag=append conv=notrunc

oder um die Datei von Grund auf neu zu erstellen:

echo inbytes | sudo dd of=outfile

Vorteile:

  • schöner als tee seit keine /dev/null Umleitung
  • schöner als sh seit keine explizite Subshell (aber eine implizite für die Umleitung)
  • dd hat viele mächtige Optionen, z.B. status=progress , um den Übertragungsfortschritt zu sehen

Funktioniert, weil sudo stdin an den Befehl weiterleitet.

    

Tags und Links