windows - 在进程完成之前,Windows cmd.exe 中的管道不会转发标准输出?

标签 windows batch-file delay pipe buffered

考虑 Windows 命令 shell cmd.exe 中的管道:

C:\>feed | filter

直到馈送过程运行完成之后,馈送过程的标准输出似乎才达到过滤过程的标准输入。

这种类型的“缓冲”可能会导致长时间运行的馈送进程的输出消息出现烦人的延迟(您可能希望在早期失败时按“ctrl-c”来中断它)。

有没有办法避免这种情况,以便一旦数据可用,馈送过程的标准输出就达到过滤过程的标准输入? (无缓冲)

例如下面的简化示例:

feed.bat:

@echo off
echo something
sleep 3
echo something else

过滤器.bat:

@echo off
for /F "tokens=*" %%a in ('more') do (
    echo _%%a
)

以下命令在 3 秒后( sleep 完成时)才会显示任何内容:

C:\>feed | filter
_something
_something else

期望的行为是打印“_something”,然后延迟 3 秒,然后打印“_something else”。

最佳答案

Windows cmd.exe 中的管道是异步的。他们不会等待左侧完成后再将信息传递到右侧。但由于两个原因,您的程序并未证明这一点。

1) FOR/F 命令在 IN() 子句中的命令完成之前不会开始迭代任何行。对于所有 FOR/F 变体都是如此。 IN() 子句的整个结果在迭代任何行之前被缓冲。

所以你的filter.bat不可能展示管道的异步特性。

2) MORE 命令不会写入部分行 - 它会等到收到换行符后再打印到标准输出。 (除非它到达文件末尾)。

如果您想真正了解管道的异步特性,最好使用从 stdin 读取每个字符并立即将其写回 stdout 的程序。

<小时/>

这是我的 FEED.BAT 版本 - 它会写入带有多个暂停的多行。它还会在不换行的情况下写入三个字符,每个字符后有一个暂停。

@echo off
echo something
timeout /nobreak 3 >nul
echo something else
timeout /nobreak 3 >nul
for /l %%N in (1 1 3) do (
  <nul set /p "=%%N"
  timeout /nobreak 3 >nul
)
echo(
echo Done

这是我的 FILTER.JS 版本 - 它从 stdin 读取一个字符并将其写入 stdout,直到到达文件末尾。

while (!WScript.StdIn.AtEndOfStream) WScript.Stdout.Write(WScript.StdIn.Read(1));

这是测试行为的命令

feed | cscript //nologo filter.js

这是输出,其中 <pause>每当更多输出之前有暂停时就插入。

something
<pause>something else
1<pause>2<pause>3<pause>
Done
<小时/>

我上面的测试表明管道将立即发送它收到的任何信息(假设过滤器已准备好接收它)。

进料器和/或过滤器的设计可能会掩盖自由流动行为。您最初的测试在过滤器中存在瓶颈,因为它在继续之前等待所有输入。喂食器也可以支撑东西。有些程序有缓冲输出。在缓冲区已满、缓冲区被刷新或流关闭之前,馈送器可能不会发送数据。

有许多与 Windows 管道相关的特殊行为。我建议阅读 Why does delayed expansion fail when inside a piped block of code? 的所有答案对许多非直观问题有一个很好的概述。

关于windows - 在进程完成之前,Windows cmd.exe 中的管道不会转发标准输出?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21566707/

相关文章:

python - 删除 Tkinter 中的最小化/最大化按钮

c++ - UnicodeString 到 char* (UTF-8)

batch-file - 批处理If/Else语法错误

php - 多次刷新页面时读取文件变慢

windows - 使用 Makefile 创建 DLL 以在 Windows XP(32 位)和 Windows 7(64 位)上运行

在 XP 中从隐藏或剪切的窗口复制内容?

batch-file - 当另一个命令正在处理时在后台运行命令?

batch-file - 带有空字符串的子字符串扩展会导致 If 子句出错

jQuery 仅当鼠标按住元素时才激活鼠标悬停功能

android - 添加延迟以开始等待 admob 显示插页式广告的 Activity