Praxisbeispiele aus der DevOps-Welt – Teil 3

PowerShell – nützliche Praxisbeispiele
Kommentare

Nachdem in den ersten Teilen die Grundlagen der PowerShell-Benutzung erklärt wurden, folgen nun die Praxisbeispiele. Dabei liegt der Fokus nicht auf komplexeren Skriptingaufgaben, sondern auf den einfachen, aber mächtigen Tricks, die man im Entwickleralltag mal schnell aus dem Hut ziehen kann.

Dieser Artikel erklärt, wie PowerShell Remoting und die Integration mit COM und WMI/CIM funktioniert. Weiter werden das Providermodell und die Arbeit mit SOAP und REST Web Services vorgestellt. Abgerundet wird der Artikel mit einer Sammlung von PowerShell-Snippets für den Alltag.

Die PowerShell ist ein Kommandozeileninterpreter für Windows. Sie wird mit dem Windows-Betriebssystem ausgeliefert und ist in vielen Produkten, wie SharePoint, TFS oder Exchange Server integriert. Weil die PowerShell auf dem .NET Framework aufgebaut ist und Schnittstellen zur Windows Management Instrumentation (WMI), dem Component Object Model (COM), der Registry und vielen anderen Komponenten anbietet, können komplexe Aufgaben mithilfe der PowerShell oft mit einem einzigen Befehl erledigt werden. Diese Befehle lassen sich sowohl lokal als auch remote ausführen.

Artikelserie
Teil 1: PowerShell-Grundlagen: Hilfe, wie geht’s los?
Teil 2: PowerShell-Grundlagen: Bearbeitung und Weiterverarbeitung von Cmdlet-Ergebnissen
Teil 3: PowerShell-Praxisbeispiele aus dem DevOps-Alltag
Powershell: Das Resultat der Get-Service-Anfrage mit ConvertToHtml im Edge-Browser

Abb. 1: Das Resultat der Get-Service-Anfrage mit ConvertToHtml im Edge-Browser

PowerShell-Befehle – auch Commandlet (Cmdlet) genannt – können über den Pipe-Operator „|“ miteinander verbunden werden. Die PowerShell kommt mit einer Fülle von Cmdlets, die beispielsweise zur Formatierung der Ausgabe verwendet werden können.

Folgendes Beispiel zeigt einen Befehl, der vom lokalen Rechner die ersten zehn Windows Services ermittelt und deren Namen und Status als HTML-Datei ausgibt. Das Resultat ist in Abbildung 1 zu sehen.

PS C:\> Get-Service | Select-Object Name, Status -First 10 |Sort-Object Status -Descending | ConvertTo-Html | Out-File "D:\ServiceReport.html"

PowerShell Remoting

Ein großer Anteil der Power in der Shell kommt daher, dass Cmdlets mit wenig Aufwand auch auf Remote-Maschinen ausgeführt werden können. Der Zielrechner muss dabei für PowerShell Remoting vorbereitet sein, indem unter anderem der Windows-Remote-Management-Service eingeschaltet wird. Mit dem Cmdlet Test-WSMan –ComputerName kann überprüft werden, ob der Zielrechner PowerShell-Anfragen entgegennehmen kann.

Ist dies nicht der Fall, kann Remoting mit Enable-PSRemoting –force eingeschaltet werden. Dabei wird der benötigte Windows-Service gestartet, ein Listener registriert und Firewallports geöffnet.

Die PowerShell bietet mehrere Möglichkeiten, um auf andere Rechner zuzugreifen.

Mit dem Enter-PSSession Cmdlet wird eine PowerShell-Session auf dem Zielrechner geöffnet, vorausgesetzt, die Berechtigung ist vorhanden. Mit der Option -Credentials kann ein Benutzername angegeben werden, und die PowerShell erfragt das dazugehörende Passwort. Sobald die Verbindung steht, können Cmdlets normal ausgeführt werden.

