我正在尝试将输出日志通过管道传输到另一个脚本进行处理。但是,如果我正确理解这个问题,powershell 会等待第一个命令完成,然后再将输出发送到第二个命令。
例如,这按预期工作(脚本收到“hi”),因为echo很快完成:
echo "hi" | python script.py
Run Code Online (Sandbox Code Playgroud)
而在这个(caddy是网络服务器,所以它没有完成)中,球童的标准输出永远不会到达脚本的标准输入:
caddy run | python script.py
Run Code Online (Sandbox Code Playgroud)
是否可以将第一个命令的输出异步转发到第二个命令,而无需等待第一个命令完成?
--
编辑:最小的例子
echo "hi" | python script.py
Run Code Online (Sandbox Code Playgroud)
caddy run | python script.py
Run Code Online (Sandbox Code Playgroud)
# output.py
from time import sleep
while True:
print("SENDING")
sleep(1)
Run Code Online (Sandbox Code Playgroud)
这有效(打印到 stdout Received: SENDING):
python onetime.py | python input.py
Run Code Online (Sandbox Code Playgroud)
这不起作用(没有打印任何内容):
python output.py | python input.py
Run Code Online (Sandbox Code Playgroud)
的确:
在Windows PowerShell中,当管道传输到外部程序时,输入命令的输出是意外的:
首先在内存中完整收集
并且仅在输入命令退出后,收集的输出才会通过管道传递。
幸运的是,这个问题已在PowerShell (Core) 7+中得到修复,输入命令的输出现在像往常一样,在行可用时逐行进行流式传输。(如果接收命令是PowerShell命令,这也是它在 Windows PowerShell 中的工作方式。)
一个简单的例子:
请注意,提供输入的命令是 PowerShell 命令还是外部程序并不重要- 重要的是接收命令是外部程序
示例输入命令输出 3 个数字,一次一个,每个数字后等待 1 秒,最后等待用户按下Enter才退出。
接收命令findstr.exe .简单地回显每个数字。
# In Windows PowerShell:
# 3 seconds elapse without anything getting printed, because PowerShell
# is collecting the output first.
# Then the user is prompted to press Enter.
# Only if and when the user does so do the numbers print.
# In PowerShell 7+:
# The numbers print as they are being emitted by the ForEach-Object call, and
# only then is the user prompted to press Enter.
1..3 | ForEach-Object { $_; sleep 1 } -end { pause } | findstr.exe .
Run Code Online (Sandbox Code Playgroud)
解决方法:
cmd.exe通过的 CLI调用( cmd /c),因为cmd.exe的管道行为符合预期(在类Unix平台上,类似地使用sh -c):
cmd /c 'caddy run | python script.py'
Run Code Online (Sandbox Code Playgroud)
实际上:
cmd.exe的 ( /bin/sh's) 管道是一个原始字节管道,与 PowerShell 的管道不同,从 v7.3.4 开始“只讲文本”
因此,在需要将原始字节数据发送到/外部程序之间/发送到文件的情况下,也需要上述解决方法 - 请参阅此答案。
| 归档时间: |
|
| 查看次数: |
299 次 |
| 最近记录: |