1.1 Basics

Inhalt

Die Shell

Die Shell ist ein Programm über welches der Benutzer mit dem System kommuniziert. Es nimmt Befehle an und führt die gewünschten Aktionen auf dem System aus. Genau gleich wie es verschiedene Linux Distributionen gibt, gibt es auch verschiedene Shells. Hier eine Auflistung der Populärsten mit ihrem initialen Releasedatum.

  • sh, Bourne Shell, 1979
  • bash, Bourne Again Shell, 1989
  • ash, Almquist Shell, 1989
  • zsh, Z Shell, 1990
  • dash, Debian Almquist Shell, 1997
  • fish, friendly interactive shell, 2005

Auf den allermeisten Linux system finden sich heutzutag bash und sh als Standardshell vorinstalliert. Daher befasst sich dieses Lab auch ausschliesslich mit der Bedienung dieser Beiden.

1
user@linux:/home/user$

Ein Blick auf die Standardshell

Programme auf der Shell reden miteinander über die Kanäle “Standard Out” stdout und “Standard In” stdin. Normalerweise schreibt ein Programm seinen Output nach stdout und nimmt auf stdin Input entgegen. Diese Kanäle lassen sich über die Operatoren <,>,&,| umbiegen. Doch dazu später mehr.

Alle Programme die dem POSIX Standard folgen kommen mit einer Hilfe Ausgabe. Diese kann über die Parameter -h oder --help ausgegeben werden.

Die eben kennengelernte Shell dient als Interface für die Bedienung einer Vielzahl von Programmen. Auch die Navigation in der Ordnerstruktur des Betriebsystems kann komplett über die Shell erfolgen. Folgende Werkzeuge werden dafür verwendet.

  • ls, list, Zeige den Inhalt des aktuell gewählten Pfades an
  • cd, change directory, Springe zu einem beliebigen Pfad hin
  • pwd, print working directory, Zeige den kompletten Pfad an

Beispiel Navigation

1
2
3
4
5
6
user@linux:$ cd ~/git/sys-lab
user@linux:$ pwd
/home/user/git/sys-lab
user@linux:$ ls
1_commandline  2_git  3_networking  4_ansible  5_troubleshooting  README.md
user@linux:$

Beispiel Navigation

In obigem Beispiel wird die Shell dazu verwenden in den Ordner dieses Labs zu springen und dessen Inhalt auszugeben. Das ~ ist dabei ein Shortcut und bezieht sich immer auf das Home Verzeichnis des aktuellen Nutzers.

Manipulation mit Dateien

Über die Shell können natürlich auch Dateien und Ordner erstellt, gelöscht und ausgegeben werden. Dafür dienen folgende Werkzeuge.

  • touch, Erstelle eine Datei
  • cat, Gib eine Datei aus
  • cp, Kopiere eine Datei oder einen Order
  • file, Zeige Metainformationen zu einer Datei
  • mkdir, Erstelle einen Ordner
  • rm, Lösche eine Datei oder einen Ordner
  • mv, Verschiebe eine Datei oder einen Ordner
  • less, Gib eine beliebige grosse Datei aus ohne mir das ganze System zu zerschiessen

Beispiel

1
2
3
4
5
6
user@linux:$ mkdir -p ~/documents/labs/cli
user@linux:$ cd ~/documents/labs/cli
user@linux:$ file ~/git/sys-labs/README.md
README.md: UTF-8 Unicode text
user@linux:$ cat ~/git/sys-labs/README.md > stuff_I_should_study.md
user@linux:$ less stuff_I_should_study.md

Verwalten von Dateien mit der Shell

Hier wird die Shell dazu verwendet einen neuen Order im Homeverzeichnis des Nutzers zu erstellen. Der Parameter -p weist das Programm mkdir dazu an Unterordner die es noch nicht gibt gleich mit zu erstellen. Das Programm file wird dazu benutzt um den Typ des Inhalts der Datei zu prüfen. Dann wird die Datei mit cat ausgegeben und der Output mittels > gleich dazu verwendet eine neue Datei mit diesem Inhalt zu erstellen. Schlussendlich wird less verwendet um die Datei bequem zu lesen. Das Programm kann mittels CTRL+C verlassen werden.