Gewisse Cmdlets unterstützen von sich aus die Ausführung auf einem anderen Rechner. Das Öffnen einer Remote-Session ist dann nicht mehr nötig. Listing 1 zeigt ein Beispiel mit dem Get-Process Cmdlet. Dabei wird mit dem Argument -Computername der Name des Zielrechners übergeben.

Noch spannender wird PowerShell Remoting wenn ein Befehl gleichzeitig auf mehreren Rechnern ausgeführt wird. Dem Cmdlet Invoke-Command kann ein Skriptblock übergeben werden, der einen weiteren Befehl enthält. Mit der Option –ComputerName können ein oder mehrere Zielrechner angegeben werden.

#Variante 1: Enter-PSSession
#Öffnen einer Remoting Session auf Zielrechner LTMME05
PS C:\> Enter-PSSession –ComputerName LTMME05

#Der Rechnername wird in der Eingabeaufforderung angezeigt und Befehle können auf dem Remote-Rechner ausgeführt werden.
[LTMME05] PS C:\> hostname
LTMME05

#Variante 2: Cmdlet mit Option –Computername
PS C:\> Get-Process -ComputerName LTMME05 | Select-Object -First 1
Handles  NPM(K)    PM(K)      WS(K) VM(M)   CPU(s)     Id  SI ProcessName
-------  ------    -----      ----- -----   ------     --  -- -----------
    113       9     6156       7804    64     0.27   8900   1 ACEngSvr

#Variante 3: Invoke-Command
#Das Beispiel holt einen EventLog Eintrag von 3 Rechnern
PS C:\> Invoke-Command -ComputerName LTMME05, LTMME06, LTMME07 -ScriptBlock {Get-EventLog Security -Newest 1}

#Alternativ können die Rechnernamen auch aus einer Textdatei gelesen werden
PS C:\> Invoke-Command –ComputerName (Get-Content Rechnerliste.txt)...

COM Interop

Das Resultat von Get-Service in Excel

Abb. 2: Das Resultat von Get-Service in Excel

Auf das Component Object Model (COM) kann aus der PowerShell mit New-Object in Kombination mit der Option -ComObject zugegriffen werden. Listing 2 zeigt zwei Beispiele. Im ersten Beispiel wird die SAPI.SPVoice-COM-Komponente verwendet, um eine Sprachausgabe zu erzeugen.
Das zweite Beispiel greift mit Excel-Interop auf Microsoft Excel zu und erstellt ein Excel-Dokument, das eine Liste aller Windows-Services enthält. Die Services werden dabei nach ihrem Status eingefärbt (Abb. 2).

#Sprachausgabe mit COM Interop
PS C:\> $voice = New-Object –ComObject SAPI.SPVoice
PS C:\> $voice.Speak("Hello Windows Developer");

#Vorlesen einer Datei
PS C:\> New-Object –ComObject SAPI.SPVoice
PS C:\> $text = Get-Content C:\Datei.txt
PS C:\> $voice.Speak($text)

#Erstellen eines Excel Sheets mit COM Interop
[Threading.Thread]::CurrentThread.CurrentCulture = "EN-us"
$ex = New-Object -ComObject Excel.Application
$ex.visible = $true
$exWb = $ex.Workbooks.Add()
$exWs = $exWb.Worksheets.Item(1)

$exWs.Cells.Item(2, 1).EntireColumn.ColumnWidth = 40

$exWs.Cells.Item(2,1) = "Services Name"
$exWs.Cells.Item(2,2) = "Service Status"

$row = 3
$services = Get-Service | Select-Object -First 20
foreach($Service in $services)
{
  $exWs.Cells.Item($row,1) = $Service.DisplayName
  $exWs.Cells.Item($row, 2) = $Service.Status.ToString()
  if($Service.Status -eq "Running")
  {
    $exWs.Cells.Item($row,1).Font.ColorIndex = 10
    $exWs.Cells.Item($row,2).Font.ColorIndex = 10
  }
  elseif($Service.Status -eq "Stopped")
  {
    $exWs.Cells.Item($row,1).Font.ColorIndex = 3
    $exWs.Cells.Item($row,2).Font.ColorIndex = 3
  }
  $row++
  Write-Host "row++"
}
$exWs.SaveAs("C:\ServiceStatusReport.xlsx");

