Linux für Webworker, Teil 3: Einführung in die Arbeit mit der Shell

Der folgende Gastartikel stammt von Janek Bevendorff.

Linux Tux: By Larry Ewing, Simon Budig, Anja Gerwinski ([1]) [Attribution], via Wikimedia Commons In den vorigen Teilen (eins und zwei) dieser Serie ging es hauptsächlich darum, warum sich ein Wechsel zu Linux vielleicht lohnen könnte (oder eben auch nicht), wie das System aufgesetzt wird, was dabei zu beachten ist und welche Grafik- und Entwicklungs-Tools zur Verfügung stehen. In diesem Teil möchte ich gern auf ein allgemeineres Linux- bzw. UNIX-Thema eingehen, das so nicht zwangsläufig auf Webworker zugeschnitten, aber doch Grundlage für viele andere Dinge ist.

Der Titel verrät es schon: es geht um die Arbeit mit der Shell. Die letzten Male habe ich vermehrt darauf hingewiesen, dass Shell-Kenntnisse keinesfalls notwendig seien und sich die Arbeit unter Linux ohne Kommandozeile genauso gut erledigen lasse, wie unter allen anderen Systemen auch. Ich wollte damit in erster Linie Berührungsängste mit Linux abbauen.

In diesem Artikel möchte ich nun aber über diese anfänglich Barriere hinüber steigen. Während die Aussage, dass Kommandozeilen-Kenntnisse nicht notwendig seien, weiterhin Gültigkeit besitzt, möchte ich in diesem Artikel erläutern, warum das vielleicht doch nicht die ganze Wahrheit ist und man doch vielleicht die Shell benutzen sollte.

Aber fangen wir ganz von vorn an…

Was ist eine Shell?

Die Shell ist genau genommen ein Programm, das eine Schnittstelle zwischen Benutzer und Betriebssystem darstellt. So ist bspw. der Windows Explorer, der einen Desktop, eine Taskleiste, einen Dateimanager etc. bereitstellt, per definitionem eine Shell. Auch der Gnome- oder KDE-Workspace ist genau genommen eine Shell. Im allgemeinen Sprachgebrauch wird mit Shell allerdings eine textbasierte Kommandoschnittstelle bezeichnet, weshalb an dieser Stelle oft auch die Rede von der Kommandozeile ist. Um genau zu sein, ist die Kommandozeile eine Untermenge der Shell, aber im täglichen Gebrauch werden Shell und Kommandozeile meist synonym verwendet, was ich in diesem Artikel ebenfalls tun werde. Wenn also in diesem Artikel die Rede von der Shell ist, dann ist damit die textbasierte Eingabeaufforderung gemeint.

Warum braucht man im Jahr 2012 noch eine Kommandozeile?

Kommen wir zur essentiellen Existenzfrage der Kommandozeile in Zeiten schneller Rechner mit allerlei bunten grafischen Oberflächen, die stets zum Klicken einladen. Die erste Antwort, die man meist auf diese Frage erhält, ist die, dass es einfach effizienter sei. Diese Antwort ist keinesfalls falsch, aber allein für sich ein schlechtes Argument, um zu überzeugen. Die passende Antwort darauf ist stets “Aber es geht doch auch so…” und “Ich kann mir das eh alles nicht merken.”

Um die Vorzüge einer Kommandozeile darzulegen, muss man also etwas weiter ausholen und das Argument Effizienz etwas genauer beleuchten.

Zunächst einmal ist die Shell ein Universalwerkzeug, das viele kleinere Werkzeuge in sich vereinigt (das Bild eines Werkzeugkastens passt vielleicht eher). Genauso wie eine Desktop-Shell gibt einem die Kommandozeile die Möglichkeit, von zentraler Stelle verschiedene Werkzeuge/Programme aufzurufen und auszuführen, nur bloß viel kompakter. Anstatt bspw. ein großes Menü bereitzustellen, in dem alle Programme aufgelistet sind, stellt die textbasierte Shell eine Kommandozeile bereit, die Befehle ausführt.

Das geht schnell und ist unkompliziert. Man muss weder in einer Liste nach einem Programm suchen, noch muss man jemals die Shell verlassen, um komplexe Aufgaben auszuführen. Dank der in vielen Shells durch die Tabulator-Taste erreichbaren Autovervollständigung für Befehls- und Dateinamen, muss man sich oftmals noch nicht einmal den gesamten Namen eines Befehls merken, geschweige denn, ihn vollständig ausschreiben.

Das allein wäre aber noch kein Totschlagargument. Wer weiß, welche Werkzeuge er benötigt und wo diese sich aufrufen lassen, ist auch auf einer grafischen Oberfläche fix unterwegs. Deshalb hier der zweite Vorzug einer Kommandozeile: die Verknüpfung von Befehlen. Sowohl Desktop-Shell als auch Kommandozeile stellen beide ein zentrales Werkzeug bereit, mit dessen Hilfe sich weitere Einzelwerkzeuge aufrufen lassen. Allein die Kommandozeile bietet aber eine universelle Möglichkeit, mehrere Teilwerkzeuge direkt zu verknüpfen.

