It *_* Me 4 windows batch command-line cmd.exe
最终,我move nul 2>&0
在脚本中使用“突然”关闭 cmd 窗口的当前,从而立即中止/关闭正在运行的 bat。
我不能说它在剧本中像自杀一样,但我通常称之为。
事实上,这会导致在当前 cmd 窗口中扩展/达到效果的自动终止。
这不仅仅是关闭/结束正在运行的蝙蝠。
基本上用于某些批处理,其中"%cmdcmdline%"
通过单击调用执行响应的变量值,而不是简单地关闭 bat,还关闭通过单击 bat 激活/加载的窗口。
我想知道的是:
1.什么解释了这种行为?
2.这是一个错误吗?
3.将来它的行为可能不一样吗?
一些代码示例:
@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
Run Code Online (Sandbox Code Playgroud)
dbe*_*ham 10
我对您的短语“当前 cmd 窗口”感到困惑-不确定您的意思。在我看来,你结合了两个不同的概念
您的命令使 cmd.exe 进程崩溃,并且您的控制台进程干净利落地关闭,因为它不再有在其中运行的进程。
如果您在额外的子 cmd.exe 进程中运行命令,这很容易证明 - 子 cmd.exe 崩溃,但父进程仍然有效,因此控制台窗口也保持运行。这是一个从在控制台中运行的全新 cmd.exe 进程开始的示例。
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:\>
Run Code Online (Sandbox Code Playgroud)
最后context=outer,证明内部环境丢失了,原因是内部进程崩溃了。如果我随后发出 EXIT 命令,则外部 cmd.exe 进程将终止并关闭控制台。
现在了解为什么您的命令会导致 cmd.exe 崩溃。您对MOVE
命令或nul
设备的使用没有什么特别之处。关键是 cmd.exe 在重定向到 stdin 后试图将错误消息写入 stderr。显然这是行不通的,所以写入失败——这是导致 cmd.exe 崩溃的触发器。
可以通过零误差除法实现相同的效果SET /A 1/0 2>&0
。
重要的是要注意重定向实际上是成功的。重定向并不关心标准输入不能接受输出,它盲目地进行重定向。仅当 cmd.exe 错误写入例程尝试实际写入重定向的 stderr 时才会发生故障。
如果您只是重定向不写入 stderr 的命令,则很容易证明重定向成功。例如,echo Hello world 2>&0
执行无意义的重定向并将消息成功写入标准输出。
在 DosTips 的某个地方,我有一些帖子研究了 cmd.exe 如何处理 I/O 错误。我希望我能找到那个帖子。我相信我的测试涉及将 stdout 或 stderr 重定向到可移动设备,然后暂停。在暂停期间,我会移除设备,然后继续。然后,当我尝试通过 stdout 或 stderr 写入丢失的设备时,我会观察行为。据我所知,所有失败的写入 stderr 都会立即使 cmd.exe 崩溃。
这是错误还是设计缺陷?没有把握。有人可能会争辩说,如果错误报告失败,最安全的做法可能是终止。但我不相信这是一个计划中的“功能”,因为当写入 stdout 失败时,没有任何错误消息或错误返回!输出只是消失在以太中,cmd.exe 愉快地继续,好像没有发生任何不好的事情。写入标准输出时,批处理不可能检测到故障。我觉得那太残忍了。我只能假设 cmd.exe 的开发人员从来没有考虑过这种可能性。因此,如果这是真的,那么 stderr 失败崩溃的事实很容易成为(快乐?)事故。
stdout 和 stderr 行为之间还有一些其他差异。两者都是缓冲的,但如果出现缓冲区溢出,它们的行为会有所不同。我希望我能记住这种区别是什么:-(
更新
我在https://www.dostips.com/forum/viewtopic.php?t=6881找到了我的一些调查
写入标准输出比我上面的文章所暗示的要复杂一些。Cmd.exe 有多个尝试写入标准输出的内部例程。例如:
当写入失败时,其中一些写入 stdout 的入口点可能有自己的行为。例如,我上面的链接描述了 ECHO 和 SET /P 之间的差异。
我不确定,但我相信 stderr 的错误消息是不同的。我相信所有错误报告都是通过一个内部例程汇集的,当出现写入错误时该例程会崩溃。我上面的链接并没有真正调查这个。我仍在寻找更晚的帖子,更好地调查 I/O 错误(和缓冲问题)
归档时间: |
|
查看次数: |
1041 次 |
最近记录: |