Come risolvere il "permesso negato" quando si usa sudo con reindirizzamento in Bash?


138

Quando utilizzo sudo per consentire le modifiche ai file, ricevo regolarmente "permesso negato".

Ad esempio, il mio mouse è nervoso e lento, quindi voglio disabilitare il polling:

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

Mi viene richiesta una password, quindi ottengo:

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

Quindi ho provato a fare una modifica temporanea per disabilitare il polling usando:

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

Ancora una volta il sistema ha risposto con:

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

Qualche idea?

Risposte:


158

Il reindirizzamento dell'output (tramite l' >operatore) viene eseguito dalla shell, non dall'eco . Devi accedere come root

sudo -i

Quindi è possibile utilizzare il reindirizzamento

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

Altrimenti puoi eseguire bash string con sudo

sudo bash -c "echo N> /sys/module/drm_kms_helper/parameters/poll"

1
Non puoi eseguire l'eco con sudo? per quanto riguarda il risultato che ho ottenuto:saji@laptop:~$ sudo echo "Hi" [sudo] password for saji: Hi
saji89

puoi scrivere su un file, fare eco "qualcosa"> somewhre. Sta usando la pipe .. Questo è il problema.
shantanu,

4
Ok, in tal caso, ti preghiamo di aggiornare la tua risposta per riflettere che l'esecuzione dell'eco è un problema solo in quel caso.
saji89,

Non puoi semplicemente eseguire la shell incorporata echocome sudo, a meno che tu non faccia qualcosa di simile sudo bash -c 'echo …'; tuttavia, i sistemi POSIX normalmente forniscono un echocomando esterno come /bin/echosu OS X, che sudo può eseguire senza rigamarole. Pertanto, il echocomando che di solito si esegue e il echocomando che si esegue con sudo sono probabilmente due comandi diversi, ma simili.
Kojiro,

In tal caso, perché le risposte a questa domanda suggeriscono l'eco? askubuntu.com/questions/840431/…
Harsha,

75

Il reindirizzamento dell'output viene eseguito dalla shell da cui è stato richiamato il comando . Quindi, rompendo tutto a pezzi, ecco cosa sta succedendo *:

  • invoca la shell sudo echo "options drm_kms_helper poll=N", che esegue il sudocomando con la echo "options drm_kms_helper poll=N"riga di comando

  • sudo chiede una password, apre la shell del superutente e invoca echo "options drm_kms_helper poll=N", che esegue il echocomando passando"options drm_kms_helper poll=N"

  • echo, in esecuzione con rootprivilegi, stampa la stringa sul suo output standard.

  • echoil comando termina, la shell del superutente esce, sudotermina

  • la shell da cui è stato invocato il comando raccoglie l'output e tenta di reindirizzarlo /etc/modprobe.d/local.conf, che è scrivibile solo da root. Viene visualizzato l'errore "permesso negato".

Per i modi per risolvere questo problema, vedi la risposta @shantanu.


(*) - mentre la sequenza sopra riportata aiuta a capire perché il comando fallisce, in realtà le cose accadono in qualche modo fuori ordine: la shell originale nota il reindirizzamento e prova ad aprire il file per la scrittura prima di invocare il sudo ...comando. Quando l'apertura del file fallisce, la shell non invoca nemmeno il comando che avrebbe dovuto scrivere sul file (grazie a @PanosRontogiannis per averlo sottolineato).

Ecco un breve test:

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

Nel test sopra whoami | tee who.txtstava per creare un file chiamato who.txtcontenente la parola "root". Tuttavia, quando il reindirizzamento dell'output non riesce nella shell chiamante, manca anche il file "who.txt" perché il comando non è stato invocato.


Più probabilmente la shell si "forcherà" da sola e prova ad aprire /etc/modprobe.d/local.conf prima di provare a "exec" sudo, il che significa che i primi 4 passaggi descritti non si verificano realmente perché il file non può essere aperto.
Panos Rontogiannis,

1
@PanosRontogiannis: grazie, ho aggiornato la risposta
Sergey

60

Aggiungendo alla risposta di Shantanu:

... O potresti usare un teecomando come questo:

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

o se è l'output di un comando:

echo 10 | sudo tee /sys/module/drm_kms_helper/parameters/poll

3
+1 login come root è una cattiva idea per il lavoro manuale, e una davvero pessima idea per le attività di script.
l0b0

2
Inoltre, sudo tee /sys/module/drm_kms_helper/parameters/poll > /dev/nullse non lo desideri, stampa stdoutanche.
Fabian Tamp,

16

Un approccio che non ho visto menzionato qui è semplicemente quello di eseguire l'intera riga di comando nella propria shell. La sudostessa manpage fornisce un esempio di questo approccio:

Per creare un elenco di utilizzo delle directory nella partizione / home. Si noti che questo esegue i comandi in una sotto-shell per far funzionare il reindirizzamento di cd e file.

$ sudo sh -c "cd /home ; du -s * | sort -rn > USAGE"

Wow grazie. una soluzione semplice
Resilience

4

Un'altra opzione è quella di utilizzare un file temporaneo. Questo è utile in uno script bash.

temp=$(mktemp)
echo "Hello, world!" > $temp
sudo cp $temp /etc/wherever

3

sudo dd of=

Per aggiungere come vuoi:

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

o per ricreare il file da zero:

echo inbytes | sudo dd of=outfile

vantaggi:

  • più bello che teeda nessun /dev/nullreindirizzamento
  • più bello che da shallora nessuna subshell esplicita (ma implicita per il reindirizzamento)
  • ddha molte opzioni potenti, ad esempio status=progressper vedere l'avanzamento del trasferimento

Funziona perché sudo inoltra stdin al comando.


1
Questo è buono. Pensiamo dda come sovrascriviamo i nostri file system un tempo fantastici e non ci rendiamo conto che è anche per compiti banali - e che anche altri comandi come root causano un danno grave se utilizzati su file / dispositivi sbagliati. Ad esempiosudo tee , sudo ddovviamente funzionerà anche con stringhe qui , ad es sudo dd of=outfile <<<'hello world'. [Grazie per il montaggio. NB con sh -c 'cmd', shè un sottoprocesso che è una shell, ma in realtà non una subshell tranne nel senso in cui tutti i comandi esterni iniziano come uno.]
Eliah Kagan
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.