Während bei grafischen Programmen Ausgaben zuerst in eine Datei oder die Zwischenablage geschrieben werden müssen, um damit anschließend manuell ein anderes Programm zu füttern, lassen sich Kommandozeilen-Programme direkt durch Eingabe- und Ausgabe-Umleitung miteinander verknüpfen. So lassen sich Befehlsketten erstellen, die aus mehreren Teilwerkzeugen ein mächtigeres Gesamtwerkzeug bilden.

Und damit wären wir auch direkt beim dritten Vorzug: der Automatisierung. Nur wenige grafische Programme bieten bspw. die Möglichkeit, Makros aufzuzeichnen, um häufig anfallende Aufgaben automatisiert zu lösen. Und selbst wenn eine Makrofunktion geboten wird, so ist sie in aller Regel auf das eine Programm beschränkt.

Auf der Shell ist das anders. Hier ist die Automatisierung in Form von Shell-Skripten direkt eingebaut. Jeder Befehl, der sich direkt eingeben lässt, lässt sich auch als Text-Datei abspeichern und später wieder ausführen. Einmal gebaute Befehlsketten können so wiederverwendet werden, um Zeit zu sparen. Viel Zeit. Wer ein bestimmtes Problem immer und immer wieder zu lösen hat, der schreibt sich mit den Mitteln der Shell bloß ein Programm, anstatt dieselben Klick-Operationen wieder und wieder manuell auszuführen.

Die Grundlagen: Eingabe- und Ausgabe-Umleitung

Beginnen wir mit den Grundlagen der Shell. Die meisten Tutorials fangen an dieser Stelle damit an, zunächst einige Grundbefehle aufzulisten, mit denen in Verzeichnisbäumen navigiert, Dateien angelegt oder gelöscht werden können. Ich tue dies nicht (es sei dafür auf eine gute Auflistung der gängigsten Kommandos in der Wikipedia verwiesen). Stattdessen beginne ich lieber mit dem allem zugrundeliegenden Konzept auf der Shell: der Umleitung von Eingabe- Ausgabestreams. Wer dieses Konzept verstanden hat, der hat die Shell verstanden und kann nahezu alle Aufgaben erledigen.

Doch was hat es damit auf sich? Nun, auf der Shell werden Daten in Form von Streams weitergereicht und verarbeitet. Wer eine Datei öffnen, um deren Inhalt zu lesen, der öffnet genau genommen einen Stream, über den er die Daten liest und wer eine Ausgabe auf dem Bildschirm tätigt, der öffnet ebenfalls einen Stream, in den er diese Daten schreibt. Nur wie sieht das jetzt aus?

Es gibt dafür drei grundlegende Operatoren: <, > und |. Des Weiteren gibt es drei vordefinierte Streams: STDIN (0), STDOUT (1) und STDERR (2), die für Standard-Eingabe (Standard Input), Standard-Ausgabe (Standard Output) und Standard-Fehlerausgabe (Standard Error Output) stehen. Mithilfe dieser drei Operatoren und der Standard-Streams lassen sich nun Daten zwischen Kommandozeilen-Programmen austauschen. < leitet dabei den Inhalt einer Datei auf den Eingabestream STDIN, > schreibt den Ausgabe-Stream STDOUT in eine Datei und | leitet STDOUT an das nachfolgende Programm weiter (das nennt sich Piping oder Pipelining, weshalb der Operator oft auch einfach Pipe genannt wird).

