Ausführen von Powershell-Skripts oder -Funktionen mit einer Unix-ähnlichen Pipeline-Syntax

804
Cyberwiz

Ich möchte mehrere benutzerdefinierte Verarbeitungsschritte mit der Pipeline in Powershell ausführen.

In Linux könnte ich so etwas tun:

listServers.sh | <some commands to filter servers> | commandToApplyToEachServer.sh 

Fügen Sie für jeden Schritt relevanten Code in verschiedene Skripts ein (jeder Befehl kann mehrere Parameter enthalten und zumindest der letzte kann vollständig durch ein anderes Skript ersetzt werden.)

Ich möchte etwas Ähnliches in Powershell machen, ohne "Overhead" hinzuzufügen (Skripts müssen vor der Verwendung ihrer Funktionen erstellt werden, Skripts müssen neu erstellt werden, wenn Änderungen vorgenommen wurden usw.).

Das Ausführen der Befehle direkt an der Eingabeaufforderung ist einfach:

"server1","server2" | % 

... aber ich möchte den Benutzern (und mir selbst) eine einfachere und robustere Art und Weise ermöglichen, dies und ähnliche Befehle auszuführen (im Wesentlichen wird jeder Schritt in ein Skript oder eine Funktion eingeschlossen, was auch immer die kraftvollste Art ist).

Das nächste, was ich bekommen habe, ist folgendes:

[CmdletBinding()] param( [Parameter(Mandatory=$true)] $env )  Function global:srv { Begin { }  Process { Get-Service -Name someServiceName -ComputerName $_ }  End { } }  Get-Content "$env.csv" 

Damit kann ich Dinge ausführen wie:

.\listServers.ps1 appServers | srv 

Die srv-Funktion wird jedoch leider erst aktualisiert, nachdem der gesamte Befehl ausgeführt wurde (Änderungen der Echo-Pipe-Funktion werden also erst beim zweiten Ausführen wirksam, und natürlich muss ich listServers.ps1 verwenden, bevor ich kann tu gar nichts, weil srv bis dahin nicht existiert)

UPDATE: Ich habe einen Single-Script-Ansatz verwendet (mit einigen Parametern zur Filterung und Steuerung, welcher Befehl am Ende ausgeführt werden soll, keine Pipeline). Es wäre jedoch immer noch interessant zu wissen, ob die Pipeline genutzt werden kann.

1
Gibt es einen Grund, warum Sie die Servernamen nicht normal als Parameter übergeben können? soandos vor 9 Jahren 0
Ja, es könnte 10 Server geben und ich möchte sie aus einer Datei lesen. Cyberwiz vor 9 Jahren 0
Warum nicht eine Funktion schreiben, die die Datei liest und sie dann als Array von Servernamen übergibt? soandos vor 9 Jahren 0
Ich bin nicht sicher, wie Sie das meinen, könnten Sie das näher erläutern? Cyberwiz vor 9 Jahren 0

1 Antwort auf die Frage

1
Austin T French

Es scheint, dass die wörtlichste Übersetzung von

listServers.sh | <some commands to filter servers> | commandToApplyToEachServer.sh 

wäre wie:

Get-content listServers.txt | Where-Object {*attributes and whatever} | CommandToRun 

Mit PowerShell und Piping liegt es wirklich an Ihnen, wie Sie irgendetwas bekommen und herumleiten. Angenommen, ich möchte alle meine Server mit dem Namen MAILSERVERxxxx neu starten:

Get-QADComputer -name * | where-object {$_.Name -Match "$MAILSERVER"} | Restart-Computer -ComputerName $_.Name 

Das könnte man tun, aber mit den PowerShell-Praktiken können Sie dies oft ganz anders verhalten:

Get-QADComputer -Name "MAILSERVER*" | Restart-Computer $_.Name 

Ein paar Anmerkungen:

  • PowerShell ist sehr flexibel
  • PowerShell sollte die Windows-Befehlszeile auf die BASH-Dienstebenen bringen
  • Die Syntax ist auch flexibel
  • Get-QADComputers ist ein Cmdlet von Quest und jetzt von Dell

Sie können auch eine C-ähnliche Syntax verwenden, um viele der gleichen Aufgaben auszuführen. Dadurch wird die Leistungsfähigkeit von PowerShell noch weiter erhöht.

Wenn Sie zum Beispiel eine Datei lesen möchten, erstellen Sie ein Array mit Übereinstimmungskriterien und tun Sie etwas, bevor Sie fortfahren:

$someArray = @() Get-Content "H:\SomeFile.txt" | ` Foreach-object { if ($_ -MAtch "$MAILSERVER") { $someArray += $_} }  $someArray | foreach-Object { if (Test-Connection "$_") { $Version = (Get-WmiObject -ComputerName "$_" -Class "Win32_OperatingSystem").Version } } 

Ich hoffe das hilft.

Hallo! Danke, Ihre Antwort war sehr informativ (besonders Get-QADComputer, ich werde das definitiv gebrauchen). Es löst jedoch nicht mein Kernproblem: Wie verwende ich Skriptdateien in der Pipeline? (oder eine ähnliche Funktion, mit der ich den Befehl bequem ausführen kann, ohne dass Dateien neu erstellt werden müssen, wenn Änderungen vorgenommen wurden, bevor der eigentliche Befehl ausgeführt wurde.) Cyberwiz vor 9 Jahren 0