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

115

Quando si utilizza sudo per consentire modifiche ai file, ottengo regolarmente il "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

Vengo avvisato per una password, e poi ottenere:

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

Così 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?

    
posta Jack 19.12.2012 - 05:12
fonte

6 risposte

123

Il reindirizzamento dell'output (tramite l'operatore > ) viene eseguito dalla shell, non da echo . Devi effettuare il login come root

sudo -i

Quindi puoi usare il reindirizzamento

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

Altrimenti puoi eseguire la stringa bash con sudo

sudo bash -c "echo N> /sys/module/drm_kms_helper/parameters/poll"
    
risposta data shantanu 19.12.2012 - 05:22
fonte
70

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

  • la shell richiama sudo echo "options drm_kms_helper poll=N" , che esegue il comando sudo con echo "options drm_kms_helper poll=N" riga comandi

  • sudo richiede una password, apre la shell superuser e richiama echo "options drm_kms_helper poll=N" , che esegue echo comando passandolo "options drm_kms_helper poll=N"

  • echo, eseguito con root privilegi, stampa la stringa sul suo output standard.

  • Il comando echo termina, la shell superuser termina, sudo termina

  • la shell da cui è stato invocato il comando raccoglie l'output e tenta di reindirizzare a /etc/modprobe.d/local.conf , che è scrivibile solo da root. Ottiene l'errore "autorizzazione negata".

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

(*) - 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 richiamare 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 indicato).

Ecco un test rapido:

$ 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 il whoami | tee who.txt stava per creare un file chiamato who.txt contenente 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 richiamato.

    
risposta data Sergey 19.12.2012 - 06:19
fonte
55

Aggiunta alla risposta di Shantanu:

... Oppure potresti usare un comando tee come questo:

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

o se è un output di un comando:

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

Un approccio che non ho visto qui è semplicemente eseguire l'intera linea di comando nella propria shell. La stessa manpage sudo fornisce un esempio di questo approccio:

  

Per creare un elenco di utilizzo delle directory nella partizione / home. Nota 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"
    
risposta data kojiro 19.12.2012 - 14:53
fonte
2

Un'altra opzione è usare un file temporaneo. Questo è utile in uno script bash.

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

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

I vantaggi:

  • più bello di tee poiché nessun /dev/null reindirizzamento
  • più bello di sh poiché nessuna subshell esplicita (ma implicita per il reindirizzamento)
  • dd ha molte opzioni potenti, ad es. status=progress per vedere l'avanzamento del trasferimento

Funziona perché sudo inoltra stdin al comando.

    
fonte

Leggi altre domande sui tag