1
2
3
user@linux:$ rm stuff_I_should_study.md
user@linux:$ cd ..
user@linux:$ rm -r ~/documents/labs/cli

Löschen von Dateien und Ordnern

In obigem Beispiel wird zuerst die eben erstellte Datei gelöscht, anschliessend wird mittels cd .. in den übergeordneten Ordner gesprungen und der entsprechende Ordner, mit -r (rekursiv) gelöscht. Der erste Schritt wäre nicht nötig gewesen, da beim Löschen eines Ordners logischerweise auch der Inhalt flöten geht.

Suchen und Finden

Die suche von Dateien über die Shell ist effizient und schnell. Die Hauptarbeit leistet hierbei das Programm find. Find ermöglicht es sowohl nach Ordnern wie auch Dateien an beliebigen Orten im System zu suchen. Die grundlegenden Funktionen von find sind schnell erklärt. Das erste Argument von find ist immer das Verzeichnis in welchem gesucht werden soll. Wird es weggelassen sucht find im aktuellen Verzeichnis. Mittels -type lässt sich der Typ der Suche festlegen, also beispielsweise Datei (-f) oder Ordner (-d). Und über das Argument -name kann der Name einer Datei spezifiziert werden. Natürlich funktionieren beim Namen auch Platzhalter wie Wildcards. Es kann beispielsweise mittels -name "*.txt" nach allen Dateien mit der Endung .txt gesucht werden.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
user@linux:$ find ~/git/sys-labs/ -type d
git/sys-labs/1_commandline
git/sys-labs/1_commandline/3_text_basic
git/sys-labs/1_commandline/1_basic
git/sys-labs/1_commandline/4_text_advanced
git/sys-labs/1_commandline/6_workflows
git/sys-labs/1_commandline/7_scripting
git/sys-labs/1_commandline/5_vi
git/sys-labs/1_commandline/2_man
user@linux:$ find ~/git/sys-labs/1_commandline -type f -iname "*.md"
git/sys-labs/1_commandline/3_text_basic/README.md
git/sys-labs/1_commandline/1_basic/README.md
git/sys-labs/1_commandline/4_text_advanced/README.md
git/sys-labs/1_commandline/6_workflows/README.md
git/sys-labs/1_commandline/README.md
git/sys-labs/1_commandline/5_vi/README.md
git/sys-labs/1_commandline/2_man/README.md

Grundlegende Funktion von find

Weitere Standardprogramme

Hier werden weitere wichtige Werkzeuge genannt. Deren Funktion und Details sollen von der lesenden Person über das Helpfile (-h oder --help) als Aufgabe erarbeitet werden.

  • history
  • tree
  • wc
  • nl
  • sort
  • uniq

STDIN, STDOUT und andere Kanäle

STDOUT

Wie bereits angesprochen verwendet jede Shell die Kanäle STDIN und STDOUT um den Input sowie Output von Programmen zu verwalten. In diesem Teil untersuchen wir genauer was dabei passiert. Dazu betrachten wir folgendes Beispiel.

1
$ echo "Hallo Puzzle" > test.txt

Beispiel Umbiegen von STDOUT

Der > Operator wurde in obigen Beispielen bereits einige Male verwendet. Normalerweise gibt ein Programm seinen Output auf dem STDOUT Kanal aus. Dieser wird von der Shell direkt angezeigt. Bei diesem Operator handelt es sich um einen Shortcut welcher den Output des Programms nun so umbiegt dass der Text in einer Datei namens test.txt landet. Die Datei wird neu erstellt falls sie noch nicht existiert. Will man stattdessen einer Datei etwas hinzufügen ohne den Inhalt zu überschreiben verwendet man >> wie im folgenden Beispiel ersichtlich.

1
2
3
4
5
6
7
$ echo "Hallo Puzzle 1" >> test.txt
$ echo "Hallo Puzzle 2" >> test.txt
$ echo "Hallo Puzzle 3" >> test.txt
$ cat test.txt
Hallo Puzzle 1
Hallo Puzzle 2
Hallo Puzzle 3

Beispiel Umbiegen von STDOUT mit append

STDIN

Um Programme mit Input zu füttern verwenet man den STDIN Kanal. Betrachten wir folgendes Beispiel für das Programm cat.

1
2
3
$ echo "Hallo Puzzle" > hallo.txt
cat < hallo.txt
Hallo Puzzle

