Wäre das ein Fehler? Sofortiges Schließen des aktuellen Cmd-Fensters bei der Ausführung: move nul 2>&0

Wäre das ein Fehler? Sofortiges Schließen des aktuellen Cmd-Fensters bei der Ausführung: move nul 2>&0

Schließlich benutze ichmove nul 2>&0in meinen Skripten, um das aktuelle Cmd-Fenster „abrupt“ zu schließen und somit den laufenden Bat sofort abzubrechen/zu schließen.

Ich kann nicht sagen, dass es im Drehbuch wie ein Selbstmord wirkt, aber ich nenne es normalerweise so.

Tatsächlich führt dies zu einem Auto-Kill, der auch im aktuellen Befehlsfenster wirksam wird.

Es ist etwas anderes als nur das Schließen/Beenden eines laufenden Schlags.

Grundsätzlich verwenden Sie für einige Stapel, bei denen der Wert der Variablen"%cmdcmdline%"auf eine Reaktion durch Ausführen der per Klick aufgerufenen Aktion, wobei nicht nur der Bat geschlossen wird, sondern auch das Fenster geschlossen wird, das durch den Klick auf den Bat aktiviert/geladen wurde.

Was ich mich frage ist:

  1. Was erklärt dieses Verhalten?
  2. Ist es ein Fehler?
  3. Könnte es in Zukunft nicht genauso sein?

Einige Codebeispiele:

@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

Antwort1

Ich habe Probleme mit Ihrem Ausdruck „aktuelles cmd-Fenster“ – ich bin mir nicht sicher, was Sie meinen. Meiner Meinung nach kombinieren Sie zwei unterschiedliche Konzepte

  • Es gibt den Konsolenprozess - analog zu, aber nicht ganz dasselbe wie ein Terminal
  • Und es gibt den Prozess cmd.exe, der im Konsolenfenster ausgeführt wird

Ihr Befehl bringt den Prozess cmd.exe zum Absturz und Ihr Konsolenprozess wird ordnungsgemäß beendet, da kein Prozess mehr darin ausgeführt wird.

Dies lässt sich leicht beweisen, wenn Sie Ihren Befehl in einem zusätzlichen untergeordneten cmd.exe-Prozess ausführen – das untergeordnete cmd.exe stürzt ab, aber das übergeordnete cmd.exe bleibt gültig, sodass auch das Konsolenfenster weiterhin ausgeführt wird. Hier ist ein Beispiel, das mit einem brandneuen cmd.exe-Prozess beginnt, der in der Konsole ausgeführt wird.

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:\>

Dass am Ende context = outer steht, beweist, dass die innere Umgebung verloren gegangen ist, weil der innere Prozess abgestürzt ist. Wenn ich dann den EXIT-Befehl abgebe, dann beendet sich der äußere cmd.exe-Prozess und die Konsole schließt sich.

Nun zu der Frage, warum Ihr Befehl cmd.exe zum Absturz bringt. Es ist nichts Besonderes an Ihrer Verwendung des MOVEBefehls oder des nulGeräts. Der kritische Teil ist, dass cmd.exe versucht, eine Fehlermeldung an stderr zu schreiben, nachdem es an stdin umgeleitet wurde. Das kann offensichtlich nicht funktionieren, also schlägt der Schreibvorgang fehl – ​​das ist der Auslöser, der den Absturz von cmd.exe verursacht.

Der gleiche Effekt kann mit einem Division-durch-Null-Fehler über erzielt werden SET /A 1/0 2>&0.

Es ist wichtig zu beachten, dass die Umleitung tatsächlich erfolgreich ist. Redirect kümmert sich nicht darum, dass stdin keine Ausgabe akzeptieren kann, es führt die Umleitung blind aus. Der Fehler tritt nur auf, wenn die Fehlerschreibroutine von cmd.exe tatsächlich versucht, in das umgeleitete stderr zu schreiben.

Es lässt sich leicht nachweisen, dass die Umleitung erfolgreich ist, wenn Sie einfach einen Befehl umleiten, der nicht nach stderr schreibt. Führt beispielsweise echo Hello world 2>&0die unsinnige Umleitung aus und schreibt die Nachricht erfolgreich nach stdout.

Irgendwo auf DosTips habe ich einige Beiträge, in denen ich untersucht habe, wie cmd.exe mit E/A-Fehlern umgeht. Ich wünschte, ich könnte diesen Beitrag finden. Ich glaube, mein Test beinhaltete die Umleitung von stdout oder stderr auf ein entfernbares Gerät und dann eine Pause. Während der Pause entfernte ich das Gerät und fuhr dann fort. Ich beobachtete dann das Verhalten, als ich versuchte, über stdout oder stderr auf das fehlende Gerät zu schreiben. Soweit ich mich erinnere, stürzten alle fehlgeschlagenen Schreibvorgänge auf stderr cmd.exe sofort ab.

Ist das ein Fehler oder ein Konstruktionsfehler? Ich bin mir nicht sicher. Man könnte argumentieren, dass das Beenden das Sicherste ist, wenn die Fehlerberichterstattung fehlschlägt. Aber ich bin nicht überzeugt, dass das eine geplante „Funktion“ war, denn wenn das Schreiben auf stdout fehlschlägt, wird weder eine Fehlermeldung noch ein Fehler zurückgegeben! Die Ausgabe verschwindet einfach im Äther, cmd.exe macht munter weiter, als wäre nichts Schlimmes passiert. Es ist für Batch unmöglich, Fehler beim Schreiben auf stdout zu erkennen. Ich finde das grauenhaft. Ich kann nur annehmen, dass die Entwickler von cmd.exe sich nie die Mühe gemacht haben, diese Möglichkeit in Betracht zu ziehen. Wenn das also stimmt, dann könnte die Tatsache, dass stderr-Fehler zum Absturz führen, leicht ein (glücklicher?) Zufall sein.

Es gab noch weitere Unterschiede zwischen dem Verhalten von stdout und stderr. Beide sind gepuffert, aber sie verhielten sich bei einem Pufferüberlauf unterschiedlich. Ich wünschte, ich könnte mich daran erinnern, was dieser Unterschied war :-(

Aktualisieren

Einige meiner Untersuchungen fand ich beihttps://www.dostips.com/forum/viewtopic.php?t=6881

Das Schreiben auf stdout ist etwas komplizierter, als es meine Beschreibung oben vermuten lässt. Cmd.exe hat mehrere interne Routinen, die versuchen, auf stdout zu schreiben. Zum Beispiel:

  • ECHO-Befehl
  • SET /P-Meldung (Aufforderung zur Eingabe)
  • Die Eingabeaufforderung und das Echo der Batch-Befehlszeile (wenn ECHO eingeschaltet ist)
  • Ausgabe von Befehlen wie DIR usw.

Einige dieser Einstiegspunkte, die in die Standardausgabe schreiben, können bei einem Schreibfehler ein eigenes Verhalten aufweisen. Mein Link oben beschreibt beispielsweise die Unterschiede zwischen ECHO und SET /P.

Ich bin mir nicht sicher, aber ich glaube, dass die Fehlermeldungen an stderr anders sind. Ich glaube, dass alle Fehlerberichte durch eine einzige interne Routine geleitet werden, die abstürzt, wenn ein Schreibfehler auftritt. Mein Link oben untersucht dies nicht wirklich. Ich suche immer noch nach den viel späteren Beiträgen, in denen die E/A-Fehler (und Pufferprobleme) besser untersucht wurden.

verwandte Informationen