Bash vs. PowerShell

Aus LinuxUser 04/2007

Bash vs. PowerShell

Die Kraft der Muschel

Microsofts neue PowerShell greift auf die Bibliotheken des .NET-Frameworks zurück und verfügt so über einen riesiger Fundus von Funktionen und Objekten. Ist sie dadurch einer traditionellen Shell wie der Bash überlegen?

Das Grundrezept

Die Hauptaufgabe einer Shell ist die Systemverwaltung. Daher bieten sowohl die Bash [1] als auch die PowerShell [2] die notwendigen Befehle, um in den Verzeichnissen zu navigieren, Dateioperationen vorzunehmen und andere Programme aufzurufen. Auch das Verwalten der Systemkonfiguration stellt eine wichtige Aufgabe dar. Während die Bash dafür vorwiegend auf externe Programme zurückgreift, integriert die PowerShell einige wichtige Systemwerkzeuge. So bietet etwa in der PowerShell das CmdletGet-Process ein Gegenstück zu ps, während das Cmdlet Get-Content dem Programm less entspricht.

Um den Programmablauf zu steuern, benötigt eine Shell Elemente zur bedingten Ausführung. Eine definierte Anzahl von Durchläufen legen beispielsweise for oder while in Verbindung mit der Auswertung einer Variablen fest. Listing 1 vergleicht die Ausgabe eines Zählers mit for in PowerShell und Bash.

Listing 1

Eine for-Schleife in der Windows Vista Powershell:

PS:> for ($i=1;$i -le 3;$i++) { Write-Host $i }
1
2
3
PS:>

Die gleiche Schleife in der Bash:

