¿Sería eso un error? Cierre inmediato de la ventana cmd actual al ejecutar: mover nul 2>&0

¿Sería eso un error? Cierre inmediato de la ventana cmd actual al ejecutar: mover nul 2>&0

Al final usomove nul 2>&0en mis scripts para cerrar "abruptamente" la ventana actual de cmd y, por lo tanto, abortar/cerrar inmediatamente el bat en ejecución.

No puedo decir que funcione como un suicidio en el guión, pero normalmente lo llamo así.

De hecho, esto da como resultado una eliminación automática que se extiende/alcanza el efecto también en la ventana cmd actual.

Es algo más que simplemente cerrar/terminar un bate en carrera.

Básicamente se usa para algunos lotes donde el valor de la variable"%cmdcmdline%"a una respuesta ejecutando invocado por clic, en lugar de simplemente cerrar el murciélago, cerrando también la ventana que se activó/cargó al hacer clic en el murciélago.

Lo que me pregunto es:

  1. ¿Qué explica este comportamiento?
  2. ¿Es un error?
  3. ¿En el futuro puede que no se comporte igual?

Algunos códigos de muestra:

@echo off 

title <nul 
title to kill or not to kill?

mode 50,05

echo\%cmdcmdline%|find "%~0" >nul && (
     echo\
     echo\ so sorry bro, I'll kill myself
     echo\ and this CMD.exe window too!
     
     timeout 5 /nobreak 
     move nul 2>&0 
   )

echo/ will run this code bro!
echo/
echo/ keep itself alive: %date% %time:~0,5%
echo/
pause

Respuesta1

Lucho con tu frase "ventana cmd actual"; no estoy seguro de lo que quieres decir. En mi opinión estás combinando dos conceptos distintos.

  • Existe el proceso de consola, análogo, pero no exactamente igual, a una terminal.
  • Y está el proceso cmd.exe que se está ejecutando dentro de la ventana de la consola.

Su comando está bloqueando el proceso cmd.exe y el proceso de su consola se cierra limpiamente porque ya no tiene un proceso ejecutándose dentro de él.

Esto es fácil de comprobar si ejecuta su comando dentro de un proceso cmd.exe secundario adicional: el cmd.exe secundario falla, pero el principal sigue siendo válido, por lo que la ventana de la consola también permanece ejecutándose. A continuación se muestra un ejemplo a partir de un nuevo proceso cmd.exe que se ejecuta en la consola.

Microsoft Windows [Version 10.0.18363.1256]
(c) 2019 Microsoft Corporation. All rights reserved.

P:\>set context=outer

P:\>cmd
Microsoft Windows [Version 10.0.18363.1256]
(c) 2019 Microsoft Corporation. All rights reserved.

P:\>set context=inner

P:\>move nul 2>&0

P:\>set context
context=outer

P:\>

El hecho de que contexto = exterior al final prueba que el entorno interior se ha perdido, la razón es que el proceso interior se ha estrellado. Si luego emito el comando EXIT, el proceso externo cmd.exe finaliza y la consola se cierra.

Ahora veamos por qué su comando falla cmd.exe. No hay nada especial en el uso del MOVEcomando o del nuldispositivo. La parte crítica es que cmd.exe intenta escribir un mensaje de error en stderr después de haber sido redirigido a stdin. Obviamente, eso no puede funcionar, por lo que la escritura falla; este es el desencadenante que hace que cmd.exe falle.

El mismo efecto se puede lograr con el error de división por cero mediante SET /A 1/0 2>&0.

Es importante señalar que la redirección realmente se realiza correctamente. A Redirect no le importa que la entrada estándar no pueda aceptar la salida, realiza la redirección a ciegas. El error se produce sólo cuando la rutina de escritura de errores cmd.exe intenta escribir en el stderr redirigido.

Es fácil demostrar que la redirección tiene éxito si simplemente redirige un comando que no escribe en stderr. Por ejemplo, echo Hello world 2>&0realiza una redirección sin sentido y escribe correctamente el mensaje en la salida estándar.

En algún lugar de DosTips tengo algunas publicaciones en las que investigué cómo cmd.exe maneja los errores de E/S. Ojalá pudiera encontrar esa publicación. Creo que mi prueba implicó redirigir stdout o stderr a un dispositivo extraíble y luego hacer una pausa. Durante la pausa, quitaba el dispositivo y luego continuaba. Luego observaba el comportamiento cuando intentaba escribir en el dispositivo faltante mediante stdout o stderr. Por lo que recuerdo, todas las escrituras fallidas en stderr bloquean inmediatamente cmd.exe.

¿Es esto un error o un defecto de diseño? No estoy seguro. Se podría argumentar que quizás lo más seguro si falla el informe de errores es terminar. Pero no estoy convencido de que fuera una "característica" planificada porque cuando falla la escritura en la salida estándar, no aparece ningún mensaje de error ni se devuelve ningún error. La salida simplemente desaparece en el éter, cmd.exe continúa alegremente como si nada malo hubiera pasado. Es imposible que el lote detecte fallas al escribir en la salida estándar. Eso me parece atroz. Sólo puedo asumir que los desarrolladores de cmd.exe nunca se molestaron en considerar esa posibilidad. Entonces, si eso es cierto, entonces el hecho de que las fallas estándar fallen podría ser fácilmente un (¿feliz?) accidente.

Hubo algunas otras diferencias entre el comportamiento stdout y stderr. Ambos están almacenados en búfer, pero se comportaron de manera diferente si hubo un desbordamiento del búfer. Ojalá pudiera recordar cuál era esa diferencia :-(

Actualizar

Encontré algunas de mis investigaciones enhttps://www.dostips.com/forum/viewtopic.php?t=6881

Escribir en stdout es un poco más complicado de lo que implica mi artículo anterior. Cmd.exe tiene varias rutinas internas que intentan escribir en la salida estándar. Por ejemplo:

  • comando ECO
  • Mensaje SET /P (solicita entrada)
  • La línea de comando y el eco de la línea de comando por lotes (cuando ECHO está activado)
  • Salida de comandos como DIR, etc.

Algunos de estos puntos de entrada que escriben en la salida estándar pueden tener su propio comportamiento cuando se produce un error de escritura. Mi enlace anterior describe las diferencias entre ECHO y SET /P, por ejemplo.

No estoy seguro, pero creo que los mensajes de error de stderr son diferentes. Creo que todos los informes de errores se canalizan a través de una única rutina interna que falla cuando hay un error de escritura. Mi enlace anterior realmente no investiga esto. Todavía estoy buscando publicaciones posteriores que investigaron mejor los errores de E/S (y los problemas de almacenamiento en búfer)

información relacionada