WMI

Die Windows Management Instrumentation (WMI) ist eine Schnittstelle zum Windows-Betriebssystem. Über die WMI kann auf eine riesige Menge von Informationen des lokalen Rechners oder eines Remote-Rechners zugegriffen werden. Beispiele dafür sind Informationen über das BIOS, sämtliche Peripheriegeräte, Prozesse oder die installierte Software.

Mit dem Befehl Get-WmiObject -Class * -List können sämtliche verfügbaren WMI-Klassen abgefragt werden. Alternativ kann mit Get-CimClass *usb* nach einer Klasse gesucht werden, die usb im Namen enthält. CIM steht für Common Information Model und ist ein offener Standard zur Beschreibung von Prozessen, Komponenten und Software. Die Cim-Cmdlets kapseln den Zugriff auf die WMI gemäß der CIM-Spezifikation.

Sobald eine Klasse gefunden wurde, lassen sich mit Get-WmiObject –Class Win32_BIOS oder Get-CimInstance –ClassName Win32_BIOS ihre Informationen abrufen.

Script Execution Policy

Grundsätzlich ist die Ausführung von PowerShell-Skripten abgeschaltet. Mit dem Cmdlet Set-ExecutionPolicy kann die Skriptausführung erlaubt werden. Folgende Werte können gesetzt werden:

  • Restricted: Keine Scripts können ausgeführt werden
  • AllSigned: Nur Skripte, die von einem Trusted Publisher signiert wurden, dürfen ausgeführt werden
  • RemoteSigned: Heruntergeladene Skripte müssen von einem Trusted Publisher signiert sein
  • Unrestricted: Alle Skripte können ausgeführt werden

Damit sich die „ExecutionPolicy“ ändern lässt, muss die PowerShell mit administrativer Berechtigung ausgeführt werden.

PowerShell-Provider

Die PowerShell implementiert ein erweiterbares Providermodell. Das Providermodell erlaubt die Navigation durch hierarchische Strukturen, wie zum Beispiel ein Dateisystem. Im Dateisystem wird mit den Befehlen dir, cd, „..“ usw. durch die vorhandenen Ordner navigiert, wie es in der Windows Eingabeaufforderung üblich ist. Dass dies in der PowerShell auch funktioniert, ist dem FileSystem-Provider zu verdanken.

Die Liste aller verfügbaren Provider kann mit Get-PSProvider abgerufen werden. Die Provider können über so genannte Drives angesprochen werden, genau wie man es vom alten DOS-Prompt gewohnt sein dürfte. Im Listing werden für den Filesystemprovider die Drives C, A, D, Z aufgeführt, die logischen Laufwerken entsprechen. Viel interessanter sind aber die anderen Provider. Über den Drive Env kann zum Beispiel auf die Umgebungsvariablen oder über das Drive HKLM auf die Registry zugegriffen werden. Listing 3 zeigt, wie über das Providermodell durch die Registry navigiert wird.

#Anzeigen aller verfügbaren Provider
PS C:\> Get-PSProvider
Name        Capabilities                       Drives
----        ------------                       ------
Registry    ShouldProcess, Transactions        {HKLM, HKCU}
Alias       ShouldProcess                      {Alias}
Environment ShouldProcess                      {Env}
FileSystem  Filter, ShouldProcess, Credentials {C, D, G, H}
…

#Wechsel zum Registry Provider über das „HKLM“ Drive
#Hinweis: HKLM steht hier für den Registry-Ast HKEY_LOCAL_MACHINE
PS C:\> cd hklm:

#Navigation durch die Registry zum PowerShellEngine Eintrag
#Hinweis: Mit der Tabulatortaste können die Einträge vervollständigt werden.
PS HKLM:\> dir
Name
----
BCD00000000
DRIVERS
HARDWARE
SAM
SOFTWARE
SYSTEM