bash[~]$ for ((i=1;i<=3;i++); do echo $i; done
1
2
3
bash[~]$

Bei der Programmsteuerung durch Fallentscheidungen mittels if oder switch unterscheiden sich Bash und PowerShell nur wenig. Auch bei der Definition von Funktionen, der Nutzung von Umgebungsvariablen, dem begrenzte Gültigkeitsbereich von Variablen (“Scoping”), der Nutzung von regulären Ausdrücken und der Evaluation der Rückgabewerte von Programmen funktionieren beiden Shells recht ähnlich.

Eingeschränkte Starterlaubnis

Ein erster Unterschied zwischen PowerShell und Bash ergibt sich schon beim Aufruf eines Skript: Die PowerShell startet standardmäßig keine Skriptdateien und lässt sich daher nur interaktiv nutzen. Man kann sie aber dazu bringen, Skripte zu starten, sofern diese digital signiert sind. Eine solche digitale Signatur identifiziert den Autor des Skripts, denn nur er kann sie auf kryptografischem Weg erzeugt haben. Indem man das Signatur-Zertifikat des Skriptautors akzeptiert, bescheinigt man sein Vertrauen diesem gegenüber. “Fremde” Skripte dagegen führt die PowerShell erst einmal nicht aus. Um auch ohne Signatur ein Skript auszuführen, gilt es auf der Kommandozeile die Ausführungsrichtlinie (ExecutionPolicy) auf RemoteSigned zu setzen:

PS:> Set-ExecutionPolicy RemoteSigned

Nun akzeptiert die PowerShell alle lokalen Skripte. Stammen die Dateien dagegen aus einem Download oder sind sie per E-Mail angekommen, besteht die Shell weiter auf einer Signatur. Kommandodateien aus externen Quellen grundsätzlich nicht auszuführen, ist sicherheitstechnisch eine neue Qualität: Ein Skript-Virus wie “Love Letter” [3] verliert so jeden Schrecken.

Die Bash dagegen reguliert die Ausführungsberechtigung eines Skripts nicht über digitale Signaturen. Ob ein Skript ausgeführt werden darf, kontrollieren allein die im Dateisystem gesetzten Ausführungsberechtigungen.

Eine Frage des Anbieters

Eine überraschende Gemeinsamkeit findet sich in der Art und Weise, wie beide Shells mit der Systemkonfiguration umgehen. Ein Novum für die Windows-Welt stellt die Tatsache dar, dass die PowerShell alles als Dateisystem betrachtet und daher im Dateisystem genauso wie in der Registry navigiert, im Zertifikatsspeicher und in den Umgebungsvariablen wie in Laufwerken. Registry-Werte lassen sich also genauso kopiert, umbenennen und verschieben wie eine Datei auf einem Laufwerk. Die PowerShell nennt diese virtuellen Dateisysteme Provider und realisiert damit eine Philosophie, die Linux der Bash mit dem Ansatz “Alles ist eine Datei” schon immer geboten hat.

Weiterleitung

Das mächtigste Werkzeug der PowerShell ist ohne Zweifel die Pipe. Eine Pipe bietet eine geordnete Übergabe von Werten, so dass sich die Ausgabedaten eines Befehls als Eingabedaten des nächsten Befehls übernehmen lassen. Die Bash kennt die Pipe natürlich auch, stellt allerdings keine besonderen Anforderungen an die Ein- und Ausgabedaten. Sie vertraut vielmehr darauf, dass der nächste Befehl in der Lage ist, die Ausgabedaten des Vorgängers zu verstehen.

Bei der PowerShell erzeugen alle Cmdlets statt reiner Textausgaben definierte Objekte als Ausgabedaten. Auch wenn es so aussieht, als würden bei der Textausgabe nur die Zeichenketten weitergegeben, so findet doch eine vollständige Umwandlung in ein Objekt statt.

Diese Objekte untersucht man bei Bedarf mit dem Befehl Get-Member. Er gibt die Elemente und Funktionen des Objektes an, wie Listing 2 zeigt. Zum Beispiel lassen sich über das Kommando

PS:> Get-Content Textdatei.txt | Sort { $_.Length }

mit der Objekteigenschaft Length die Zeilen einer Textdatei der Länge nach sortieren.

Listing 2
PS:> Get-Content Textdatei.txt | Get-Member
   TypeName: System.String
Name             MemberType            Definition
—-             ———-            ———-
Clone            Method                System.Object Clone()
CompareTo        Method                System.Int32 CompareTo(Object value), System.Int32 CompareTo(String strB)
Contains         Method                System.Boolean Contains(String value)
CopyTo           Method                System.Void CopyTo(Int32 sourceIndex, Char[] destination, Int32 destinationIn…
…
Length           Property
PS:>

Datenstrukturen verarbeiten

Die Übergabe von Daten in Objektform ist zwar etwas komplizierter, sorgt jedoch für Einheitlichkeit und erlaubt die Verarbeitung sehr komplexer Datenstrukturen. Die Bash muss hier passen; sie greift zur Verarbeitung strukturierter Daten auf die Fähigkeiten externer Programme zurück.

So braucht die Bash zum Auswerten einer XML-Datei einen externen XML-Parser (etwa saxon oder Xalan-J). Listing 3 zeigt ein kurzes PowerShell-Skript, das einen RSS-Feed in Form einer XML-Datei aus dem Internet lädt. Es definiert eine Funktion Show-SpiegelRSS, die bei Aufruf die aktuellen RSS-Feeds von Linux-Community.de abholt.

Listing 3
# Show-SpiegelRSS.ps1
# Deklaration der Variablen für die URL
    $feed="https://www.linux-community.de/Ticker/news.rdf")
    Write-Host -ForegroundColor "green" "RSS-Feed: " $feed
# Download des RSS-Feeds
    $wco = New-Object System.Net.WebClient
    $rss = [xml]$wco.DownloadString($feed)
# Titel anzeigen
    Write-Host -ForegroundColor "red" $rss.RDF.channel.title
# Anzeigen in Kurzform
    $rss.RDF.item | Select-Object title,description
# Anzeigen von Titel und Beschreibung der Einträge
    $rss.RDF.item | Select-Object title,date,description | format-list

Fazit

Die PowerShell lehnt sich einerseits am bewährten Unix-Konzept an: Viele kleine Werkzeuge, die sich kombinieren lassen, sind besser als ein großes, das für einen bestimmten Zweck gebaut wurde. Andererseits bietet sie einen objektorientierten Ansatz, der zwar größere Vorhaben erleichtert, dafür aber schwieriger zu erlernen und zu handhaben ist. Das große Problem beim Umgang mit Objekten: Man muss einiges an Zeit investieren, um die gesuchte Funktion oder das passende Objekt herauszufinden. Das Cmdlet Get-Member dürfte daher wohl das meist genutzte Cmdlet der PowerShell sein.

Die Bash eignet sich als schlichtes und überschaubare Werkzeug für die meisten Aufgaben des Alltags bestens. Wenn es etwas kniffliger wird, kann man immer noch auf das objektorientierte Python oder die grafischen Möglichkeiten von Tcl/Tk ausweichen.

Glossar

Cmdlet

Bezeichnung für einen PowerShell-Befehl. Cmdlets sind dabei strikt nach dem Prinzip Verb-Substantiv aufgebaut: Get-Content, Set-Item, New-Item, und so weiter.

Ausführungsrichtlinie

Kontrolliert, ob ein Skript gestartet wird. Mit Get-ExecutionPolicy lässt sich die aktuelle Einstellung abfragen. Nur Administratoren dürfen die Einstellung ändern. Mögliche Werte für die ExecutionPolicy sind Unrestricted (uneingeschränkt), RemoteSigned (lokale Skripte und signierte Downloads), AllSigned (signierte Skripte) und Restricted (keine Skripte).

Infos

[1] Bash: Cameron Newham, “Einführung in die Bash Shell”, O’Reilly 2005, ISBN 978-3-89721-424-8, http://www.oreilly.de/catalog/bash3ger/

[2] Powershell: Andy Oakley, “Schnelleinstieg in die Windows PowerShell”, O’Reilly 2007, ISBN 978-3-89721-487-3, http://www.oreilly.de/catalog/powershellger/

[3] CERT-Advisory CA-2000-04 “Love Letter Worm”: http://www.cert.org/advisories/CA-2000-04.html

LinuxUser 04/2007 KAUFEN
EINZELNE AUSGABE
ABONNEMENTS
TABLET & SMARTPHONE APPS
E-Mail Benachrichtigung
Benachrichtige mich zu:

Hinweis: Dieser Artikel ist älter als ein Jahr, enthaltene Informationen sind möglicherweise veraltet.

1 Kommentar
Älteste
Neuste Beste Bewertung
Inline Feedbacks
Alle Kommentare anzeigen
maurizio
6 Jahre her

Stupid error, it’s not
bash[~]$ for ((i=1;i<=3;i++); do echo $i; done
but
bash[~]$ for ((i=1;i<=3;i++)); do echo $i; done
Typical for dumbies that not test the code before public it.

Nach oben