2016-04-23 7 views
0

Ich arbeite mit einem Skript, das in eine Reihe von Servern funkt und Befehle aus einer Reihe von PoSh-Funktionen ausführt. Ich muss die synchrone Verarbeitung beibehalten und möchte einfach die Möglichkeit hinzufügen, eine asynchrone Operation für die Funktion auszuführen.Arbeiten mit Invoke-Command/Start-Job und PSRemoting

Wie kann ich dies so transformieren, dass es als Job von einer primären Funktion mit Start-Job oder Invoke-Command -AsJob aufgerufen wird? Diese Funktionen sind Teil eines PowerShell-Moduls, wenn dies einen Unterschied macht.

Ich habe ein paar verschiedene Beispiele ausprobiert, die ich hier gesehen habe, aber sie scheinen die Funktion nicht wirklich zu verarbeiten.

Zum Beispiel für die unten Funktion habe ich versucht:

foreach($s in $servers) 
{ 
      if($lbFileLocation -eq $true) 
      { 
       #Rename-LoadBalancerFile -ServerName $server -Revert $false -filePath $filePath -cred $cred - #sync function works great 
       Start-Job -Name 'RenLb' -InitializationScript {Import-Module '.\Down.psm1'} $ScriptBlock -ArgumentList $server,$false,$lbFileLocation,$Cred | Out-Null 
      } 
} 

     Write-Host 'Waiting for LB rename.' 
     While (Get-Job -Name 'RenLb' | where { $_.State -eq 'Running' }) 
       { 
        Start-Sleep 1 
       } 

      Write-Host 'completed' 

Original-Synchronfunktion:

function Rename-LoadBalancerFile 
{ 
    param 
    (
     [string] 
     [Parameter(Mandatory=$true)] 
     $ServerName, 
     [bool] 
     [Parameter(Mandatory=$true)] 
     $Revert, 
     [string] 
     [Parameter(Mandatory=$true)] 
     $filePath, 
     [PSCredential] 
     [Parameter(Mandatory=$false)] 
     $cred 
    ) 

    $scriptBlock = { 
     param 
     (
      [bool] 
      [Parameter(Mandatory=$true)] 
      $Revert, 
      [string] 
      [Parameter(Mandatory=$true)] 
      $filePath 
     ) 

     if(Test-Path $filePath -eq $true) 
     { 
      Write-Host 'file tested true' 
      if($Revert -eq $true) 
      { 
       $fileName = [IO.Path]::GetFileName($filePath) 
       $directory = [IO.Path]::GetDirectoryName($filePath) 

       Rename-Item -Path "$directory\file.txt" -NewName $fileName 
      } 
      else 
      { 
       Rename-Item -Path $filePath -NewName 'file.txt' 
      } 
     } 
    } 

    $session = New-PSSession -ComputerName $ServerName -Authentication Credssp -Credential $cred 
    Invoke-Command -Session $session -ScriptBlock $scriptBlock -ArgumentList $Revert, $filePath 
    Remove-PSSession $session 
} 
+1

Kann es nicht atm testen. aber ich denke, Sie sollten 'new-session',' invoke-command' und 'remove-session' mit' Invoke-Command -ScriptBlock {} -ArgumentList $ Revert, $ filePath -ComputerName $ ServerName -Authentication Credssp - ersetzen können. Credential $ cred' –

+0

Für innerhalb der Funktion? Wenn es die Sitzung automatisch öffnet/schließt, sollte das in Ordnung sein. Aber wird das tatsächlich das Problem lösen, das ich erlebe? –

+0

Es löst das Problem nicht. Deshalb ist es ein Kommentar. :-) nur ein Tipp –

Antwort

1
  1. Import-Module .\down.psm1 wird wahrscheinlich scheitern, weil Start-Job nicht das gleiche hat Arbeitsverzeichnis als Ihr Skript, so müssen Sie entweder das Arbeitsverzeichnis ändern oder den absoluten Pfad zum Modul verwenden.
  2. Was ist $scriptblock in Start-Job? Es wurde nie erstellt. Denken Sie daran, dass $scriptblock$args[0] , $args[1] .. verwenden muss, um auf die Werte zuzugreifen, die mit -ArgumentList übergeben wurden, oder definieren Sie die Parameter (param($server,$filepath...)) am Anfang des Skriptblocks.

Sie könnten so etwas wie dies versuchen:

#Get full path for module 
$module = Resolve-Path ".\Down.psm1" 

#Create scriptblock 
$scriptblock = { Rename-LoadBalancerFile -ServerName $args[0] -Revert $args[1] -filePath $args[2] -cred $args[3] } 

foreach($s in $servers) 
{ 
    Start-Job -Name "RenLb" -InitializationScript ([scriptblock]::Create("Import-Module $module")) -ScriptBlock $scriptblock -ArgumentList $s,$false,$lbFileLocation,$Cred | Out-Null 
} 

Write-Host 'Waiting for LB rename.' 

While (Get-Job -Name 'RenLb' | where { $_.State -eq 'Running' }) 
{ 
    Start-Sleep 1 
} 

Write-Host 'completed' 

I ([scriptblock]::Create("Import-Module $module")) verwendet, um die InitializationScript zu erzeugen, um sicherzustellen, dass die $module -variable seit $module zu einem filepath erweitert wurde, ist in dem neuen Job nicht verfügbar -Faden. Sie können es durch -InitializationScript { Import-Module c:\mymodule\down.psm1 } ersetzen, wenn Sie den Modulpfad fest codieren möchten.

+0

Versucht, dass es nicht funktioniert hat. Der Job wird erstellt, aber sofort beendet (und "Get-Job" gibt einen Fehler aus, dass der Job "RenLb" nicht gefunden werden kann). Und ja, habe vergessen, den Original-Skriptblock einzubauen. Es hatte passende Parameter definiert, aber genauso einfach mit $ args [0] ... ist in Ordnung. Meine Annahme ist, dass dies ein Problem innerhalb der Funktion selbst und/oder der PSRemoting ist. Funktioniert synchron, aber nicht innerhalb von 'Start-Job'. –

+0

Keine Jobs? : S sind Sie sicher, $ Server ist nicht leer? –

+0

$ Server ist nicht leer. Ich sollte klarer sein, es * schafft * die Jobs, endet aber, bevor 'Get-Job' eine Chance hat, sie zu holen. –