¿Cómo resolver "permiso denegado" cuando se usa sudo con redirección en Bash?

115

Cuando uso sudo para permitir ediciones en archivos, recibo regularmente 'permiso denegado'.

Por ejemplo, mi mouse está inquieto y lento, así que quiero deshabilitar el sondeo:

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

Se me solicita una contraseña y luego obtengo:

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

Así que traté de hacer un cambio temporal para desactivar el sondeo al usar:

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

Una vez más, el sistema respondió con:

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

¿Alguna idea?

    
pregunta Jack 19.12.2012 - 05:12

6 respuestas

124

La redirección de salida (a través del operador > ) la realiza el shell, no mediante eco . Debes iniciar sesión como root

sudo -i

Luego puede usar la redirección

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

De lo contrario, puedes ejecutar bash string con sudo

sudo bash -c "echo N> /sys/module/drm_kms_helper/parameters/poll"
    
respondido por el shantanu 19.12.2012 - 05:22
71

La redirección de salida la realiza el shell desde el que se ha invocado el comando . Entonces, rompiendo todo en pedazos, aquí lo que está sucediendo *:

  • shell invoca sudo echo "options drm_kms_helper poll=N" , que ejecuta el comando sudo con echo "options drm_kms_helper poll=N" línea de comando

  • sudo solicita una contraseña, abre el shell del superusuario e invoca echo "options drm_kms_helper poll=N" , que ejecuta el comando echo pasándolo "options drm_kms_helper poll=N"

  • echo, ejecutándose con privilegios root , imprime la cadena en su salida estándar.

  • El comando
  • echo finaliza, el shell del superusuario sale, sudo termina

  • el shell desde el que se ha invocado el comando recopila el resultado e intenta redirigirlo a /etc/modprobe.d/local.conf , que solo se puede escribir por root. Obtiene el error de "permiso denegado".

Para las formas de corregir esto, vea la respuesta @shantanu.

(*): aunque la secuencia anterior ayuda a entender por qué el comando falla, en realidad las cosas suceden un poco fuera de orden: el shell original nota la redirección e intenta abrir el archivo para escribir antes de invocar el sudo ... mando. Al abrir el archivo falla el shell ni siquiera invoca el comando que se suponía que debía escribir en el archivo (gracias a @PanosRontogiannis para señalar esto).

Aquí hay una prueba rápida:

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

En la prueba anterior, whoami | tee who.txt iba a crear un archivo llamado who.txt que contiene la palabra "raíz". Sin embargo, cuando la redirección de salida falla en el shell de llamada, el archivo "who.txt" también falta porque el comando no se invocó.

    
respondido por el Sergey 19.12.2012 - 06:19
55

Añadiendo a la respuesta de Shantanu:

... O podría usar un comando tee como este:

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

o si es un resultado de comando:

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

Un enfoque que no he visto mencionado aquí es simplemente ejecutar toda la línea de comandos en su propio caparazón. La página de manual de sudo da un ejemplo de este enfoque:

  

Para hacer una lista de uso de los directorios en la partición / home. Tenga en cuenta que esto ejecuta los comandos en un subconjunto para que funcione la redirección de archivos y CD.

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

sudo dd of=

Para agregar como quieras:

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

o para volver a crear el archivo desde cero:

echo inbytes | sudo dd of=outfile

Ventajas:

  • más bonito que tee ya que no /dev/null redirección
  • más bonito que sh ya que no hay ninguna subcarpeta explícita (sino una implícita para la redirección)
  • dd tiene muchas opciones potentes, p. status=progress para ver el progreso de la transferencia

Funciona porque sudo reenvía stdin al comando.

    
2

Otra opción es usar un archivo temporal. Esto es útil en un script bash.

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

Lea otras preguntas en las etiquetas