2014-12-12 12 views
6

Ich schreibe gerade ein Skript in Powershell, das das Kopieren eines Ordners in einem SVN-Repository zu einem anderen ermöglicht, während der Verlauf beibehalten wird. Ein Beispiel für einen solchen Befehl lautet:Powershell-Piping verursacht explosiven Speicherverbrauch

svnadmin.exe dump $FromRepoPath ` 
    | svndumpfilter.exe include --drop-empty-revs --renumber-revs --preserve-revprops $Folder ` 
    | svnadmin.exe load --ignore-uuid $ToRepoPath 

Dies verursacht eine sehr hohe Speicherauslastung in Powershell. Es scheint, dass Powershell zuerst svnadmin.exe ausführt und das stdout von SVN admin puffert, dann svndumpfilter ausführt und diese Ausgabe puffert und schließlich svnadmin.exe ausführt.

Ich kann es umgehen, indem eine separate Batch-Datei zu erstellen:

@echo off 
svnadmin.exe dump %1 | svndumpfilter.exe include --drop-empty-revs --renumber-revs --preserve-revprops %2 | svnadmin.exe load --ignore-uuid %3 

Und dann ist es von Powershell-Aufruf:

cmd.exe /c "SvnHelper.cmd $FromRepoPath $Folder $ToRepoPath" 

Aber das fühlt sich an wie eine böse und unnötige Abhilfe.

Gibt es eine Möglichkeit, Powershell beim Piping direkt zu übergeben, anstatt es zu puffern?

+0

Versuchen 'svnadmin.exe ... | out-string | svnfilter.exe ... '? Dies kann Powershell dazu verleiten, jede Zeile zu pipen, anstatt alles zu sammeln. Ich habe kein SVN und weiß es auch nicht, also entschuldige mich, wenn das schrecklich bricht. – Eris

Antwort

2

Es wird nicht die Ausgabe gepuffert, sondern die Eingabe in einen externen Prozess.

function Read-Pipeline { 
[cmdletbinding()] 
param ([Parameter(Mandatory = $true, ValueFromPipeline=$true)] $inp) 
    Begin {} 
    Process {Write-Verbose $inp ; Return $inp} 
    End {} 
} 

Wenn Sie dann ausführen: Sie können das Verhalten mit einer Funktion wie dies überprüfen

.\LongRunning.exe | Read-Pipeline -Verbose | .\Other.exe 

Sie werden die LongRunning.exe die Ausgabe in Ausführlich sehen aber Other.exe werden nicht ausgeführt werden bis seine Pipeline geschlossen ist. Wenn Sie dies tun:

.\LongRunning.exe | Read-Pipeline -Verbose | Write-Host 

Sie werden sehen, abwechselnd Verbose/Console Ausgangsleitungen ohne Pufferung, da Eingaben nicht Prozessgrenzen überqueren.

Nichts davon hilft Ihnen wirklich. Sie können dies umgehen, indem Sie auf .NET zurückgreifen, um die Prozesse zu starten und STDOUT manuell in STDIN [1] zu kopieren, aber es ist eine Menge Arbeit für wenig Belohnung. Die einfachste Sache zu tun wäre, geben Ihre Befehle CMD, so etwas wie:

& cmd.exe "/C svnadmin.exe dump $FromRepoPath ^| svndumpfilter.exe include --drop-empty-revs --renumber-revs --preserve-revprops $Folder ^| svnadmin.exe load --ignore-uuid $ToRepoPath 

[1] http://sushihangover.blogspot.com/2012/01/powershell-piping-standard-output-to.html

+0

Danke, das ist genau das, was ich befürchtet habe. Was macht "| ^" in Ihrem Beispiel? – Sebazzz

+0

^| entgeht dem | Zeichen, das notwendig ist, weil es als Parameter an cmd.exe übergeben wird. http://ss64.com/nt/syntax-esc.html – tby