Bash

Ein grafischer Desktop wie GNOME oder KDE macht einfache Dinge sicherlich noch einfacher. Eine Shell dagegen macht eine automatisierte Lösung anspruchsvoller Aufgaben durch Skripting und elegante Konzepte überhaupt erst möglich - ganz ohne GUI-Overhead und bei Bedarf über Systemgrenzen hinweg.

Kommandozeile

Textbasierte Schnittstelle, um Befehle abzusetzen.

Konsole

Einheit aus Bildschirm und Tastatur, entweder physisch oder logisch.

Terminal

Die Software, die in einer Konsole läuft, als Schnittstelle zur Shell. Ein Terminal stellt einen Input- und einen Output-Kanal zur Verfügung.

Shell

Eine Shell ist ein Kommando-Interpreter, der in einem Terminalfenster durch die Benutzeroberfläche zur Verfügung gestellt wird, und an welches der Benutzer seine Befehle als Strings sendet. Eine Shell kann Skripte ausführen, sogar in Sessions ohne Terminalfenster.

Bash

Eine von vielen möglichen Shells auf Linux-Systemen.

Linux erlaubt aufgrund seiner Modularität das temporäre oder permanente Abschalten des X Window System, der Basis der grafischen Desktops. In Produktionsumgebungen kommt eine Server-Installation in der Regel in einer Minimal-Installation ohne X daher, was die Systeme um Grössenordnungen kleiner und damit sparsamer, schneller und weniger angreifbar macht.

Die 1974 massgeblich vom britischen Informatiker Stephen Richard Bourne für das Betriebssystem Unix entwickelte und nach ihm benannte Bourne-Shell wurde für die Firma AT&T in den Bell Laboratories erstellt. Die als verbesserte Version 1987 erschienene und heute in Version 4 vorliegende Bash (Bourne-Again SHell) ist die Standard-Shell auf RHEL-basierten Systemen. Sie beherrscht unter anderem Funktionen wie die „Command-History“, die $RANDOM-Variable, die Command-Substitution per $(…​) wie auch eine Ganzzahlarithmetik. Die Befehle sind teilweise kompatibel zu denen anderer UNIX-Shells wie C-Shell (csh) oder Korn Shell (ksh). Andere bekannte Shells sind zsh oder fish.

Im September 2014 machte die Bash mit einer seit 25 Jahren bestehenden Sicherheitslücke auf sich aufmerksam, dem so genannten ShellShock, die unter den beiden CVE-Nummern CVE-2014-6271 und CVE-2014-7169 geführt wird.

Versionen:
  • CentOS 6: Bash 4.1

  • CentOS 7: Bash 4.2

  • CentOS 8: Bash 4.4

Der Prompt ist der visuelle Indikator, mit dem die Shell darauf aufmerksam macht, dass sie auf Benutzereingaben wartet. Die Shell-Prompts werden für Benutzer und root traditionell unterschiedlich dargestellt:

  • für Benutzer: Prompt mit vorangestelltem $, Beispiel [user@host ~]$

  • für root: Prompt mit vorangestelltem #, Beispiel [root@host ~]# - die Superuser-Shell

Die Bourne-Shell /bin/sh ist die Standard-Shell des Systems, die in CentOS eben auf /usr/bin/bash zeigt.

Ermitteln, in welchem Shell-Typ man unterwegs ist (bash, sh, ksh, csh, zsh, …)?

echo $0

Das Kommando history zeigt die zuletzt verwendeten Kommandos. Die maximale Anzahl ist in der Umgebungsvariablen HISTSIZE festgelegt. Gespeichert wird die Kommando-Historie pro Benutzer in ~/.bash_history

Die Umgebungsvariable HISTCONTROL=ignoredups sorgt dafür, dass wiederholt ausgeführte, identische Kommandos nicht mehrfach protokolliert werden.

Um den Befehl-Nummer 591 aus der history erneut ausführen, !591 verwenden.

Tipp

Um effizient mit der Kommandozeile zu arbeiten, hilft neben der Verwendung der Cursortasten vor allem die „Reverse Search“, die per Tastenkürzel Ctrl + r zu erreichen ist. Gibt man dort beliebige Teile eines vorherigen Kommandos ein, sorgt die Bash für ein AutoComplete.

