¿Cuál es la diferencia entre `>> / dev / stderr` (con el espacio en blanco) y`> & 2`?

11

En bash.

¿Tengo dificultades para determinar qué debo usar?

todos mis scripts usan ">> / dev / stderr"

en bash prompt, si lo intento:
echo test >>/dev/stderrfunciona
echo test >> /dev/stderrfunciona
echo test >/dev/stderrfunciona
echo test > /dev/stderrfunciona

echo test >>&2FALLAS!
echo test >> &2FALLAS!
echo test >&2funciona
echo test > &2falla!

Estoy dispuesto a cambiar todos mis scripts a >&2.

Parece que también tiene un gran efecto sobre ssh (after su SomeUser) donde >>/dev/stderrno funcionará en absoluto (permiso denegado), solo >&2funcionará.

Poder de acuario
fuente
¿Puedes mostrar un ejemplo del error ssh? No puedo reproducirlo
Jeff Schaller
@JeffSchaller tienes razón, es solo después de suque sucede el problema, actualicé la pregunta
Aquarius Power
@AquariusPower, ... para explicar esa discrepancia, por cierto: con su -c 'some command', ese comando se ejecuta /bin/sh, no bash, por /dev/stderrlo que no se garantiza que haya un comportamiento específico de bash (como simular con fines de redireccionamiento cuando no está disponible).
Charles Duffy

Respuestas:

22

>& nes la sintaxis de shell para duplicar directamente un descriptor de archivo . El descriptor de archivo 2 es stderr; así es como funciona. También puede duplicar otros descriptores de archivos, no solo stderr. No puede usar el modo de agregar aquí porque duplicar un descriptor de archivo nunca se trunca (incluso si su stderr es un archivo) y >&es un token, por eso no puede poner un espacio dentro de él, pero >& 2funciona.

>> namees una sintaxis permitida diferente, donde namees un nombre de archivo (y el token es >>). En este caso, está utilizando el nombre del archivo /dev/stderr, que mediante el manejo específico del sistema operativo (en Linux, es un enlace simbólico /proc/self/fd/2) también significa error estándar. El modo Agregar y truncar terminan haciendo lo mismo cuando stderr es una terminal porque eso no se puede truncar. Si el error estándar es un archivo, sin embargo, se puede truncar:

anthony@Zia:~$ bash -c 'echo hi >/dev/stderr; echo bye >/dev/stderr' 2>/tmp/foo
anthony@Zia:~$ cat /tmp/foo
bye

Si ve un error con /dev/stderrmás de ssh, es posible que el administrador del servidor haya aplicado alguna medida de seguridad para evitar que ese enlace simbólico funcione. (Por ejemplo, no puedes acceder /proco /dev). Si bien esperaría que causara todo tipo de roturas extrañas, usar la sintaxis de descriptor de archivo duplicado es un enfoque perfectamente razonable (y probablemente un poco más eficiente). Personalmente lo prefiero.

derobert
fuente
Estaba teniendo un gran problema tratando de replicar ese problema truncado que tenía antes (de lo contrario, habría agregado eso a la pregunta jeje), la razón por la que cambié todo para usar >>, ¡gracias por señalarlo! Además, me perdí un paso su SomeUserdespués de conectarme a través de ssh.
Acuario Power
esto bash -c 'echo hi >&2; echo bye >&2' 2>/tmp/foo;cat /tmp/foono se truncará aunque! (incluso con 2>&1 |tee /tmp/foo) lo que es perfecto para iniciar sesión, y funcionará perfectamente después de que lo cambie todo >&2. Así que supongo que solo un uso directo del archivo /dev/stderrpermite truncar, no el descriptor duplicado, ¡genial!
Acuario Power
@AquariusPower correcto, el descriptor de archivo duplicado nunca se trunca. Eso está en el primer párrafo, ¿tal vez necesito resaltarlo de alguna manera?
derobert
no es necesario, a veces soy lento ehehe
Aquarius Power
3
Esta respuesta se puede mejorar. > & es una ficha, no dos, y ahí está la confusión de OP.
Joshua
8

Los casos de falla ocurren porque la sintaxis bash para usar &en redirecciones especifica una sola >y requiere que exista directamente adyacente al &signo:

[n]> y palabra

Jeff Schaller
fuente
2

Use '>'para redirigir (trunca si existe) o '>>'(agrega si existe)

Úselo '>&'para duplicar una secuencia, por ejemplo, si desea una salida estándar Y un error estándar en el mismo archivo, redirige a un archivo '> output.log'y también error con'2>&'

myjob.sh > output.log 2>&
Jose Manuel Gomez Alvarez
fuente