【问题标题】:How to Prevent Powershell from "Caching" Piped Data如何防止 Powershell “缓存”管道数据
【发布时间】:2014-09-24 18:25:38
【问题描述】:

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

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

【问题讨论】:

  • & 运算符是处理带有空格的命令和参数时的噩梦。您可以尝试将 7zip 表达式放在括号内或脚本块中并尝试执行。
  • 要去掉&运算符,试试New-Alias 7z "C:\Program Files\7-Zip\7z.exe",然后你可以用7z代替& "C:\Program Files\7-Zip\7z.exe"
  • 这是一个非常有趣的问题。我尝试将 35MB 的文本文件通过管道传输到 7z,而 PowerShell 使用 500MB 的 RAM 来完成。

标签: powershell pipe powershell-2.0


【解决方案1】:

这更像是一个建议而不是一个解决方案,但它可能会对您的情况有所帮助。我对此进行了很多试验,但在将数据全部加载到内存(然后是一些)之前,我无法将数据刷新到 7z。我的预感是,当您使用管道时,“普通”shell 会获取第一个命令的标准输出并将其流式传输到第二个命令的标准输入。使用 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 应该在你的路径中,所以它应该可以正常工作。它在我的机器上要快得多,而且几乎没有内存。

【讨论】:

  • 很好的信息。尝试使用 CMD 方法,但它仍然对我不起作用,因为 PowerShell 执行了一些不需要的解析。 CMD /C "svnadmin dump ... 有效(当命令在我的路径中时),但 CMD /C """C:\Program Files (x86)\VisualSVN Server\bin\svnadmin.exe"" dump ... 无效(错误“...无法识别为内部或外部命令...”)。
  • 作为旁注,我偶然发现了 PowerShell 的停止解析符号 --%,这可能有帮助,但它在 v2.0 中不起作用。
猜你喜欢
  • 2013-05-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-02-12
  • 2011-12-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多