windows - online - ¿Por qué mi stderr redirection no termina después de que termine el comando? ¿Y cómo lo arreglo?
tag rename (3)
Aquí hay un script de prueba que reproduce el problema que estás viendo.
@echo off
2>nul 3>nul (
echo I want to see stream1
1>&2 echo I don''t want to see this stream2
1>&3 echo I don''t want to see this stream3
)
echo stream1 works fine
1>&2 echo stream2 is now "permanently" void. I don''t see this.
1>&3 echo stream3 works fine
Y aquí está la salida
I want to see stream1
stream1 works fine
stream3 works fine
stderr (secuencia 2) se ha desactivado "permanentemente", incluso para el shell padre CMD.EXE.
Puede evitar el aspecto "permanente" haciendo su redirección por etapas:
@echo off
2>nul (
3>nul (
echo I want to see stream1
1>&2 echo I don''t want to see this stream2
1>&3 echo I don''t want to see this stream3
)
)
echo stream1 works fine
1>&2 echo stream2 works fine
1>&3 echo stream3 works fine
Y aquí está el resultado deseado:
I want to see stream1
stream1 works fine
stream2 works fine
stream3 works fine
Realmente no entiendo lo que está pasando. Pero he hecho algunos experimentos interesantes. Mira este hilo: http://www.dostips.com/forum/viewtopic.php?f=3&t=2836&start=30
Apéndice
Como Erbert ha descubierto y compartido su comentario, la solución es aún más fácil si solo cambia el orden de la redirección, no es necesario que lo organice.
@echo off
3>nul 2>nul (
echo I want to see stream1
1>&2 echo I don''t want to see this stream2
1>&3 echo I don''t want to see this stream3
)
echo stream1 works fine
1>&2 echo stream2 works fine
1>&3 echo stream3 works fine
Actualización 2012-04-03 Creo que finalmente entiendo la mecánica de la redirección de Windows CMD.EXE. Tengo una teoría de trabajo que explica completamente todo el comportamiento extraño, incluyendo por qué invertir el orden impide la redirección "permanente". También explica la observación de Aacini de que el identificador 3 parece estar conectado a CON: (No lo es, en realidad no está definido según la documentación de Windows).
Los puntos clave son:
1 - Cada vez que se redirige un identificador (transmisión), la definición original se transfiere al primer manejador indefinido disponible. Las redirecciones sucesivas siempre se llevan a cabo de izquierda a derecha.
2 - Cuando finaliza la redirección, las definiciones originales se restauran normalmente. Pero si hay una cadena de redirecciones, entonces la restauración solo se realiza a un nivel de profundidad. Esta es la fuente de la redirección "permanente".
Edit 2014-12-19: Dicho de otra manera, la restauración parece estar hecha usando una estructura de cola (FIFO - First In First Out), cuando debería haberse implementado como una pila (LIFO - Last In First Out).
3 - Cuando CMD.EXE lleva a cabo la redirección, primero guarda la definición actual en el manejador indefinido, luego redirige el primer manejador. Si el primer identificador se redirige al identificador original indefinido, se redirige efectivamente a su definición original. Es por eso que echo hello 1>&3
salidas a la consola.
La teoría completa y los casos de prueba están disponibles en dos publicaciones consecutivas en http://www.dostips.com/forum/viewtopic.php?p=14612#p14612 .
En Windows, ya sea en línea de comandos o en un archivo por lotes, el comando "DIR 2> NUL: 3> & 2" (puede reemplazar "DIR" con cualquier cosa, incluso si no es un archivo o un comando) hará todos los errores de luego, desaparecerá a menos que escriba "2> CON:" después de cada comando. ¿Por qué CMD incluso está haciendo esto? ¿Y cómo puede volver a la normalidad sin iniciar un nuevo proceso de CMD? "DIR 2> CON: 3> & 2" solo funcionará para ese comando solo.
EDITAR: Esto también funcionará con los archivos. "DIR 2> TEXT.TXT 3> & 2" Cualquier error posterior se agregará al archivo.
El problema es con 3>&2
. El descriptor de archivo 3 no es válido y parece alterar Windows de alguna manera. Déjalo, no lo necesitas.
Consulte la documentación de Microsoft para el tratamiento completo.
Me disculpo por publicar esto como una respuesta en lugar de un comentario, pero mi "comentario" es demasiado grande ...
En el estándar de MS-DOS, todos los programas en ejecución tienen abiertos estos controladores estándar : 0-STDIN (teclado), 1-STDOUT (pantalla), 2-STDERR (pantalla), 3-STDAUX (puerto serie) y 4-STDPRN (impresora ) Aunque la documentación de Windows indica claramente que los identificadores 3-9 no están definidos, el manejador 3 tiene un tratamiento especial por CMD.EXE. Tengo tres razones para pensar esto:
1- La Manija 3 está conectada a CON: dispositivo (teclado para entrada, pantalla para salida); los mangos 4-9 no:
C>ver
Microsoft Windows XP [Version 5.1.2600]
C>echo To handle 3 >&3
To handle 3
C>echo To handle 4 >&4
The handle could not be duplicated
during redirection of handle 1.
C>set /P var=From handle 3: <&3
From handle 3: Value entered in keyboard
C>echo %var%
Value entered in keyboard
C>set /P var=From handle 4: <&4
The handle could not be duplicated
during redirection of handle 0.
2- El extraño comportamiento de handle 3 indicado en el presente tema, que fue resuelto de dos maneras diferentes. Descubrí que si los controladores 0, 1 o 2 se redirigen con el controlador 3 (y posiblemente con los controles 4 a 9), la redirección de los identificadores 0, 1 o 2 pasa a ser "permanente"; este comportamiento no ocurre si el identificador 0, 1 o 2 son los últimos identificadores en la lista de redirecciones que incluyen el identificador 3. Este problema se evita completamente si los identificadores 0, 1 o 2 se redirigen con los identificadores 4-9 en cualquier orden, pero no manejar 3.
3- Los resultados obtenidos con mi programa TypeOfHandle.com . Este programa es un archivo ejecutable puro de MS-DOS que verifica el identificador proporcionado en su parámetro y devuelve a través de errorlevel un valor de 3 si el identificador está conectado al dispositivo CONsole, o un valor de 128 si el identificador se redirige a un archivo de disco . Estos son los resultados:
C>typeofhandle 0
C>echo %errorlevel%
3
C>typeofhandle 0 < anyFile.txt
C>echo %errorlevel%
128
C>typeofhandle 1
C>echo %errorlevel%
3
C>typeofhandle 1 > anyFile.txt
C>echo %errorlevel%
128
C>typeofhandle 3
C>echo %errorlevel%
0
C>typeofhandle 3 <&3 anyFile.txt
C>echo %errorlevel%
0
C>typeofhandle 3 >&3 anyFile.txt
C>echo %errorlevel%
0
Las manijas 3-9 se comportan de manera extraña en otros aspectos:
Los resultados obtenidos con mi programa SetFilePointer.com . Aunque los identificadores 3-9 se pueden usar en un archivo por lotes para lograr la entrada / salida de / a varios archivos a la vez, dicho mecanismo solo permite el acceso secuencial porque mi programa SetFilePointer no puede mover el puntero de archivo de los identificadores 3-9. El programa SetFilePointer funciona correctamente en los controles 0, 1 y 2; esta característica permite escribir una aplicación completa de Base de datos relacionales en Batch. Este tema se describe en detalle en esta publicación