bash: / dev / stderr: permiso denegado

19

Después de actualizar a una nueva versión de lanzamiento, mis bashscripts comienzan a escupir errores:

bash: /dev/stderr: Permission denied

en versiones anteriores, Bash reconocería internamente esos nombres de archivo (razón por la cual esta pregunta no es un duplicado de este ) y haría lo correcto (tm) , sin embargo, esto ha dejado de funcionar ahora. ¿Qué puedo hacer para poder ejecutar mis scripts nuevamente con éxito?

Intenté agregar al usuario que ejecuta el script al grupo tty, pero esto no hace ninguna diferencia (incluso después de cerrar sesión y volver a iniciarla).

Puedo reproducir esto en la línea de comando sin problema:

$ echo test > /dev/stdout
bash: /dev/stdout: Permission denied
$ echo test > /dev/stderr
bash: /dev/stderr: Permission denied
$ ls -l /dev/stdout /dev/stderr
lrwxrwxrwx 1 root root 15 May 13 02:04 /dev/stderr -> /proc/self/fd/2
lrwxrwxrwx 1 root root 15 May 13 02:04 /dev/stdout -> /proc/self/fd/1
$ ls -lL /dev/stdout /dev/stderr
crw--w---- 1 username tty 136, 1 May 13 05:01 /dev/stderr
crw--w---- 1 username tty 136, 1 May 13 05:01 /dev/stdout
$ echo $BASH_VERSION
4.2.24(1)-release

En un sistema anterior (Ubuntu 10.04):

$ echo $BASH_VERSION
4.1.5(1)-release
0xC0000022L
fuente
1
¿Cuál es la salida de ls -l /dev/stdout /dev/stderry ls -lL /dev/stdout /dev/stderr?
Keith Thompson
@Keith: mira mi pregunta editada. ¿Eso significa que Bash ha abandonado por completo el manejo interno de esto? En sistemas más antiguos, estos enlaces simbólicos no existían y, sin embargo, el código funcionó sin problemas. Tenga en cuenta que esto se está ejecutando a través de sudo su username2 -...
0xC0000022L
¿Qué versión de bash estás usando? echo $BASH_VERSION
jippie
1
¿Cuáles son las versiones antiguas y nuevas (antes y después de su sistema operativo y de bash?)
Keith Thompson

Respuestas:

41

No creo que esto sea completamente un problema bash.

En un comentario, dijo que vio este error después de hacer

sudo su username2

cuando inicie sesión como username. Es lo suque está desencadenando el problema.

/dev/stdoutes un enlace simbólico a /proc/self/fd/1, que es un enlace a, por ejemplo, /dev/pts/1. /dev/pts/1, que es un pseudoterminal, es propiedad de y puede escribirlo username; esa propiedad se otorgó al usernameiniciar sesión. Cuando usted sudo su username2, la propiedad de /dev/pts/1no cambia y username2no tiene permiso de escritura.

Yo diría que esto es un error. /dev/stdout debería ser, en efecto, un alias para el flujo de salida estándar, pero aquí vemos una situación en la que echo hellofunciona pero echo hello > /dev/stdoutfalla.

Una solución alternativa sería formar username2un miembro del grupo tty, pero eso daría username2permiso para escribir en cualquier tty, lo que probablemente no sea deseable.

Otra solución alternativa sería iniciar sesión en la username2cuenta en lugar de utilizarla su, de modo que /dev/stdoutapunte a un pseudoterminal recientemente asignado propiedad de username2. Esto podría no ser práctico.

Otra solución sería modificar sus scripts para que no se refieran a /dev/stdouty /dev/stderr; por ejemplo, reemplace esto:

echo OUT > /dev/stdout
echo ERR > /dev/stderr

por esto:

echo OUT
echo ERR 1>&2

Veo esto en mi propio sistema, Ubuntu 12.04, con bash 4.2.24, a pesar de que el documento bash ( info bash) en mi sistema dice eso /dev/stdouty /dev/stderrse trata especialmente cuando se usa en redirecciones. Pero incluso si bash no trata esos nombres especialmente, deberían actuar como equivalentes para los flujos de E / S estándar. (POSIX no menciona /dev/std{in,out,err}, por lo que puede ser difícil argumentar que esto es un error).

