如何防止Powershell"缓存"管道数据

时间:2014-09-24 18:25:39

标签: powershell pipe powershell-v2.0

我在命令窗口中执行以下命令:

"C:\Program Files (x86)\VisualSVN Server\bin\svnadmin.exe" dump --quiet "C:\svnrepo" | "C:\Program Files\7-Zip\7z.exe" a -si "C:\svnbak.7z"

这会将我的SVN存储库的内容转储到一个接受的7-zip实例中,该实例将压缩的内容写入磁盘。当命令运行时,我可以观察7z文件的增加,直到它完成。

尝试使用Powershell v2脚本时,我altered it来:

& "C:\Program Files (x86)\VisualSVN Server\bin\svnadmin.exe" dump --quiet "C:\svnrepo" | "C:\Program Files\7-Zip\7z.exe" a -si "C:\svnbak.7z"

它抱怨说“表达式只允许作为管道的第一个元素”。基于另一个SO answer,我将命令改为:

& "C:\Program Files (x86)\VisualSVN Server\bin\svnadmin.exe" dump --quiet "C:\svnrepo" | & "C:\Program Files\7-Zip\7z.exe" a -si "C:\svnbak.7z"

Powershell脚本似乎正在运行,但是没有看到文件被慢慢写入,只有我的内存增加。我假设没有将内容写入7-zip进程,Powershell正在“缓存”内容,直到转储完成。转储完成后,内容将被推送到7-zip。反正是为了防止这种情况发生(为了获得与初始命令相同的结果)?

1 个答案:

答案 0 :(得分:1)

这是一个建议而非解决方案,但它可能会对您的情况有所帮助。我试验了很多,我无法将数据刷新到7z,直到它全部加载到内存中(然后是一些)。我的预感是“普通”shell获取第一个命令的stdout并在使用管道时将其流式传输到第二个命令的stdin。使用PowerShell,一切都是对象。所以它试图传递对象并且不知道要传递什么类型的对象,直到它全部被加载。如果你的第一个命令产生了一个字符串数组,而第二个命令可以从管道中使用一个数组,它可能会按预期工作。

以下是部分解决方案:

New-Alias svnadmin "C:\Program Files (x86)\VisualSVN Server\bin\svnadmin.exe"
New-Alias 7z "C:\Program Files\7-Zip\7z.exe"
svnadmin dump --quiet "C:\svnrepo" > snvdump.txt 
Get-Content svndump.txt | 7z a -si "C:\svnbak.7z"

这使用大约1/5的内存作为表单解决方案,但仍然超过它应该。在全部加载之前,它也不会将数据刷新到7z,因此可能无法正常工作,具体取决于转储的大小。


更新:由于它适用于CMD而不是PowerShell(而svnadmin和7z是控制台应用而非cmdlet),为什么不直接调用CMD?

 CMD /C """C:\Program Files (x86)\VisualSVN Server\bin\svnadmin.exe"" dump --quiet ""C:\svnrepo"" | ""C:\Program Files\7-Zip\7z.exe"" a -si ""C:\SourceCode\svnbak.7z"""

注意,我的机器上没有svn,所以我用大文本文件做了:

CMD /C "type files.txt | ""C:\Program Files\7-Zip\7z.exe"" a -si ""C:\SourceCode\svnbak.7z"""

CMD应该在你的道路上,所以它应该有效。它在我的机器上要快得多,并且在没有内存的情况下使用。