Beispiel Umbiegen von STDIN

Erst legen wir eine Datei mit dem Namen hallo.txt und dem Inhalt “Hallo Puzzle” an. Dann verwenden wir den < Operator um den Inhalt der Datei über STDIN an das Programm cat zu senden welches wiederum den Text ausgibt.

Gehen wir anhand des nächsten Beispiels nun einen Schritt weiter und verwenden die Ausgabe von cat um eine weitere Datei output.txt zu erstellen.

1
2
$ echo "Hallo Puzzle" > hallo.txt
cat < hallo.txt > output.txt

Beispiel Umbiegen von STDIN und Schreiben nach STDOUT

Nun landet der Text nicht in der Shell, sondern in der neuen Datei output.txt

STDERR

Ein weiterer Kanal der oft fürs Debugging verwendet wird ist STDERR. In diesem Kanal landen alle Fehlermeldungen. Bricht ein Programm mit einem Fehlercode ab, so wird es seinen Output über diesen Kanal umschreiben, sofern es dem POSIX Standard folgt. Die allermeisten Shells machen hier keine Ausnahme und geben alles was in STDERR landet direkt aus.

1
2
3
4
$ ls asdf
ls: cannot access 'asdf': No such file or directory
$ echo $?
2

Beispiel STDERR

Wir versuchen per ls Informationen über die nicht vorhandene Datei asdf zu betrachten, erhalten stattdessen einen Fehler da die Datei nicht existiert. Bei der Ausgabe der Zustandsvariable $? sehen wir einen Returncode mit dem Wert 2. Was heisst das nun?

  • Alle Programme die dem POSIX Standard folgen geben nach erfolgreicher Ausführung den Returncode 0 aus.
  • Mittels $? lässt sich der Returncode des zuletzt ausgeführten Programmes anzeigen.
  • Jeder Returncode ungleich Null ist gemäss POSIX ein Fehler.
  • In der entsprechenden Manpage des jeweiligen Programmes sind die Bedeutungen verschiedener Returncodes nachzuschlagen.
1
2
3
4
   Exit status:
       0      if OK,
       1      if minor problems (e.g., cannot access subdirectory),
       2      if serious trouble (e.g., cannot access command-line argument).

Auszug aus der Manpage von ls

In der Manpage finden wir heraus dass der Returncode 2 also ein Fehler mit der angegebenn Datei darstellt. In diesem Fall existiert diese einfach nicht. Nicht jeder Programm hat definierte Error Codes. Grundsätzlich ist alles was nicht Null ist aber ein Fehler.

Doch was wenn wir den Fehler nun loggen möchten ohne den kompletten Output des Programmes inklusive STDOUT in eine Datei zu schreiben? Wir möchten ja schliesslich nur die Fehler sehen und nicht was das Programm sonst noch so tut. Dazu können wir die Filedeskriptoren 0,1,2 verwenden welche zu den Kanälen stdin,stdout,stderr korrellieren. Möchten wir nur STDERR in eine Datei schreiben biegen wir also den Kanal mitdem Filedeskriptor 2 um.

1
2
3
$ ls asdf 2> err_log.txt
$ cat err_log.txt
ls: cannot access 'asdf': No such file or directory

Beispiel Umbiegen von STDERR in eine Datei

Dies wird beispielsweise auch oft verwendet wenn wir die Fehlermeldungen nicht sehen möchten. Beispielsweise in Skripten oder Cronjobs wo diese sich störend auf den Programmfluss auswirken würden. Unter Unix gibt es dafür das sogenannte Null Device, oder auch /dev/null. Alles was nach /dev/null geschrieben wird wird verworfen.

1
$ ls asdf 2> /dev/null

Beispiel Umbiegen von STDERR nach /dev/null

Die Fehlermeldungen von ls werden in diesem Fall nun verworfen. Oft möchte man sämtlichen Output eines Programmes nach /dev/null umleiten. Dazu kann man folgende Syntax verwenden.

1
$ ls asdf > /dev/null 2>&1

Beispiel Umbiegen jeglichen Outputs nach /dev/null

Die Angabe 2>&1 weist die Shell dazu an den Kanal STDERR nach STDOUT umzuleiten. Da STDOUT aber bereits nach /dev/null umgeleitet ist wird sämlticher Output im Null Device landen. Dieser Trick sollte man sich merken da er oft verwendet wird!