Mirando las versiones antiguas de bash, la documentación implica que /dev/stdoutet al son tratados especialmente si los archivos existen o no. La característica se introdujo en bash 2.04, y el NEWSarchivo para esa versión dice:

El código de redirección ahora maneja varios nombres de archivo especialmente: / dev / fd / N, / dev / stdin, / dev / stdout y / dev / stderr, estén o no presentes en el sistema de archivos.

Pero si examina el código fuente ( redir.c), verá que ese manejo especial está habilitado solo si el símbolo HAVE_DEV_STDINestá definido (esto se determina cuando bash se construye desde la fuente).

Por lo que puedo decir, ninguna versión lanzada de bash ha hecho que el manejo especial de /dev/stdoutet al sea incondicional, a menos que alguna distribución lo haya parcheado.

Entonces, otra solución (que no he probado) sería tomar las fuentes de bash , modificar redir.cpara hacer que el /dev/*manejo especial sea incondicional y usar su versión reconstruida en lugar de la que vino con su sistema. Sin embargo, esto probablemente sea exagerado.

RESUMEN :

Su sistema operativo, como el mío, no está manejando la propiedad y los permisos de /dev/stdouty /dev/stderrcorrectamente. supuestamente bash trata estos nombres especialmente en redirecciones, pero de hecho solo lo hace si los archivos no existen. Eso no importa si /dev/stdouty /dev/stderrfuncionó correctamente. Este problema solo aparece cuando estás suen otra cuenta o haces algo similar; Si simplemente inicia sesión en una cuenta, los permisos son correctos.

Keith Thompson
fuente
La propiedad del TTY debería cambiar. Para eso es ConsoleKit (también conocido pam_ck_connector.socomo).
Mikel
En realidad, podría estar equivocado. Habrá que cavar más.
Mikel
En mis sistemas, /proc/self/fd/1se están actualizando sus permisos, pero eso no tiene sentido, ya que es un enlace simbólico. También sucede en Fedora, que parece descartar ConsoleKit.
Mikel
1

En realidad, la razón de esto es que udev establece específicamente los permisos en 0620 en dispositivos tty y su no cambia ni la propiedad ni los permisos, ni debería hacerlo. En mi opinión, esto nos deja en una situación que hace que / dev / std * no sea portátil.

La solución simple es poner "mesg y" en / etc / profile (o cualquier perfil de nivel superior que quiera usar) ya que esto cambia los permisos de su dispositivo tty a 0622. Realmente no me gusta, pero probablemente sea mejor que cambiar las reglas de udev.

Wheely
fuente
"msg y" no funciona
Luciano
Espere ... tal vez la búsqueda de Bash maneja varios nombres de archivo especialmente cuando se usan en redirecciones en la página de manual de Bash.
0xC0000022L
0

Como usuario de Linux desde hace mucho tiempo, configuré recientemente un nuevo sistema Ubuntu 64 bit 12.04 LTS y estaba desconcertado de por qué mis scripts de bash no funcionaban (permiso denegado) y posteriormente encontré este hilo. Pensé que el problema podría deberse a algo en el nuevo sistema operativo.

Al final resulta que había usado estúpidamente una herramienta de interfaz de usuario para establecer permisos en mi /homedirectorio, y el problema estaba relacionado con la unidad . Para estar seguro, creé un tempdirectorio /opty descubrí que mis scripts se ejecutarían bien desde allí. Una vez que arreglé los /homepermisos de la unidad, todo volvió a la normalidad.

Un pequeño misterio resuelto. suspiro

Ichiro Furusato
fuente
2
Esto debe haber sido un error diferente. Modificar algo en / home no afecta a / dev.
ott--
-1

Esta es una vieja pregunta, pero creo que sigue siendo muy relevante, por lo tanto, aquí hay una solución que encontré que no se menciona aquí.

Me encontré con esta pregunta ya que también he visto problemas en un comando de ejecución de cuenta conmutada 'su' como este en bash:

echo test > /dev/stderr

Como todo lo que intento hacer es redirigir stdout a stderr, lo siguiente logra lo mismo, y funciona incluso en la cuenta conmutada 'su':

echo test 1>&2
Marcin K
fuente