PS HKLM:\> cd .\SOFTWARE\Microsoft\PowerShell\1\
PS HKLM:\SOFTWARE\Microsoft\PowerShell\1\> dir
Name                           Property
----                           --------
PowerShellEngine               ApplicationBase         : C:\Windows\System32…
                               ConsoleHostAssemblyName : Microsoft.PowerShel…
                               Culture=neutral, PublicKeyToken=31bf…
                               PowerShellVersion       : 2.0
                               RuntimeVersion          : v2.0.50727
…

Mit dem Import-Module Cmdlet können weitere Provider importiert werden. Eine Liste von Produkten, die einen PowerShell-Provider bereitstellen, ist in der Wikipedia ersichtlich.

Listing 4 zeigt die Benutzung der Provider für SQL Server und die Internet Information Services (IIS). Das Modul für den SQL Server wird mit dem SQL Server zusammen installiert oder kann manuell nachinstalliert werden. Das WebAdministration-Modul für den IIS wird auf Windows Server zusammen mit der Web Server Role installiert.

#Importieren der Provider für Sql Server und IIS
PS C:\> Import-Module SQLPS
PS C:\> Import-Module WebAdministration 
PS C:\> Get-PSProvider
Name              Capabilities                       Drives
----              ------------                       ------
SqlServer         Credentials                        {SQLSERVER}
WebAdministration ShouldProcess                      {IIS}
…

#Anzeigen aller Sites im IIS
PS C:\> cd IIS:
PS IIS:\> dir
Name
----
AppPools
Sites
SslBindings

PS IIS:\> dir sites
Name             ID   State      Physical Path   Bindings
----             --   -----      -------------   --------
Default Web Site 1    Stopped    D:\PROJECTS…    net.tcp 808:*
                                                 net.pipe *
                                                 net.msmq 
MySite1          3    Started    D:\TFS\...      http *:41019:

#Anzeige aller Application Pools und deren Applications
PS IIS:\> dir apppools
Name                     State        Applications
----                     -----        ------------
.NET v4.5                Started
.NET v4.5 Classic        Started
DefaultAppPool           Started      Default Web Site
                                      /App1
                                      /App2
                                      /App3
MySite1                  Started      MySite1
                                      /AppA
                                      /AppB

#Hinweis: Die AppPools können auch von einem anderen Drive aus aufgerufen werden ohne explizit in den Provider zu wechseln:
PS C:\> dir iis:\apppools

#Erstellen eines neuen Application Pools
PS IIS:\> New-Item AppPools\NewAppPool

#Setzen eines Application Pools
PS IIS:\> Set-ItemProperty 'sites\MySite1\AppB' –Name applicationPool –Value NewAppPool

#Wechsel auf den SqlServer Provider
PS C:\> cd sqlserver:
PS SQLSERVER:\> dir
Audits
AvailabilityGroups
BackupDevices
Credentials
CryptographicProviders
Databases
Endpoints
JobServer
Languages
LinkedServers
Logins
Mail
ResourceGovernor
Roles

#Pfad zu einer Tabelle
SQLSERVER:\sql\ltmme02\default\databases\mydb1\tables\dbo.mytable

Arbeiten mit SQL Server und IIS

Neben den Providern für SQL Server und IIS gibt es eine weitere Möglichkeit, um mit Produkten von Microsoft oder Drittherstellern via PowerShell zu kommunizieren. Viele dieser Produkte bringen bei der Installation ihre eigenen PowerShell-Module mit. Ein Modul ist dabei nichts anderes als ein Behälter für PowerShell Cmdlets. Mit Get-Module –ListAvailable können die auf dem Rechner vorhandenen Module abgefragt werden. Der Befehl Import-Module –Name modulname importiert das entsprechende Modul in die aktive Session. Über die Umgebungsvariable PSModulePath werden Module der PowerShell bekannt gemacht, damit sie nicht in jede Session importiert werden müssen, sondern automatisch zur Verfügung stehen.

Die Module für SQL Server und IIS enthalten Cmdlets für alle gängigen Operationen. Die folgende Liste zeigt einen Auszug:

  • Invoke-Sqlcmd
  • Backup-SqlDatabase
  • Restore-SqlDatabase
  • New-WebSite
  • New-WebApplication
  • Backup-WebConfiguration