Terminals

Auf einem virtuellen CentOS-System lassen sich bis zu sechs virtuelle Terminals (VT) nutzen. Auf VT1 findet sich - falls installiert - der grafische Desktop auf Basis von GNOME, KDE o.ä.. Mit Hilfe der Tastenkombinationen Alt + F1 bis Alt + F6 lässt sich zwischen den einzelnen Terminals hin- und herschalten, was beispielsweise nützlich ist, um Probleme im X-Server zu beheben.

Wer unter GNOME arbeitet, startet die Shell am schnellsten per Druck der Super-Taste, gefolgt von t e r und Enter. Neue Terminal-Fenster erzeugt man aus dem vorhandenen GNOME-Terminal am schnellsten per Shift + Ctrl + n, neue Tabs mit Shift + Ctrl + t. Der interne Befehl für dieses Programm lautet gnome-terminal.

Note

Die Super-Taste ist auf den meisten Tastaturen fälschlicherweise mit einem Windows-Symbol bedruckt und wird daher manchmal als Windows-Taste bezeichnet. ;-)

Tastaturkürzel

Auf Bare Metal: Alt + F1 bis Alt + F6, auf VMs und/oder in unter einem Desktop: Ctrl + Alt + F1 bis Ctrl + Alt + F6

Wechselt auf eines der sechs Terminals. Ist ein GUI (z.B. GNOME) installiert, läuft dieses seit CentOS 6 auf der ersten Konsole (davor auf der siebten), und man muss Ctrl + Alt + F2 drücken, um auf die zweite Konsole zu gelangen.

Ctrl + c

Laufenden Befehl oder Eingabe abbrechen.

Ctrl + r

Reverse Search - sucht in der Befehls-Historie nach den eingegebenen Zeichen.

Home oder Ctrl + a

An den Anfang einer Zeile springen.

End oder Ctrl + e

An das Ende einer Zeile springen.

Ctrl + u

Löscht alles ab Cursor-Position bis zum Anfang der Zeile und kopiert es in einen Buffer.

Ctrl + k

Löscht alles ab Cursor-Position bis zum Ende der Zeile und kopiert es in einen Buffer.

Ctrl + y

Fügt das was im Buffer ist in die Linie ein.

Ctrl + Shift + u

Unicode-Zeichen eingeben (Bsp: Ctrl + Shift + u, 0 3 b b, was dem „λ“ entspricht“).

Ctrl + l

Leert den Bildschirm (analog zum Bash-Befehl clear).

Ctrl + d

Aus aktueller Terminal- oder SSH-Sitzung abmelden (analog zu den Bash-Befehlen exit oder logout).

Kommandos

Ein Bash-Kommando besteht in der Regel aus

  • dem Namen des aufzurufenden Programms (command),

  • Optionen (Schalter), die das Verhalten des Kommandos beeinflussen und

  • Argumenten, die festlegen, worauf der Befehl angewendet wird.

Optionen sind immer vom Kommando abhängig. Es gibt sie meist in Kurz- (-k) und Langschreibweise (--lang).

Hilfe zur Verwendung des Kommandos erhält man meist über die Optionen command -h oder command --help.

Diese Zeichen muss man, sobald sie in Optionen oder Argumenten von Kommandos vorkommen, mit einem vorangestellten Backslash (\) quoten/maskieren/escapen, da sie sonst von der Bash interpretiert werden:

" & ( ) ' ` | ! ; \ < > -

Grundsätzlich kann man jedes Zeichen quoten/maskieren. Wer sich also bei einem Sonderzeichen unsicher ist, maskiert - es schadet nicht, es ist nur anstrengender zu lesen. Sowas funktioniert durchaus: echo \H\a\l\l\o

Man kann mit $(command) und ${variable} ein Kommando oder eine Variable zuerst auswerten lassen:

# $() with a command
$ echo Today is $(date)
Today is Do 01 Jan 01:00:00 CET

# ${} with a variable
$ TEST=example
$ echo Testing an test${TEST}
Testing an testexample

Input-Output-Umleitung

Jedem Linux-Kommando wird der Zugriff auf drei wichtige Dateien gewährt:

