Heutzutage gibt es eine Vielzahl an Interfaces zur Eingabe von Computerbefehlen: Abgefahrene grafische Schnittstellen, Spracherkennung, mit Sicherheit auch VR-Krams … All das macht die Bedienung eines Computers für den Großteil der Nutzer wesentlich einfacher. Aber diese Schnittstellen sind beschränkt … man kann keinen Button anklicken, der nicht da ist. Will heißen: Wenn man alle Werkzeuge des Rechners komplett nutzen will, muss man sich auf die Textebene begeben – in die Eingabeaufforderung.
Nahezu alle Betriebssysteme verfügen über eine Art Eingabeaufforderung (Shell), manche sogar über mehrere. Wenn sich die Feinheiten dieser Shells auch unterscheiden können, ist die Kernaufgabe bei allen gleich: Sie erlauben es einem, Programme zu starten, Eingaben zu machen und ihre Ausgaben zu analysieren.
In diesem Tutorial beschränke ich mich auf die bekannteste und am meisten genutzte Shell, die Boune Again SHell, oder Bash. Um Befehle in eine Shell einzugeben, benötigt man zunächst ein Terminal. Jedes Betriebssystem verfügt über solch ein Terminal oder bietet die Möglichkeit eines zu installieren.
Unter Windows ist die Power Shell seit 2006 die Kommandozeile und Scripting-Sprache der Wahl. Die Befehle sind ähnlich, aber es gibt natürlich schon einige Unterschiede. Ich nutze derzeit hauptsächlich ein Windows System, habe mich aber schon vor langem an die Bash gewöhnt. Diese kann man unter Windows auch nutzen und es gibt auch verschiedene Terminals, die man zu diesem Zweck unter Windows installieren kann – bei mir hier kommt Terminus zum Einsatz.
Wenn man das Terminal öffnet, sieht man folgende Eingabeaufforderung:
tardis:~$
Dies ist die Eingabeaufforderung der Shell. Sie sagt, dass man sich auf dem Rechner tardis
befindet und dort im Home-Verzeichnis (~) des aktuellen Users. Das $ sagt aus, dass man nicht der root User ist (dazu später mehr). Unter Umständen kann die Eingabeaufforderung auch etwas anders aussehen, je nachdem wie der Rechner heißt und in welchen Verzeichnis man sich gerade befindet…
Hier könnte man nun seine Kommandos eingeben, welche von der Shell dann interpretiert werden. Der einfachste Befehl wäre das Ausführen eines Programms.
tardis:~$ date
Thu May 20 18:11:34 CEST 2021
tardis:~$
Hier habe ich nun das Programm date
ausgeführt, welches (wenig überraschend) das aktuelle Datum ausgibt. Die Shell fragt uns dann gleich nach einem neuen Kommando. Man kann auch Befehle mit Parametern ausführen:
tardis:~$ echo hello
hello
tardis:~$
Hier habe ich das Programm echo
mit dem Parameter hello
ausgeführt. Das echo
Programm gibt seine Parameter einfach auf dem Bildschirm aus. Die Shell untersucht den Befehl anhand der Leerzeichen in der Eingabe. Das erste Wort wurde als Befehl erkannt und die nachfolgenden Worte dementsprechend als Parameter. Falls man einen Parameter eingeben möchte, der eventuell selbst Leerzeichen enthält (einen Satz beispielsweise), dann muss man einfache '
oder zweifache "
Anführungszeichen nutzen. ('dies ist ein Satz'
).
tardis:~$ echo 'dies ist ein Satz'
dies ist ein Satz
tardis:~$
Aber wie findet die Shell denn das date
oder echo
Programm? Die Shell ist eine Programmierumgebung, genauso wie Python oder Ruby. Somit verfügt sie über Variablen, Schleifen, Bedingungen und Funktionen. Wenn man einen Befehl ausführt, ist das in Wahrheit ein Stück Programmcode, welchen die Shell interpretiert. Falls man ihr sagt, dass sie ein Programm ausführen soll, dass keinem ihrer Programmier-Schlüsselwörter entspricht, dann sucht sie in der Umgebungsvariable $PATH danach. In dieser Variable sind bestimmte Verzeichnisse auf der Festplatte gespeichert, in der die Shell nach den Befehlen nachsehen soll:
tardis:~$ echo $PATH
/usr/local/sbin /usr/local/bin /usr/sbin /usr/bin /sbin /bin
tardis:~$ which echo
/bin/echo
tardis:~$ /bin/echo $PATH
/usr/local/sbin /usr/local/bin /usr/sbin /usr/bin /sbin /bin
Wenn ich das echo
Programm ausführen will, sieht die Shell den Befehl echo
in meiner Eingabe, sucht dann in der Liste von Verzeichnissen in $PATH
nach einem Befehl mit diesem Namen. Falls die Shell fündig wird, wird der Befehl ausgeführt. Mit dem Befehl which
kann man sich anzeigen lassen, welches Programm bei welchem Befehl aufgerufen wird. Man kann die Suche in $PATH
auch komplett umgehen, wenn man direkt selbst den Pfad zu einem Programm mit angibt.
In der Shall navigieren
Ein Pfad in der Shell ist eine Liste von Verzeichnissen, die mit einem /
voneinander getrennt werden. (zumindest unter Linux und MacOS, unter der windowseigenen Shell sieht der Separator so aus \
). Wir beschäftigen uns hier aber nur mit dem Linux-Standard. Das Hauptverzeichnis (root) ist der schlichte Pfad /
. Ein Pfad, der mit /
beginnt ist ein absoluter Pfad, ausgehend vom Root-Verzeichnis.
Jeder andere Pfad ist relativ. Relative Pfade gehen immer vom aktuellen Verzeichnis aus, welches wir mit dem Befehl pwd
ausgeben können und mit dem cd
Befehl ändern. In einem Pfad bezieht sich ein .
auf das aktuelle Verzeichnis und ein ..
auf das Verzeichnis eine Ebene höher.
tardis:~$ pwd
/home/tardis
tardis:~$ cd /home
tardis:/home$ pwd
/home
tardis:/home$ cd ..
tardis:/$ pwd
/
tardis:/$ cd ./home
tardis:/home$ pwd
/home
tardis:/home$ cd tardis
tardis:~$ pwd
/home/tardis
tardis:~$ ../../bin/echo hello
hello
Man beachte, dass uns die Eingabeaufforderung immer anzeigt, in welchen Verzeichnis wir uns gerade befinden (wenn man unter Windows ein Terminal wie Terminus und ein Windows-Subsystem für Linux nutzt, dann sehen die Pfade etwas anders aus).
Normalerweise wird ein Programm im aktuellen Verzeichnis ausgeführt, es sei denn wir geben etwas anderes an. D.h. eigentlich schaut das Programm immer im aktuellen Verzeichnis nach irgendwelchen Dateien oder legt welche dort an, wenn es dazu aufgefordert wird.
Um anzuzeigen, was sich alles im aktuellen Verzeichnis befindet, geben wir ls
ein:
tardis:~$ ls
cpp/ shellScripting/
tardis:~$ cd /
tardis:/$ ls
bin/ boot/ dev/ etc/ home/ init* lib/ lib64/ media/ mnt/ opt/ proc/ root/ run/ sbin/ snap/ srv/ sys/ tmp/ usr/ var/
tardis:/$
Wenn dem ls
Befehl kein Verzeichnis als Parameter übergeben wird, wird das aktuelle Verzeichnis angezeigt. Den meisten Befehlen kann man noch zusätzliche Optionen oder Flags mitgeben, denen in vielen Fällen einfach ein -
vorangestellt wird.
Normalerweise wird beim Ausführen eines Programms mit dem Flag -h
oder --help
die Hilfe dazu angezeigt.
tardis:~$ ls --help
Usage: ls [OPTION]... [FILE]...
List information about the FILEs (the current directory by default).
Sort entries alphabetically if none of -cftuvSUX nor --sort is specified.
Mandatory arguments to long options are mandatory for short options too.
-a, --all do not ignore entries starting with .
-A, --almost-all do not list implied . and ..
--author with -l, print the author of each file
-b, --escape print C-style escapes for nongraphic characters
--block-size=SIZE scale sizes by SIZE before printing them; e.g.,
'--block-size=M' prints sizes in units of
1,048,576 bytes; see SIZE format below
-B, --ignore-backups do not list implied entries ending with ~
-c with -lt: sort by, and show, ctime (time of last
modification of file status information);
with -l: show ctime and sort by name;
otherwise: sort by ctime, newest first
...
Diese Hilfe zeigt auch die verschiedenen Flags und Optionen und was diese bewirken. Der ls
Befehl hat beispielsweise das -l
Flag, dass eine lange Darstellung des Verzeichnisses bewirkt. D.h. es werden viel mehr Informationen zu den einzelnen Dateien und Unterordner angezeigt.
tardis:~$ ls -l
drwxrwxrwx 1 bwiech bwiech 4096 May 20 18:39 cpp/
drwxrwxrwx 1 bwiech bwiech 4096 May 8 10:00 shellScripting/
Im nächsten Teil geht es dann zunächst nochmal um weitere Befehle zu Verzeichnissen und Dateien …
Höre gerade 🎵: Desert Something von Aloa Input