Software Architecture Summit 2017

The Core of Domain-Driven Design

mit Carola Lilienthal (Workplace Solutions)

Distributed Systems

mit Kyle Kingsbury (Independent Consultant)

Web Services

Das Aufrufen eines SOAP Web Service geht mit der PowerShell sehr komfortabel. Dem Cmdlet New-WebServiceProxy wird der URI zur WSDL-Datei (Web Services Description Language) übergeben, der Rückgabewert wird in einer Variablen gespeichert, und schon hat man einen typisierten Web-Services-Client. Durch die Typisierung können die Namen der Operationen des Web Service mit der Tabulatortaste vervollständigt oder durchgeklickt werden. Im Integrated Scripting Environment (ISE) werden die Operationsnamen in einem IntelliSense-ähnlichen Dialog angezeigt.

Das Aufrufen eines REST Web Service, was einem einfachen HTTP-Call entspricht, ist mit dem Invoke-Query Cmdlet möglich. Listing 5 zeigt, wie das Google-Maps-API aus der PowerShell aufgerufen werden kann.

#Aufruf eines SOAP WebServices mit einem typisierten Client
PS C:\> $uri = 'http://www.webservicex.net/airport.asmx?WSDL'
PS C:\> $airportProxy = New-WebServiceProxy -Uri $uri -Namespace ws
PS C:\> $airportProxy.getAirportInformationByAirportCode('ZRH')
<NewDataSet>





<Table>
    <AirportCode>FRA</AirportCode>
    <CityOrAirportName>FRANKFURT INTL</CityOrAirportName>
    <Country>Germany</Country>
…

#Durch Zuweisung an eine Variable vom Typ XML wird die Antwort in ein XML Objekt gespeichert werden, mit welchem weitergearbeitet werden kann
PS C:\> [XML]$xml = $airportProxy.getAirportInformationByAirportCode('FRA');
PS C:\> $xml.NewDataSet.Table[0].CityOrAirportName
FRANKFURT INTL

#Aufruf eines REST WebServices
#Es soll über die Google Maps API die Distanz zwischen der Basta Spring (Darmstadt) und der Basta (Mainz) ermittelt werden.
PS C:\> $uri = 'https://maps.googleapis.com/maps/api/directions/json'
PS C:\> $query = '?mode=driving&origin=Rheinstrasse 105, 64283 Darmstadt&destination=Rheinstrasse 66, 55116 Mainz'
PS C:\> $response = Invoke-RestMethod $uri$query

#Die Variable $response enthält ein JSON Objekt
PS C:\> $response.routes[0].legs[0].distance
text    value
----    -----
35.1 km 35141

PS C:\> $response.routes[0].legs[0].duration
text    value
----    -----
27 mins  1615

Gemischte Snippets

Listing 6 enthält eine Sammlung von nützlichen PowerShell-Snippets für die folgenden Aufgaben:

  • Testen von .NET-Format-Strings
  • Testen von Regular Expressions (Regex)
  • Finden des voll qualifizierten Namens einer Assembly
  • Finden des ASCII- oder Unicode-Codes für ein Zeichen
  • Abfragen von Performance-Counters
  • Messen der Zeit, die für einen REST-Aufruf benötigt wird
  • Einträge aus dem EventLog in eine HTML-Datei exportieren
#Testen von Format Strings
PS C:\> [string]::Format("{0:r}", [DateTime]::Now);
Wed, 16 Mar 2016 23:57:49 GMT

#Hinweis: Dasselbe geht auch mit dem Powershell Operator „-f“
PS C:\> „{0:r}“ –f [DateTime]::Now

#Testen von Regex
#Finde alle zweistelligen Zahlen
PS C:\> $regex = [regex]"\b\d\d\b"
PS C:\> $regex.Matches("123 45 1 95 1412 99 343 0202 23") | % { $_.value }
45
95
99
23

#Ausgabe des voll qualifizierten Assemblynamen eines Typs
PS C:\> [System.IO.FileStream].AssemblyQualifiedName
System.IO.FileStream, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089