Der Pipeoperator

Der | Operator nennt sich Pipe. Mit ihm lässt sich ähnlich wie mit dem > Operator der Output eines Programmes umleiten. Möchte man den Output eines Programmes als Input für ein Anderes verwenden verwendet man statt > den Pipeoperator. Ein oft verwendetes Beispiel ist das Folgende.

1
$ ls -la /etc | less

Beispiel zur Verwendung des Pipeoperators

Hier wird der Output des Programmes ls als Input in das Textbetrachtungsprogramm less geschickt. less hat gegenüber der normalen Ausgabe den Vorteil dass man darin Suchen und auch Scrollen kann.

Später werden wir den Pipeoperator im Zusammenhang mit dem Programm grep weiter verwenden um die Ausgabe von Programmen effizient nach beliebigen Mustern zu durchsuchen.

Das env (Environment)

Das Environment besteht aus einer Vielzahl an Umgebungsvariablen. In ihnen sind Informationen zur aktuell verwendeten Umgebung enthalten. Alle Werte sind für die aktuelle Shell öffentlich. Das heisst jedes Programm das in dieser Shell ausgeführt wird, kann diese Werte lesen und nach belieben überschreiben.

1
2
3
4
5
6
$ env
USER=tux
SHELL=/bin/bash
HOME=/home/tux
LANG=en_US.UTF-8
PATH=/usr/local/sbin:/usr/local/bin:/usr/bin

Beispiel zur Ausgabe des lokalen env

Die Ausgabe wurde der Einfachheit halber auf einige essentielle Variablen gekürzt. Wir sehen also dass unter anderem der User spezifiziert wird. Dies ermöglicht es auch Shell Skripte benutzerunabhängig zu schreiben, wie in folgendem Beispiel ersichtlich wird.

1
2
echo $USER
cd $HOME/Downloads

Beispiel zur Verwendung von Umgebungsvariablen

Um auf den gespeicherten Wert einer Umgebungsvariablen zuzugreifen verwendet man den $ Operator. Er ermöglicht es uns also in obigem Beispiel direkt in das Downloads Verzeichnis des Nutzers zu Springen, ohne diesen explizit zu deklarieren.

Die wahrscheinlich wichtigste Umgebungsvariable ist allerdiens die Pfadvariable oder auch PATH. Alle Ordner die in dieser Variable spezifiziert werden können von der Shell aus ohne Angabe ihrer genauen Position ausgeführt werden.

1
2
3
4
5
$ which ls
/usr/bin/ls

$ /usr/bin/ls # Aufruf von ls mit Pfad
$ ls          # Aufruf von ls ohne Pfad

Beispiel zur Verwendung der Pfadvariable

Mittels Aufruf des Programmes which sehen wir den eigentlichen Installationspfad von ls. Nämlich das Verzeichnis /usr/bin/. Wir können das Programm aber von beliebigen Orten aus über die Shell aufrufen. Dies ist nur möglich weil sich das Verzeichnis /usr/bin in der Pfadvariable befindet.

Möchte man einen eigenen Ordner zur Pfadvariable hinzufügen (um einfacher auf selbst geschriebene Skripte oder Programme zuzugreifen) kann man dies folgendermassen tun.

1
$ PATH=/home/$USER/bin:$PATH

Beispiel zum Hinzufügen von Verzeichnisen zur Pfadvariable

In obigem Beispiel erweitern wir die Pfadvariable um das Nutzer Verzeichnis /home/$USER/bin. Natürlich müssen wir dabei aufpassen dass wir die Pfadvariable nicht komplett überschreiben, sonst wirds mühsam Programme auszuführen. Dazu schreiben wir den Wert der Pfadvariable neu, hängen aber hinten den aktuellen Wert wieder an. Dadurch wird sichergestellt dass wir nichts verlieren. Mit dem obigen Befehl wird die Pfadvariable in der aktuellen Shell neu gesetzt. Damit die Änderung auch bei neuen Shells oder nach einem Reboot noch vorhanden ist, kann die Datei ~/.bashrc angepasst werden.

Zuletzt geändert November 8, 2022: convert to hugo, deploy to openshift (856591c)