Es gibt daneben noch die File Descriptors 3..9, die aber nicht näher bezeichnet sind.

Die Umleitung von Ausgabe-Daten eines Kommandos als Eingabe-Daten in ein anderes Kommando ist in der Shell-Umgebung extrem nützlich. Hier eine Zusammenfassung möglicher Umleitungen:

Leitet die Ausgabe des Kommandos in eine Datei um. Existiert die Datei nicht, wird sie erzeugt; existiert die Datei bereits, wird sie überschrieben.

command > file
ls -l > /tmp/dir.txt

Sendet den Inhalt der Datei an das Kommando.

command < file
audit2why < audit.log

Leitet die Ausgabe des Kommandos in eine Datei um. Existiert die Datei nicht, wird sie erzeugt; existiert die Datei bereits, wird die Ausgabe des Kommandos angehängt.

command >> file
echo "root: admin@xmpl.com" >> /etc/aliases

Füttert das Kommando mit dem Inhalt der Datei file1 und leitet die Ausgabe des Kommandos in die Datei file2 um.

command < file1 > file2

Leitet nur die Fehlermeldungen des Kommandos in eine Datei um. Existiert die Datei nicht, wird sie erzeugt; existiert die Datei bereits, wird sie überschrieben.

command 2> file

Tipp

Wer Meldungen nicht benötigt, leitet sie in die Nirwana-Datei /dev/null um.

Leitet nur die Fehlermeldungen des Kommandos in eine Datei um. Existiert die Datei nicht, wird sie erzeugt; existiert die Datei bereits, wird die Ausgabe des Kommandos angehängt.

command 2>> file
find / -name test 2>> /tmp/dir.txt

Ausgabe des ersten Kommandos zur Eingabe in das zweite Kommando umleiten.

command1 | command2
ps aux | grep http

Leitet STDOUT ins Nirvana um, so dass nur noch STDERR-Ausgaben angezeigt werden.

command 1> /dev/null
yum -y update 1> /dev/null

STDOUT in eine Datei umleiten, und nur STDERR anzeigen:

command 1>file >&1

Leitet zunächst einmal Meldungen ins Nirvana um; Fehlermeldung an STDERR werden danach aber nach STDOUT umgeleitet (womit diese ebenfalls im Nirvana verschwinden, da bereits umgeleitet). Mit dem vorangestellten & teilt man der Bash mit, dass es sich bei 1 nicht um eine Datei handelt. Diese Syntax ist nützlich für Cronjobs.

command > /dev/null 2>&1

Leitet STDOUT- und STDERR-Ausgaben des Kommandos in eine Datei um.

command &> file

Leitet STDOUT- und STDERR-Ausgaben des Kommandos in eine Datei um und erzeugt zusätzlich eine Bildschirmausgabe.

command  2>&1 | tee -a file

Komplexeren Text-Inhalt auf der Konsole 1:1 in eine Datei umleiten:

cat > /var/spool/cron/root << EOF
# content goes
# here across
# multiple lines
EOF

Wie oben, aber verhindern, dass die Bash Sonderzeichen auswertet:

cat > /var/spool/cron/root << 'EOF'
# content goes
# here across
# multiple lines
EOF

So sendet man Fehlermeldungen mit echo an STDERR:

echo "This is an error." >&2

Eine Ausgabe an STDERR senden:

echo "error" >&2

Leite Ausgaben an 3 und 4 auf STDOUT um:

mycommand 3>&1 4>&1

Was bedeutet mycmd 3>&1 1>&2 2>&3 in einem Shell-Script?

  • Damit werden STDOUT und STDERR getauscht.

    • File Descriptor (fd) 3 erzeugen und auf fd STDOUT umleiten

    • fd STDOUT auf fd STDERR umleiten

    • fd STDERR auf fd STDIN umleiten

Tipp

Es hilft, sich die Umleitungen als Variablen-Zuweisungen vorzustellen. > wie =, & wie $.

Aus cat file1 file2 1> file.txt 2>&1 wird damit

  • cat file1 file2

  • 1 = file.txt

  • 2 = $1 (also 2 = file.txt)

Aus cat file1 file2 2>&1 > file.txt wird

  • cat file1 file2

  • 2 = $1

  • 1 = file.txt

Built on 2022-06-03