#Finden des ASCII/Unicode für ein Zeichen
PS C:\> [int][char]'£'
163

#Installieren der IIS Rolle auf mehreren Windows Servern
PS C:\> 'Server1', 'Server2', 'Server3' |Foreach-Object { Install-WindowsFeature Web-Server –IncludeAllSubFeature –IncludeManagementTools –ComputerName $_}

#Anzeigen einer Windows Forms MessageBox
PS C:\>[System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms")
PS C:\>[System.Windows.Forms.MessageBox]::Show("Hallo Windows Developer!")

#Den Performance Counter „Total CPU Percentage“ jede Sekunde abfragen
PS C:\> Get-Counter '\Processor(_total)\% Processor Time' -Continuous -SampleInterval 1 -ComputerName LTMME05
3/17/2016 8:26:13 PM      \\ltmme05\processor(_total)\% processor time :
                          25.7970432422004
…

#Messen der Zeit, die für ein REST Aufruf benötigt wird
PS C:\> $uri = 'https://maps.googleapis.com/maps/api/directions/json'
PS C:\> $query = '?mode=driving&origin=Rheinstrasse 105, 64283 Darmstadt&destination=Rheinstrasse 66, 55116 Mainz'
PS C:\> (Measure-Command {Invoke-RestMethod $uri$query}).TotalMilliseconds
356.4796

#Die ersten 100 Einträge im application EventLog als HTML-Datei exportieren
PS C:\> get-eventlog -log "application" | select -first 100 | ConvertTo-Html > c:\evt.html

Weitere interessante Ressourcen

Neben den Tipps und Tricks in diesem Artikel gibt es noch eine Vielzahl weiterer Themen, die den begeisterten PowerShell-Benutzer interessieren könnten. So ist es zum Beispiel möglich, mit PowerShell Workflow (PSW) so genannte long-running Workflows zu erstellen. PSW basiert auf der Windows Workflow Foundation (WF) und ermöglicht PowerShell-Aktivitäten zu erstellen, die gestoppt, gestartet und sogar parallelisiert werden können.

Da die PowerShell auf dem .NET Framework basiert, ist es mit wenig Aufwand möglich, PowerShell-Anwendungen mit grafischen Benutzeroberflächen zu erstellen. Dabei kann gewählt werden, ob mit WinForms oder Windows Presentation Foundation (WPF) gearbeitet werden soll.

Natürlich gibt es noch eine Vielzahl an spannenden PowerShell-Modulen, zum Beispiel für die Arbeit mit dem Team Foundation Server oder posh-git für die Arbeit mit Git.

Als letzter Punkt sei die Integration in Microsoft Azure erwähnt. Das Azure SDK enthält eine Vielzahl an PowerShell-Skripten für die Verwaltung sämtlicher Azure-Ressourcen, wie virtuelle Maschinen, Storage-Container oder Cloud-Services. Ein besonders spannendes Feature von Azure ist die PowerShell im Browser. Für jede Azure-Website besteht unter der Adresse https://meinewebsite.scm.azurewebsites.net/ eine Kudu-Seite. Kudu ist die Engine, die für das Git Deployment in die Azure-Website verantwortlich ist. Auf der Kudu-Startseite (Abb. 3) kann über das Menü Debug Console | Powershell die PowerShell-Konsole im Browser (!) geöffnet werden (Abb. 4).

Für weiterführende Informationen zur PowerShell lohnt sich ein Blick in das frei verfügbare E-Book von Keith Hill und in die offizielle PowerShell-Startseite.

Die PowerShell hat sich im Windows-Umfeld etabliert und kann den Entwickleralltag spannender und effektiver gestalten. Diese Artikel haben Ihnen dieses mächtige Werkzeug nähergebracht, damit Sie mit der PowerShell loslegen können, um die Power bei der täglichen Arbeit zu nutzen!

Unsere Redaktion empfiehlt:

Relevante Beiträge

Meinungen zu diesem Beitrag

X
- Gib Deinen Standort ein -
- or -