Konkret am Code erklärt (Zeilen, die mit # beginnen, sind ein Kommentar und werden von der Shell ignoriert):

# Schreibe die STDOUT-Ausgabe von programm1 in die Datei meinedatei:
programm1 > meinedatei

# alternativ (etwas unübersichtlicher):
> meinedatei programm1

# Lies die Datei meinedatei ein und leite sie über STDIN an programm2
programm2 < meinedatei

# alternativ (auch wieder weniger eindeutig):
< meinedatei programm2

Anstatt die Daten zuerst in eine Datei zu schreiben, könnte man sie aber auch direkt an programm2 weiterleiten:

programm1 | programm2

Die Pipe verbindet dabei STDOUT von programm1 mit STDIN von programm2. Das ist natürlich nicht auf zwei Programme beschränkt. Es lassen sich beliebig viele Programme verketten:

programm1 | programm2 | programm3 | programm4 | ...

Dem aufmerksamen Leser mag aber aufgefallen sein, dass wir STDERR bisher gar nicht benutzt haben. Das liegt daran, dass es dafür keinen eigenen Operator gibt. Um trotzdem mit STDERR (und jedem anderen selbst erstellten Stream) arbeiten zu können, müssen wir das Konzept der Ein- und Ausgabe-Umleitung noch etwas allgemeiner fassen. Jeder dieser drei Streams ist mit einem sogenannten File-Deskriptor verbunden. Im Falle der drei Standardstreams sind dies die Deskriptoren 0, 1 und 2. Um von einem File-Deskriptor zu lesen, schreibt man n<, wobei n die Nummer des Deskriptors ist. Analog schreibt man n> um in den Deskriptor n zu schreiben. < ist also nichts weiter aus die Kurzform von 0< und > nichts anderes als 1>. Um also den STDERR-Stream eines Programms in eine Datei umzuleiten, schreibt man Folgendes:

programm 2> datei

Dies schreibt allerdings nur STDERR in die Datei. STDOUT wird weiterhin ganz normal auf dem Bildschirm ausgegeben. Das sieht man schön an diesem Befehl:

echo "Hallo Welt" 2> datei

Dies schreibt nicht etwa den String Hallo Welt in die Datei. Stattdessen wird Hallo Welt auf dem Bildschirm ausgegeben und ein leerer String in die Datei geschrieben. Warum leer? Einfach weil kein Fehler ausgegeben wurde (der Befehl lief ja korrekt). Anders bei diesem Befehl:

echox "Hallo Welt" 2> datei

Hier wird nichts auf dem Bildschirm ausgegeben und in der Datei steht bspw. zsh: command not found: echox, da der Befehl echox nicht existiert (Fehlermeldung wird nach STDERR und nicht nach STDOUT geschrieben).

Um sowohl STDOUT als auch STDERR in eine Datei zu schreiben, muss der eine Stream zunächst an den anderen angehängt werden. Das geht so:

programm 2>&1 > datei

Dies verknüpft zunächst den Deskriptor 2 (d.h. STDERR) mit dem Deskriptor 1 (d.h. STDOUT). Anschließend wird STDOUT in die Datei umgeleitet. Sieht anfangs kompliziert aus, man gewöhnt sich aber daran.

Da STDERR nach STDOUT umgeleitet wird, können wir die Fehlerausgabe aber natürlich nicht nur in eine Datei schreiben, sondern z.B. auch direkt in ein anderes Programm pipen:

programm1 2>&1 | programm2

Aber was lässt sich mit diesem Wissen anfangen? Es lassen sich die Programmketten bauen, von denen ich eingangs sprach. Hat man z.B. ein Programm kundenkartei, das einem alle Informationen zu bestimmten Kunden ausgibt, möchte aber bspw. nur alle Einträge sehen, die den Namen Schulze enthalten. Dann könnte man mit Hilfe einer Pipe und dem Programm grep, das über STDIN geleitete Daten mittels regulärer Ausdrücke filtert, folgenden Aufruf basteln:

kundenkartei | grep Schulze

Möchte man diese Ausgabe in eine Datei speichern, sieht der Aufruf so aus:

kundenkartei | grep Schulze > Schulze.txt

und möchte man kundenkartei nun aus einer bestimmten anderen Quelle speisen:

kundenkartei < kartei2 | grep Schulze > Schulze.txt

Ich gebe zu, dass das Beispiel etwas unglücklich gewählt ist, da man speziell für Kundenkarteien eher umfangreiche grafische Datenverwaltungswerkzeuge nutzt, aber es diente auch nur zur Verdeutlichung des Prinzips (möchte man Daten aus der Kartei allerdings automatisiert verarbeiten, so bietet sich die Kommandozeile mit ihrer größeren Flexibilität aber geradezu an).

Kurzer Exkurs: welche Shells gibt es überhaupt?

Die Shell auf unixoiden Systemen ist ein Programm, das vollkommen losgelöst von dem Terminal-Fenster funktioniert, innerhalb dessen man sie meistens aufruft. So mag es den einen oder anderen vielleicht überraschen, dass es nicht die Shell gibt, sondern eine Vielzahl davon. Wer also das Konsolenfenster öffnet, der startet gleich zwei Programme: einmal den Terminal-Emulator / das Konsolenfenster selbst und darin die eigentliche Shell.

Die gängigsten Shells sind diese:

  • Bourne-Shell (sh): Die Bourne-Shell ist sozusagen der Urahn der meisten heute existierenden Shells. Sie ist nahezu auf jedem Unix-System vorhanden oder es existiert zumindest eine zu ihr kompatible Shell unter demselben Namen (/bin/sh). Heutzutage wird sie vor allem für Shell-Skripte verwendet, da ihre Verbreitung enorm, die interaktive Bedienung hingegen nicht das allergrößte Erlebnis ist.
  • Bourne-Again-Shell (bash): Die Bash ist die Standard-Shell auf den meisten aktuellen Systemen (auch unter OS X). Sie entstand durch das GNU-Projekt und ist zur Bourne-Shell kompatibel, bietet aber wesentliche Verbesserungen, wie etwa eine recht fortgeschrittene Autovervollständigung, eine Historie der ausgeführten Befehle uvm.
  • C-Shell (csh): Die C-Shell ist eine Shell mit C-orientierter Syntax, die jedoch viele Prinzipien der Bourne-Shell übernommen hat. Wer also mit der doch recht gewöhnungsbedürftigen Syntax der Bourne-Shell nicht zurecht kommt, aber mit C-ähnlichen Sprachen (d.h. C, C++, Java, PHP etc.) vertraut ist, findet hier vielleicht ein Zuhause. Heutzutage wird die reine C-Shell aber kaum noch verwendet. Häufiger anzutreffen ist die TENEX-C-Shell (tcsh), eine Weiterentwicklung der ursprünglichen C-Shell.
  • Korn-Shell (ksh): Wie die Bash ist auch die Korn-Shell eine Weiterentwicklung der Bourne-Shell, die aber insbesondere viele Features des C-Shell übernommen hat, wie etwa Job-Control (also die Verwaltung von Hintergrundprozessen), Alias-Definitionen (d.h. die Definition alternativer Namen für komplexe Kommandos) oder eine Kommando-Historie. Die Schnittmenge mit der Bash ist groß.
  • Z-Shell (zsh): Die ZSH ist mein persönlicher Favorit. Sie ist ebenfalls weitestgehend kompatibel zur Bourne-Shell, vereinigt in sich aber nahezu alle Vorzüge der Bash, der C-Shell und der Korn-Shell. Dazu kommen einige Verbesserungen bei der Verwendung von Arrays, sehr flexibles Globbing (d.h. die Verwendung von Wildcards zur Beschreibung von Dateinamen, ähnlich regulären Ausdrücken wie man sie vielleicht aus diversen Programmiersprachen kennt) und eine extrem mächtige und frei programmierbare Autovervollständigung. Wer gerne mehr über diese großartige Shell wissen möchte, dem kann ich die Adventsserie zur ZSH in meinem Blog aus dem letzten Jahr empfehlen. 🙂

Der Wechsel der Shell ist übrigens simpel. Die aktuelle Login-Shell ist (neben einigen anderen Informationen) ist in der Datei /etc/passwd hinterlegt. Doch bevor man nun mit Root-Rechten anfängt, die Datei zu editieren, sollte man vielleicht eher das kleine unscheinbare Kommandozeilen-Tool chsh (change shell) verwenden. Um bspw. die ZSH (Programmdatei: /bin/zsh) als Standard-Shell für den eigenen Account festzulegen, genügt dieses Kommando:

chsh -s /bin/zsh

Das geht ganz ohne Root-Rechte und manuelle Editierung der /etc/passwd (natürlich nur für den eigenen Account).

Nützliche Tools für Webentwickler

Eine Shell existiert natürlich nicht zum Selbstzweck, sondern sie soll die Ausführung von Aufgaben vereinfachen. Nachdem ich nun einigen grundlegende Prinzipien der Shell erklärt habe, möchte ich nun ein paar Werkzeuge vorstellen, die speziell Webentwickler (aber selbstverständlich nicht nur) schätzen lernen sollten.

Git

Wer viel mit anderen zusammenarbeitet, der wird um ein Versionierungssystem mit Kollisionskontrolle nicht umhin kommen. Das derzeit wohl am häufigsten verwendete VCS (Version Control System) ist sicher Git. Git ist (anders als das klassische CVS oder SVN) ein verteiltes, d.h. dezentrales, Versionsverwaltungssystem. Es macht es sehr einfach, mit mehreren Leuten an einem Quellcode zu arbeiten, aber durchaus eigene Arbeitskopien zu besitzen, die vollkommen unabhängig von einem Master-Repository sind. Dadurch ist es bspw. sehr ohne Aufwand möglich, einen Fork von Projekten zu erstellen und selbst daran weiterzuentwickeln, ohne Zugriff auf das Ursprungs-Repository haben zu müssen.

Dadurch ist eine sehr flexible Entwicklung möglich. Wer sich z.B. ein Feature in einem Open-Source-Programm wünscht oder einen Bug ausmerzen will, der erstellt sich eine Kopie des Ursprungsrepositorys, arbeitet daran und bittet am Ende den Hauptentwickler, die im eigenen Repository vorgenommenen Änderungen zu übernehmen (zu pullen).

Sehr zu Nutze macht sich dieses Prinzip die Plattform GitHub, die mittlerweile Anlaufstelle für viele Open-Source-Projekte ist. Dort sind die Pull-Requests gleich nativ eingebaut, wodurch sich auf GitHub eine stattliche Entwickler-Community etabliert hat, in der jeder partizipieren kann.

Für Git existieren einige grafische Oberflächen (wie bspw. TortoisGit für Windows), ich persönlich bevorzuge aber nach wie vor das CLI (Command Line Interface). Es ist einfach, es ist schnell und es ist unkompliziert.

Klonen eines Repositorys? So einfach:

git clone git://foobar

Erstellen eines neuen Repositorys?

git init

Hinzufügen von Änderungen in Datei foo.bar?

git add foo.bar
git commit -m "Changed something"

Hochladen der Änderungen in ein Remote-Repository upstream?

git push upstream

Die Kommandos sind simpel, einfach zu merken und gehen schnell von der Hand. Ganz ohne lästige Klickerei. Selbstverständlich existieren aber auch Plugins à la TortoiseGit für die gängigen Dateimanager wie etwa Nautilus oder Dolphin.

Sass und Compass

Sass ist ein mächtiger CSS-Präprozessor und vielen Webentwicklern mit Sicherheit bekannt. Auch das für Sass geschriebene Framework Compass ist sicher vielen geläufig. Wie für nahezu alles existieren für beide Tools selbstverständlich praktische grafische Oberflächen, doch auch das Kommandozeilen-Interface ist simpel und praktisch.

Sass:
sass --watch style.scss:style.css
Compass:
compass create foobar       # Neues Projekt im Ordner foobar erstellen (einmalig)
cd foobar                   # Nach foobar wechseln
compass watch               # Compass anweisen, von nun an Änderungen im aktuellen Projekt zu überwachen

Sass (und damit auch Compass) erfordert übrigens, dass ruby und ruby-gems (je nach Distribution Teil des ruby-Paketes) installiert sind. Die Programme selbst lassen sich dann über RubyGems (den Ruby-Paketmanager) installieren:

gem install sass compass

Je nach Art der Installation (systemweit oder lokal ins Heimverzeichnis) werden dafür u.U. Root-Rechte benötigt.

Jekyll

Ein weiteres Ruby-Tool ist Jekyll, ein Blog-System, das aus HTML- oder Markdown-Templates HTML-Seiten erzeugt, die auf jeden Webserver hochgeladen werden können, auch wenn dort bspw. kein PHP bereitsteht, mit dem man ein CMS betreiben könnte. Hat man einmal die notwendige Struktur angelegt, so wird mit dem Befehl

jekyll --server

lokal ein Server gestartet, der (ähnlich wie Sass) Änderungen in den Dateien überwacht, die HTML-Seiten generiert und über den localhost bereitstellt. Die Dateien selbst landen dabei im _site-Verzeichnis und können von dort auf den Produktiv-Server kopiert werden.

Ein ähnliches Programm wie Jekyll ist (namentlich passend) Hyde, das auf Python basiert. Erwähnenswert ist sicher auch http://octopress.org/, ein Framework für Jekyll.

pngquant

Ladezeiten sind auch am Ende des Jahres 2012 noch von großer Bedeutung im Web, weshalb es sich empfiehlt, möglichst kleine Dateien bereitzustellen. Speziell Bilddateien können aber sehr schnell sehr groß werden, vor allem wenn sie Alpha-Transparenzen besitzen. Insbesondere PNG ist bei der Dateigröße oft großzügig. Der verwendete Kompressionsalgorithmus ist zwar (im Gegensatz zu JPEG) verlustfrei, aber auch nicht sonderlich effizient (es handelt sich um den Deflate-Algorithmus, der auch für normale ZIP-Dateien zum Einsatz kommt).

Effizientere Algorithmen wären zwar theoretisch möglich, jedoch in keinem PNG-Standard festgeschrieben. Um trotzdem kleine Dateien zu erzeugen, kann pngquant verwendet werden. Dieses wandelt 24- oder 32-bittige PNG-Dateien in 8-bit-Farbe um und erhält bei 32-Bit-PNGs sogar die Alpha-Transparenz. Schöner Nebeneffekt: selbst der IE6 kann damit umgehen, auch wenn dieser daraus nur eine binäre Index-Transparenz macht (d.h. es werden keine weichen Transparenz-Übergänge angezeigt, sondern Bildteile sind entweder sichtbar oder eben nicht).

Der Vorteil dieser Vorgehensweise liegt auf der Hand: wesentlich kleinere Dateien, oft nur wenige Prozent der Ursprungsgröße. Der Nachteil ist aber natürlich auch ein Qualitätsverlust. Durch die 8-Bit-Farbtabelle können nur noch 256 Farben dargestellt werden (ähnlich wie beim GIF-Format, die Kompression ist aber i.d.R. besser). In etwa 80 Prozent der Fälle lässt sich dies jedoch vernachlässigen. pngquant ist sehr intelligent bei der Umwandlung, sodass der Qualitätsverlust erst bei Bildern mit sehr vielen Farben auffällt (also bspw. Fotos oder Grafiken mit großen weichen Farbverläufen). Im Allgemeinen eignet sich für die Art von Bildern, bei denen der Qualitätsverlust eine Rolle spielen würde, sowieso eher das JPEG-Format.

Um also aus einem 24-/32-bittigen PNG eine 8-Bit-PNG-Datei zu erstellen, reicht folgender Befehl:

pngquant foobar.png

Ein ähnliches Programm wie pngquant ist OptiPNG, das die PNG-Datei ebenfalls sehr effizient optimiert, die Bilddaten aber nicht verändert.

jpegtran

jpegtran ist Teil der libjpeg und damit auf Linux i.d.R. vorinstalliert. Es wird dazu benutzt, um grundlegende verlustfreie Operationen auf JPEG-Dateien anzuwenden. U.a. lässt sich damit ein Bild rotieren, aber eben auch in der Dateigröße optimieren. JPEG komprimiert zwar schon sehr gut, aber man mag es nicht für möglich halten, wie ineffizient viele Bildbearbeitungsprogramme bei der JPEG-Abspeicherung vorgehen. Insbesondere an unnötigen Meta-Daten wird oft nicht gegeizt, aber auch bei der Kompression sind viele JPEGs sind optimal. Mit jpegtran lässt sich das ändern:

jpegtran -copy none -optimize infile.jpg > outfile.jpg

PHP

Ja, auch PHP kann von der Kommandozeile aus verwendet werden. Warum führe ich es hier auf? Schlicht deshalb, weil es die Programmiersprache ist, die vielen Webentwicklern am vertrautesten ist. Dies ist der großen Verbreitung insbesondere im Bereich der Content-Management-Systeme geschuldet. Wer also gerne Dinge automatisieren, sich aber nicht die Shell-Syntax aneignen will, der kann auch PHP-Programme schreiben und diese auf der Kommandozeile ausführen:

php phpfile.php [Parameter]

[Parameter] steht hierbei für optionale Kommandozeilen-Parameter, also Dinge, die man dem Programm vielleicht mit auf den Weg geben möchte. Diese sind aber nicht erforderlich und können auch weggelassen werden.

Zu beachten ist bei der Verwendung des PHP-CLIs natürlich, dass keine Eingaben über die üblichen $_GET-, $_POST– und $_REQUEST-Superglobals möglich sind, da ja keine HTTP-Verbindung verwendet wird, die GET- oder POST-Requests ermöglichen würde (von Cookies ganz zu schweigen). Stattdessen kann von STDIN gelesen werden. Ausgaben an STDOUT können weiterhin ganz normal per print und echo getätigt werden. HTML ist an dieser Stelle natürlich nicht sinnvoll. Beim Programmaufruf übergebene Kommandozeilen-Parameter finden sich im globalen Array $argv.

Wer PHP nicht mag und vielleicht lieber mit Python arbeitet, der kann natürlich auch Python nehmen. Auch Ruby bietet selbstverständlich eine Kommandozeilenschnittstelle an (ansonsten wären Programme wie Sass ja gar nicht möglich). Die Vorgehensweise ist analog. Hier am Beispiel Python:

python pythonfile.py [Parameter]

SSH

SSH (Secure Shell) ist ein verschlüsseltes Protokoll zur Kommunikation zwischen Rechnern. Wer sich auf einem entfernten UNIX-Server einloggt, der tut dies meist per SSH. Über SSH ist es dann möglich auf der Shell des entfernten Rechners zu arbeiten, als hätte man eine lokale Shell vor sich. Dies eröffnet einem viele Möglichkeiten, die man sich sonst erst über schmutzige Tricks, wie etwa einem PHP-Skript, das auf dem Server gewisse Dinge tut, erkämpfen müsste. In aller Regel ist die selbstgebastelte Lösung dabei nicht nur uneleganter, sondern auch unsicherer. Mit SSH hingegen hat man einen verschlüsselte Verbindung, bei der beide Kommunikationspartner sich gegenseitig authentifizieren.

Eine SSH-Verbindung lässt sich aufbauen wie folgt:

ssh user@remotehost

user ist dabei mit dem Benutzernamen auf dem Zielsystem zu ersetzen und remotehost durch die Adresse (also etwa durch die Domain oder IP, unter der der SSH-Server läuft). Ist der SSH-Server über einen anderen Port verfügbar als über den Standardport 22, so kann dieser mit dem optionalen Parameter -p angegeben werden:

ssh -p 1234 user@remotehost

SSH kann jedoch nicht nur verwendet werden, um auf dem Remote-Host eine Shell zu starten, sondern auch um Dateien zu übertragen. Dazu stehen in der Regel die Werkzeuge scp (Secure Copy) und sftp (SSH File Transfer Protocol) zur Verfügung, die beide über SSH laufen. scp funktioniert dabei im Großen und Ganzen wie das normale cp-Kommando zum kopieren von Dateien:

scp source user@remotehost:/home/foo/dest

oder auch umgekehrt:

scp user@remotehost:/home/foo/bar/source dest

sftp ist etwas komplexer und öffnet eine eigene Shell mit grundlegenden Befehlen zum Navigieren im Dateisystem und zum Senden (put) und herunterladen (get) von Dateien. Diese sind den FTP-Befehlen sehr ähnlich (in Zukunft wird SFTP das alte FTP-Protokoll und dessen halbgare verschlüsselte FTPS-Varianten hoffentlich auch bei Billig-Hostern endlich ablösen).

sftp user@remotehost:/startverzeichnis/

Im Regelfall wird für die Übertragung per SFTP aber nicht das Kommandozeilen-Programm verwendet, sondern z.B. der Dateimanager. Die meisten Linux-Dateimanager unterstützen SFTP nativ (anders als bspw. der Windows-Explorer, der mit Mühe und Not gerade einmal unverschlüsseltes FTP kann).

Wer übrigens plant, länger auf einem Remote-Dateisystem zu arbeiten, der sollte dieses vielleicht per sshfs in das lokale Dateisystem einhängen:

mkdir mountverzeichnis
sshfs user@remotehost:/remoteverzeichnis mountverzeichnis

Dies mountet das Verzeichnis /remoteverzeichnis des entfernten Hosts in das lokale Verzeichnis mountverzeichnis (geht ohne Root-Rechte). In diesem Verzeichnis kann dann gearbeitet werden, als läge es lokal im Dateisystem (allein die Geschwindigkeit, mit der Dateien geladen oder abgespeichert werden, unterscheidet sich). Um es nach Abschluss der Arbeiten wieder loszuwerden, kann es mit

fusermount -u mountverzeichnis

wieder aus dem Verzeichnisbaum ausgehängt werden. Das leere Verzeichnis mountverzeichnis kann dann gelöscht werden.

Ausblick Teil 4

Das soll es gewesen sein für unseren kleinen Ausflug auf die Shell. Im vierten und letzten Teil dieser Serie werde ich dann noch Wege aufzeigen, wie sich einige Vorteile von Linux-Systemen (wie etwa die sehr viel mächtigere Shell) auch auch unter Windows nutzen lassen und wie man eine hybride Umgebung mit sowohl Windows- als auch Linux-Rechnern möglichst schmerzfrei aufgebaut bekommt.

Bildnachweis, Tux: By Larry Ewing, Simon Budig, Anja Gerwinski ([1]) [Attribution], via Wikimedia Commons

Janek Bevendorff ist Webentwickler und Programmierer mit Hang zu Design und Technik. Als überzeugter Linux-Nutzer verbringe er zudem einen Großteil seiner Zeit mit dem freien Betriebssystem und betreibt seit 2010 das Blog refining-linux.org, in dem er Artikel zu fortgeschrittenen Linux-Themen veröffentlicht. Zu finden ist er auch auf Google+ unter +Janek Bevendorff und +Refining Linux sowie auf Twitter unter dem Pseudonym @Manko10.

Wir arbeiten seit 20 Jahren mit WordPress und bieten diverse Dienst­leistungen rund um das System an. Kontaktiere uns für weitere Informationen oder für ein Angebot.

Verwandte Beiträge:

19 Kommentare

  1. Kein Wort über sed oder awk/gawk, die einzigen beiden Werkzeuge, die man fast täglich benötigt?

    (Die tcsh ist unter FreeBSD und -Derivaten übrigens Standard. Ich gebe zu, ich vermisse die zsh kaum, obwohl ich sie einfach nachrüsten könnte.)

  2. Und kein Wort über ack und kein Wort über rsync und kein Wort über tee und kein Wort über htop und kein Wort über…
    Der Artikel hätte ein Buch werden können.

    Der Focus lag nicht darauf, umfassend die Linux-Grundlagen zu erläutern, sondern eine Auswahl von Tools vorzustellen, die speziell für Webentwickler praktisch sein können. Und dabei fällt halt viel hinten über, speziell die universellen Tools. Immerhin habe ich auch weder cd, noch mkdir, noch chmod, noch rmdir noch touch usw. erläutert. 🙂

  3. Das Synchronisieren von Dateien per rsync brauche ich auch oft und trotzdem wurde es mit keinem Wort erwähnt. Ich hätte noch hundert weitere wichtige Tools aufführen können. Das ist aber in einem einzigen Blog-Post nicht möglich.
    Davon abgesehen behaupte ich einfach mal, dass die meisten Webentwickler Search&Replace-Operationen sowieso direkt im Editor vornehmen. Deshalb habe ich sed und awk für diesen Artikel keine allzu hohe Priorität beigemessen.

    Wenn du aber gern etwas über diese beiden Tools lesen willst, dann führe dir gern diese beiden Artikel zu Gemüte, die im Rahmen meiner Adventskalenderserie aus dem vorletzten Jahr entstanden:
    The awk basics
    Multi-line sed search and replace. 😉

  4. Ich habe überlegt, ob ich Vim aufführe, habe mich dann aber dagegen entschieden, weil das Thema ein ganz neues Fass aufgemacht hätte. Selbiges für Emacs. Und Editoren wie nano oder joe erschienen mir dann doch zu trivial, um für diesen Artikel von großer Bedeutung zu sein.

  5. Damit ist dieser Teil der Serie aber für Webworker so gut wie nutzlos, denn die relevanten Werkzeuge fehlen komplett. Zusammengefasst: “Eine Shell ist die Kommandozeile, dort laufen PHP und CSS-Parser, mehr muss man nicht wissen.”

    Empfehle Erweiterung.

  6. Einspruch. Ich habe die grundlegenden Prinzipien einer Shell aufgeführt und anschließend eine Handvoll nützlicher Tools genannt, die speziell für Webentwickler von Interesse sind. Sozusagen als Leckerbissen. Wer mehr möchte, wird sich eh auf eigene Faust mit dem Thema beschäftigen müssen und wird dabei unweigerlich auf die Dinge stoßen, die nicht genannt wurden. Umgekehrt stößt man nicht unbedingt auf Programme wie pngquant oder jpegtran, wenn man nicht speziell nach ihnen sucht.

    Empfehle Erweiterung.

    Ich empfehle, dass du eine Enzyklopädie schreibst, in der du alles aufnimmst, was in diesem Artikel fehlt. Wenn sie dann im Jahr 2046 fertig ist, werde ich mir mit Sicherheit ein Exemplar besorgen.

  7. Mir ist kein – egal wie kleines – Buch über die Shell bekannt, in dem nicht vi, nano und (!) Emacs aufgeführt werden. Dein Tutorial ist wertlos – wer sich nach ihm richtet, profitiert nicht von ihm. Dies ist nicht “Shell für Webworker”, dies ist “wer die Shell eh kennt, der hat hier noch was zur Grafikkompression”. Da hättest du aber die Pipes weglassen können.

    Nach der Logik “kauf dir halt ein Buch” könntest du dein Tutorial auch einfach lassen. Bisher war jeder Teil eine Enttäuschung.

  8. Dann frage ich mich ernsthaft, warum du die Artikel überhaupt liest. Schade um deine Lebenszeit. Nichtsdestotrotz bist du stets der Erste, der seinen Kommentar hinterlässt. Bedenke, dass kein Tutorial der Welt auch nur ansatzweise vollständig ist und diese Serie nur dazu da ist, einen Einblick zu gewähren und sich keinesfalls als ausführliche Schritt-für-Schritt-Anleitung versteht.

    Aber vielleicht kommen ja noch andere Kommentare von anderen Lesern, die sachbezogener sind.

  9. Ich lese sie in der Hoffnung, dass was Brauchbares dabei rauskommt.

    Schade, dass du inhaltliche Kritik und Verbesserungsvorschläge als “nicht sachbezogen” wegwirfst. So wird das nix mit deiner Reputation.

  10. Wärend ich beruflich eher mit Eclipse und Co. zu tun habe, schwöre ich für meine Hobby-Projekte auch auf bash und vim. So oder so kann es ein gut eingerichteter vim in Kombination mit bash, grep, fnd, awk und co. doch noch immer mit einer überfrachteten IDE aufnehmen. Aber das ist nicht für Jeden das Richtige …

  11. Von eclipse lasse ich, wenn immer möglich, die Finger. Viel zu überladen 🙂
    Ich selbst nutze in erster Linie Sublime Text und auf der Konsole Vim.

  12. Alter Schwede,
    normaler weise halte ich mich ja raus wenn zwei sich streiten – und das versuche ich jetzt weitestgehend auch, doch soviel sei gesagt:

    @tux
    Du scheinst ja ein Profi zu sein und wenn du es besser kannst, schreib doch selbst eine “Schritt für Schritt Anleitung”. Und auch dort werden Hunderte Dinge fehlen. Doch wenn du es gut schreibst, lese ich es. Aber lass das Maulen.

    @Janek
    bin schon seit Jahre mit Unix unterwegs und versuche mich immer wieder an der Shell – bin leider ein visueller Typ, also GUi. Doch deine Anleitung finde ich prima, habe einiges gelernt und verstanden. Bin gleich in Teil 3 eingestiegen und werde mir jetzt noch die anderen Teile reinziehen.
    Tolle Arbeit die du da geleistet hast.

    Gruß Frank

  13. Natürlich bin ich ein Profi, daher darf ich maulen. Wenn schon jemand ‘ne Anleitung schreiben WILL, dann soll er es wenigstens richtig machen. Ich will nicht.

  14. @Frank Es freut mich, dass dir der Artikel gefällt. Ich sehe, er hat seinen Zweck erfüllt. Für evtl. auftretende weitere Fragen und zur Beseitigungen von Unklarheiten stehe ich gern zur Verfügung. 🙂

  15. @tux Ist die Frage, wessen Reputation den Bach runtergeht… Das Tutorial ist für interessierte Menschen gut geeignet. Für Klugscheisser mit schlechter Laune wohl nicht so 😉
    Zum inhaltlichen ein Beispiel: Wenn ich nicht wüsste, welche Auswahl ich an Editoren habe unter Linux, würde ich wohl unter Linux auch nicht webworken.
    Gruß, Reni

Kommentare sind geschlossen.