Note that the order of redirections is significant. For example, the command
ls > dirlist 2>&1
directs both standard output and standard error to the file dirlist,
while the command
ls 2>&1 > dirlist
directs only the standard output to file dirlist, because the
standard error was duplicated from the standard output before the standard
output was redirected to dirlist.
Ahora, esa última parte es confusa para mí. En ese caso, cualquier error estándar se imprimiría en el terminal y cualquier STDOUT iría al archivo dirlist. Eso es lo que sucedería, pero no es así como entiendo el manual.
Parece que debería decir "porque el error estándar fue duplicado de la salida estándar DESPUÉS de que la salida estándar fue redirigida a dirlist". Si STDERR fue enviado a STDOUT antes de que STDOUT fuera dirigido a un archivo, ¿no contendría STDOUT AND STDERR?
¿Alguien puede aclarar esto por mí? ¿Es solo mala comprensión de lectura de mi parte? El uso de la palabra duplicación me parece un poco extraño en este contexto. Quizás eso me está arrojando.
bash
shell
io-redirection
Gregg Leventhal
fuente
fuente
a = 1; b = a; a = 2
que esperasa == 2 && b == 1
ser verdad. La redirección2>&1
es similar a lab = a
asignación: es por valor, no por referencia.2>&1
no combina el descriptor de archivo 2 con el descriptor de archivo 1 para toda la eternidad; siguen siendo 2 descriptores de archivo distintos, que pueden apuntar al mismo archivo.Respuestas:
La duplicación es realmente la parte importante aquí.
Veamos a dónde van los descriptores de archivos antes de la redirección. Este es normalmente el terminal actual, por ejemplo:
Ahora, si llamamos
ls -l
sin redireccionamiento, los mensajes de salida y error van a mi terminal debajo/dev/pts/1
.Si primero redirigimos
STDOUT
a un archivo (ls -l > dirlist
), se ve así:Cuando luego redirigimos
STDERR
a un duplicado delSTDOUT
descriptor de archivo (ls -l > dirlist 2>&1
),STDERR
va a un duplicado de/home/bon/dirlist
:Si primero redirigiéramos
STDERR
a un duplicado delSTDOUT
descriptor de archivo (ls -l 2>&1
):y luego
STDOUT
a un archivo (ls -l 2>&1 > dirlist
), obtendríamos esto:Aquí,
STDERR
todavía va a la terminal.Verá, el orden en la página del manual es correcto.
Prueba de redireccionamiento
Ahora, puedes probar eso tú mismo. Usando
ls -l /proc/$$/fd/
, verá dóndeSTDOUT
(con fd 1) ySTDERR
(con fd 2) van para el proceso actual:Creemos un pequeño script de shell que muestre dónde apuntan los descriptores de sus archivos. De esta forma, siempre obtenemos el estado al llamar
ls
, incluida cualquier redirección desde el shell de llamada.(Con CtrlD, envía un fin de archivo y así detiene la
cat
lectura del comandoSTDIN
).Ahora, llame a este script con diferentes combinaciones de redireccionamiento:
Puede ver que los descriptores de archivo 1 (para
STDOUT
) y 2 (paraSTDERR
) varían. Por diversión, también puede redirigirSTDIN
y ver el resultado:(Pregunta dejada al lector: ¿Dónde apunta el descriptor de archivo 255? ;-))
fuente
No, el manual es correcto.
Si al principio 1 apunta a la terminal y 2 también a la terminal, entonces:
La redirección evaluatino ocurrirá de izquierda a derecha.
Por lo tanto, PRIMERO evaluará
2>&1
y, por lo tanto, PRIMERO copiará lo que fd1
solía señalar (es decir, el descriptor de archivothe terminal
, generalmente / dev / tty) en fd2
.Entonces, en ese punto, fd
2
ahora apunta a donde1
solía señalar fd (the terminal
)Y ENTONCES evalúa la
1>somewhere
parte, y por lo tanto copiará el descriptor de archivo desomewhere
in fd1
(entonces, en ese punto, fd1
ahora apunta asomewhere
, y fd2
todavía apunta athe terminal
)Por lo tanto, imprime 1 en "en algún lugar" y 2 en el terminal, ya que 2 se duplicó de 1 ANTES de que 1 haya cambiado.
El otro orden:
primero redirigirá fd
1
asomewhere
, y luego copiará esa misma referencia en fd 2, por lo que al final 2 también apunta asomewhere
. Pero no están "vinculados" de ahora en adelante. Cada uno todavía puede ser redirigido por separado.ex:
Al final de ese, fd
1
apunta asomewhere
, y fd2
se dirige a/dev/null
Los nombres habituales para fd
1
es STDOUT (salida estándar), y el nombre habitual para fd2
es STDERR (error estándar, ya que se usa comúnmente para mostrar errores sin interferir con STDOUT)fuente
cmd 1>somewhere 2>&1 ; exec 2>/dev/null
después del ejecutivo, solo 2 han sido redirigidos a / dev / null (1 todavía va a "en algún lugar"). Sin embargo, necesito ayuda para encontrar una manera de decir "lo que 1 señala" en lugar de "el fd 1", ya que eso también es confuso ...Creo que la parte confusa aquí es la mala interpretación de que redireccionar stderr a stdout en realidad conecta las dos corrientes.
Una idea perfectamente razonable, pero lo que sucede cuando escribes
2>&1
es stderr echa un vistazo a lo que stdout está escribiendo y escribe en el mismo lugar. Por lo tanto, si posteriormente le dice a stdout que vaya a escribir en otro lugar, no tiene ningún efecto sobre el destino de stderr que ya se ha movido.Creo que es un poco contradictorio, pero así es como funciona. Configure dónde desea escribir primero y luego diga a todos "cópieme". Espero que eso aclare ...
fuente
DUPLICACIÓN...
es importante, sino más bien en el sentido de que es fuente de mucha confusión . Es realmente bastante simple. Esta respuesta es solo una ilustración "radical".
La respuesta aceptada es buena, pero demasiado larga y enfatiza la "duplicación".
La Q termina sabiamente con:
Utilizo la notación bash y defino las variables "uno" y "dos" como manejadores de archivos "1" y "2". El operador de redireccionamiento (de salida)
>
es una asignación=
.&
y$
significa "valor" de.Los ejemplos de man bash (con el valor predeterminado "1" agregado)
volverse:
y
E incluso esto no es automático para mí, y algunos otros, supongo. La primera línea te deja con
$one
y$two
ambos contienen "dirlist". Por supuesto.La segunda línea comienza con una asignación inútil. Ambos comienzan por definición con "TTY" (un poco simbólico) como su dirección ; esta asignación no cambia ningún valor, y con las variables como con los controladores de archivo, nada está mágicamente vinculado. La variable
two
no se ve afectada por lo siguienteone=dirlist
. Por supuesto no.Sombody aquí (hace 6 años) sugirió "señalar" en lugar de "copiar" o "duplicar", y luego se dio cuenta: eso también sería confuso.
Esta duplicación o puntero semántico ni siquiera es necesaria. Tal vez sea el ampersand que necesita más atención. El "valor de" operador / token / lo que sea.
Si, y solo si, está buscando una manera de obtener un número de trabajo sorprendente en su consola , entonces un mensaje de "hecho" más un bono llamado "2", entonces:
Se lee naturalmente como " copiar" / "duplicar" 1 a 2, y luego ambos juntos a nulo . Pero la idea es incorrecta, y también la sintaxis. (pero no hay error de sintaxis, es válido)
La forma correcta de planificarlo es redirigir cualquiera de los dos a nulo y luego redirigir el OTRO al MISMO lugar:
(el "1" principal se puede dejar de lado)
(OK, el acc. A no es demasiado largo, pero es demasiado de una lista, o: muy buena visualización, no tan buena explicación)
fuente