Skip to content
On this page

Linux Console

Viele Linux-Systeme – insbes. Server und viele Embedded Systeme - laufen ohne grafisches Display (headless) und somit ohne graphische Oberfläche. Deshalb sowie als Vorbereitung für die Raspberry Pi Versuche befassen Sie sich in diesem Versuch mit der „Textconsole“ resp. „Kommandozeile“ sowie etwas „Shell Scripting“ ...

ASCII-Textdateien und Dateirechte

ASCII Zeichen und Editoren

Unter einer ASCII-Datei versteht man eine Textdatei, welche nur Zeichen und Steuerzeichen aus dem 7-Bit ASCII Zeichensatz verwendet, also keine Zeichen aus dem erweiterten Unicode oder sonstige binär codierten Formatierungsanweisungen. Im Speicher und in der Datei abgelegt werden ASCII-Zeichen immer byteweise, wobei das oberste 8. Bit jeweils 0 ist. Diese Zeichen entsprechen auch jenen UTF-8 Zeichen, welche mit 1 Byte codiert werden: UTF-8 hat ja eine Variable Zeichenlänge von 1 bis 4 Bytes und wenn das oberste Bit im ersten Byte 0 ist, handelt es sich um ein 1-Byte codiertes (ASCII-)Zeichen.

ASCII-Texteditoren gibt einerseits für die Textkonsolen, andererseits auch für die graphischen Oberfläche wie z.B. Programm gedit z.B. für GNOME, kwrite für KDE, mousepad für Xfce oder Notepad.exe für Microsoft Windows etc.

Bringt eine graphische Oberfläche keinen eigenen ASCII-Editor mit, kann ein beliebiges der oben aufgeführten Linux Programme verwenden (excl. natürlich Notepad.exe). Ubuntu (mit der GNOME Oberfläche) installiert standardmässig gedit.

ASCII-Editoren für die Textkonsole werden hingegen auf Systemen ohne Display resp. ohne graphische Oberfläche verwendet, wobei nano relativ simpel und einfach bedienbar ist und auf vielen Linux-Systemen sowie auch auf OS-X standardmässig installiert wird. Daneben gibt es auch etliche Relikte aus der UNIX-Zeit wie z.B. vi, vim oder emacs...

Erstellen Sie auf der Kommandozeile (also in einem „Terminal“) mit nano datei1 eine Datei namens datei1, speichern Sie diese und öffnen Sie diese wiederum mittels gedit.

Sie können gedit sowohl von der Kommandozeile unter direkter Angabe der zu editierenden Datei starten oder von der graphischen Oberfläche. Auf letzterer ist gedit einfach als „Texteditor“ aufgeführt. Natürlich können Sie auch einfach eine bestehende Text-Datei im Dateimanager doppelclicken ...

Soll eine existierende ASCII-Textdatei auf Kommandozeilenebene bloss kurz angezeigt werden, so kann dies auch mittels cat erfolgen:

bash
cat datei1

cat

'cat' schreibt wie die meisten Konsoleprogramme den „Output“ mittels C-Funktion printf() auf die so genannte „Standard-Ausgabe“ , engl. „standard output“ oder kurz stdout [1].

Wo stdout hinführt (in unserem Fall ins „Terminal“ Window) wird vom übergeordneten Programm vererbt. In unserem Fall von der bash Shell an das von dieser gestartete Programm cat.

Zur Anzeige grösserer Text-Dateien ist cat jedoch unpraktisch, da es gleich die gesamte Datei ausgibt.

Tauglicher hierfür ist das Programm less. Betrachten Sie damit die Systemlog-Datei /var/log/syslog.

Navigieren in less

Mittels der „Leerschlag“ Taste oder den PageUp/PageDown Tasten kann die Datei seitenweise durchgeblättert werden oder mit den up/down Pfeiltasten zeilenweise.

Beenden kann man less per q wie „quit“ und nicht wie die meisten anderen Konsole-Programme per Ctrl-C .

Wenn Sie cat /etc/sudoers eingeben, wird bloss eine Fehlermeldung ausgegeben, obwohl diese Datei im Ordern /etc existiert - wie z.B. mit ls /etc/sudoers überprüfen können.

Linux Permissions

Jedem Dateisystem-Objekt, also jeder Datei (engl. file) und jedem Ordner (engl. directory), ist einem „Eigentümer“ (engl. owner) und eine Sicherheits-Gruppe (engl. group) zugewiesen!

Sowohl für den owner einer Datei als auch für die aufgeführte group als auch „alle anderen“ (engl. others) sind Rechte in Form von „Rechte Flags“ (engl. permissions flags) definiert wie:

  • Leserecht (read) Datei resp. Ordnerinhalt darf gelesen werden
  • Schreibrecht (write) Datei darf verändert werden, resp. Dateien in Ordern erzeugt/gelöscht
  • Ausführungsrecht (execute) Datei darf als Script ausgeführt werden, Ordner „betreten“ Die permissions einer Datei können mit der langen Ausgabe von ls angezeigt werden, also per: ls -l Die Ausgabe erfolgt dann in folgender Form:
<permissionflags> <ref> <owner> <group> <Grösse> <Änderungsdatum> <Dateiname>

wobei die <permissionflags> folgende Bedeutung haben:

    1. Zeichen = Objektart: - normale Datei, d directory (also Ordner), l symbolischen Link
  • ab dem 2. Zeichen werden nacheinander jeweils read/write/exeute Rechte für den owner, die angegebene group sowie others aufgeführt, wobei "others" alle User ausser der aufgeführte owner und Mitglieder der aufgeführten group sind. Also 3 x 3 Zeichen.

Auf Ordnern (directories) ist sowohl Leserecht (read) als auch Ausführungsrecht (execute) nötig, damit betreffende Ordnerinhalt aufgelistet und der Ordner „betreten“ werden kann.

Gespeichert werden diese Datei-Metadaten übrigens im sogenannte inode der jeweiligen Datei.

Frage: Wer hat also gem. ls -l /etc/sudoers welche Rechte auf dieser Datei?





Frage: Wie können Sie diesen Dateiinhalt trotz fehlender read Permission mit cat anzeigen?





  • Dateien und Ordner welche mit einem Punkt beginnen sind standardmässig versteckt, werden also mit normalem ls oder ls -l nicht aufgeführt, können aber mit der ls Option -a ebenfalls aufgelistet werden. Listen Sie auch den versteckten Inhalt Ihres Home Ordners auf...
  • ls kennt noch viele weitere Optionen, welche aber nur selten benötigt werden, vgl. Kurzhilfe per Aufruf von ls mittels Option --help (also ls --help) sowie die ausführliche Hilfeseiten per man ls (Beenden mit q).

Kommandozeile und Input-/Output Redirection

Geben Sie folgendes auf der Kommandozeile ein:

bash
echo hello world

das Programm echo gibt bloss alle aufgeführten Kommandozeilenargumente auf stdout aus.

Sonderzeichen

Viele Sonderzeichen haben auf der Kommandozeile spezielle Bedeutung, ein * ist z.B. das „Wildcard“ Zeichen und trifft somit auf alle Dateien im aktiven Ordner zu. Soll Text auf der Kommandozeile als reiner Text, ohne derartige „Expansion“ angegeben werden, muss der Text in einfache senkrechte Anführungszeichen (') gesetzt werden (sogenannt „quoted“).

Betrachten Sie die folgende Ausgaben:

bash
echo So wird ein Stern * expandiert!
echo 'So wird ein Stern * nicht expandiert ?'

Anführungszeichen

Wie interpretiert die Shell die verschiedenen Anführungszeichen?

  • echo 'i am $USER': Text zwischen Einfach-Anführungszeichen (single quote) wird ohne Variablenexpansion ausgegeben.
  • echo "i am $USER": Text zwischen Doppel-Anführungszeichen (double quote) wird mit Variablenexpansion ausgegeben.
  • echo "my UID is `id -u`" Text zwischen Rückwärts-Hochkomma (backtick) führt die Shell vorgängig als Programm aus ausgeführt und setzt das Ergebnis (resp. den "Standard Output" des aufgerufenen Programms) an der betreffenden Stelle ein!

Umleiten von Output

Per > und >> lässt sich der „Standard Output“ auch statt auf der Console in eine Datei umleiten:

bash
echo 'eine erste Zeile' > datei2
echo 'eine weitere Zeile anhängen' >> datei2

Beachten Sie, dass nur der Text in Anführungszeichen gesetzt werden darf und nicht die Umleitung!

  • > datei: leitet den „Standard Output“ eines Programms in die angegebene Datei um. Existiert diese bereits, wird sie überschrieben.
  • >> datei: hängt den „Standard Output“ eines Programms an eine bestehende Datei an (engl. append)
  • |: program leitet den „Standard Output“ eines Programms auf den „Standard Input“ (stdin) des angegebenen Programms. Normalerweise ist stdin die Tastatur.

Eine Datei kann also statt mit einem Texteditor wie nano oder gedit auch mit echo und Standard-OutputRedirection erstellt werden. Diese Variante eignet sich v.a. für Shell-Scripts (s. später).

Mittels cat in Kombination mit „Standard-Output-Redirection“ lassen sich folglich sogar Dateien kopieren:

bash
cat datei2 >datei3 kopiert datei3 auf datei4

Üblicherweise wird zum Kopieren natürlich das Kommando cp verwendet:

bash
cp datei2 datei3

Der Standard Output (stdout) eines Programmes lässt sich gemäss obiger Tabelle mittels | auch auf den Standard Input (stdin) eines anderen Programmes umleiten (engl. pipe, also wie durch eine Röhre).

Das Programm dmesg gibt den Kernel-Log seit dem Booten auf der Standard-Ausgabe aus. Alleinstehend ausgeführt ist die Ausgabe viele Bildschirmseiten lang (versuchen Sie's!).

Um die Ausgabe seitenweise auszugeben, kann wie folgt der Output von dmes' gefolgt von | in das Programm 'less' gepiped werden, denn less ist ein so genanntes "Pager" Programm.

bash
dmesg | less # Tipp: Je nach System ist vor dmesg ein sudo nötig

Das Weiterblättern erfolgt bei less wie erwähnt per Leerschlag, ein vorzeitige Abbruch per q.

Wieviele Zeilen gibt der Command dmesg aus? Auch dies lässt sich einfach ermitteln:

bash
dmesg | wc -l # wc steht übrigens für Word Count und -l für lines

Programmargumente

Viele Commands (wie cat, less, wc, sort, find, grep, tar, ...) können sowohl mit als auch ohne DateiArgument aufgerufen werden: Erfolgt eine Dateiangabe hinter dem Programmnamen (also ein Commandline-Argument), wird der Inhalt dieser Datei als „Input“ verwendet, andernfalls erfolgt die Eingabe von stdin, also per Tastatureingabe oder im falle von | aus einer "Pipe" von einem anderen Programm.

Diese Philosophie stammt ursprünglich von UNIX: viele kleine Commands, welche jeweils nur eine Aufgabe gut erledigen und sich bei Bedarf mittels "piping" aneinanderreihen lassen...

Erinnern Sie sich an ps -ef | grep X aus dem letzten Versuch? Nun verstehen Sie den Zusammenhang!

  • Lassen Sie sich die Datei /etc/passwd per cat anzeigen ...

Versuchen Sie nun in einer einzigen Commandozeile mittels cat die Passwortdatei /etc/passwd auszulesen und dessen Output direkt auf das Programm cut zu führen, wobei cut durch Angabe geeigneter Optionen jeweils nur den Text vor dem ersten : ausschneiden soll[2].

  • Klappt dies, sortieren Sie zudem das Ergebnis mittels Programm sort (alles in einer einzigen Kommadozeile!)

Wildcards und Dateisuche

Das Wildcardzeichen * kann nicht nur alleine stehend sondern auch in Kombination mit einem Dateinamen und/oder Dateipfad verwendet werden. Die Shell ersetzt also z.B. dat* mit der Liste aller Dateien im aktuellen Ordner, auf welche das Muster passt, also z.B. auf datei1, datei2 oder auch dat oder datei.txt.

Mit ls -l dat* werden also genau jene Dateien detailliert angezeigt, welche mit dat beginnen oder mit cat dat* werden die betreffenden Dateiinhalte allesamt auf stdout angezeigt.

Weiss man hingegen nicht, wo sich eine Datei im Dateisystem befindet, ist man mit find gut bedient:

  • find <Startordner> <Optionen>

Im Dateisystem wird damit alles unter dem <Startordner> gesucht. Nach was gesucht wird kann mittels Optionen angegeben werden: [3]

Um beispielsweise im gesamten Dateisystem nach allen Dateien zu suchen, in deren Dateiname dat vorkommt, geben Sie z.B. folgendes ein:

bash
find / -name '*dat*'
# (Versuchen Sie's, Sie können mit Ctrl-C vorzeitig abbrechen falls es zu lange dauert…)

Frage: Im Beispiel oben ist das Suchmuster '*dat*' in einfache Anführungszeichen gesetzt. Weshalb wohl?




Mit find könnte man auch nach Datei-Attributen suchen, z.B. nach Dateien, welche älter oder nicht älter als so und soviele Tage alt sind oder Dateien mit einem bestimmten „owner“ oder Dateirecht etc. etc.

- bei Programmoptionen

Allgemein ist bei den meisten UNIX-oiden Programmen üblich, dass die Programmoptionen (beginnend mit einem Minuszeichen) unmittelbar nach dem Command angegeben werden müssen.

Eine der wenigen Ausnahme ist das Programm find, bei welchem die Optionen erst nach dem Dateipfad-Argument stehen!

Weiter unterscheidet man generell zwischen kurzen und langen Programmoptionen, wobei üblicherweise kurze Optionen mit nur einem Minuszeichen und einem Buchstaben sowie lange, ausführliche Optionen mit zwei Minuszeichen gefolgt von einem Wort angegeben werden.

Kurze Optionen lassen sich dann kombinieren wie z.B. ls -al statt ls -a -l.

Auch hier ist find eine Ausnahme, denn die find Optionen welche nach dem Dateipfad-Argument angegeben werden sind immer lange Optionen welche mit nur einem Minuszeichen angegeben werden.

find durchsucht also immer die Metadaten der Dateien wogegen grep nach Dateiinhalt sucht!

Dabei müssen die Kommandozeilenargumente bei grep in folgender Reihenfolge angegeben werden:

grep [<Optionen>] <Suchtext> <ein oder mehrere Dateien>

Die eckigen Klammern werden dabei nicht eingegeben, sie bedeuten dass Optionen optional sind.

grep gibt dabei nur jene Zeilen in Dateien aus, in welchen der betreffende Suchtext vorkommt. z.B. um in allen Dateien des aktiven Ordner nach dies zu suchen ist folgende Eingabe nötig: grep dies *

Oft möchte man nicht nur einzelne Dateien durchsuchen sondern alle Dateien unter einem bestimmten Ordner inkl. Unterordner, was mittels grep Option -r (wie „rekursiv“) machbar ist.

Frage: Suchen Sie in allen Dateien unter dem Ordner /etc nach Ihrer User-Id. Wie verwenden Sie grep?:




Für alle Dateien oder Ordner, welche mangels Leserecht nicht lesbar sind, wird ein Fehler ausgegeben.

Um dies zu verhindern, könnte natürlich grep mit vorangesetzem sudo aufzurufen werden, womit auch diese Dateien und Ordner durchsucht würden - oder alternativ durch anfügen von 2> /dev/null wodurch der „Error Output“ (also alle Fehlermeldungen) ins „Nirvana“ beförtert werden.

2> ist also die „Error Output Redirection“ und /dev/null eine Pseudodatei, welche ins Nirvana läuft.

Umgebungsvariablen (Environment Variable)

Die für die laufende Shell gültigen Umgebungsvariablen lassen allesamt mittels env anzeigen.

Oder bloss eine spezifische Umgebungsvariable per: echo $VARIABLENNAME.

Expandieren

Aufgrund des $-Zeichens vor einem beliebigen Wort (z.B. $VARIABELNNAME) "expandiert" die laufende Shell die aufgeführte Umgebungsvariable, d.h. die Shell übergibt dem angegebenen Programm effektiv den Inhalt der Variable.

  • Betrachten Sie mit beiden Varianten (env und mit echo) den Inhalt der Umgebungsvariable PATH.

Wichtige Besonderheit der PATH Variable

Wird auf der Kommandozeile ein Programmname ohne eine davor gesetzte Pfadangabe angegeben, wie z.B. ls und nicht /bin/ls , durchsucht die Shell zwecks Auffinden des Programmes der Reihe nach alle Ordner, welche in der PATH Umgebungsvariable enthalten sind.

Die Shell nutzt also einerseits einige Umgebungsvariablen selbst, andererseits werden die Umgebungsvariablen auch an die aufgerufenen Programme übergeben.

Weiter können auf Shell-Ebene auch Umgebungsvariablen überschrieben oder beliebig neue Umgebungsvariablen definiert werden.

Mit der Umgebungsvariable LANG (oder manchmal auch LANGUAGE [4]) wird z.B. die bevorzugte Ausgabe-Sprache und der Zeichensatz festgelegt, welche Programme verwenden sollen (sofern das aufgerufene Programm „multilingual“ ist und die entsprechende Sprache installiert ist).

Frage: Ermitteln und interpretieren Sie den Inhalt dieser Umgebungsvariable LANG:





Falls Sie „Deutsch“ bei der Installation gewählt haben, werden folglich z.B. bei cat /etc/shadow oder ls --help deutsche (Fehler-)Meldungen ausgegeben.

Auf folgende Weise können die Umgebungsvariablen neu definiert oder überschrieben werden:

Zuweisung                    Effekt
foo=blaDefiniert die Umgebungsvariable foo auf den Wert bla.
foo='bla bla bla'Falls Leerschläge im zu definierendem Text enthalten sind, muss der Text in einfache Anführungszeichen gesetzt werden. Bei Verwendung von Doppel-Anführungszeichen werden darin enthaltene Variablen oder Wildcards vor der Zuweisung „expandiert“.
export foo=blaDie Shell übergibt Umgebungsvariablen auch an neu gestartete Programme weiter, sofern die Variable „exportiert“ wird. Andernfalls kann die Variable nur von der Shell selbst verwendet werden.
foo=bla xyzHier wird foo nur temporär definiert und dem (neu gestarteten) Programm xyz übergeben
foo=`cmd` Der Standard-Output des Programmes cmd wird der Variable foo zugewiesen

Stolperfallen

  • foo= bla: Hier wird aufgrund des Leerschlages hinter dem Gleichheitszeichen die Umgebungsvariable foo als leer definiert und versucht das Programm bla zu starten!
  • foo = bla: Aufgrund des ersten Leerschlages zwischen foo und dem Gleichheitszeichen erfolgt gar keine Variablenzuweisung: foo wird als Programm gestartet und diesem als erstes Argumente das Gleichheitszeichen und als zweites Argument bla übergeben!

Keine Leerschläge bei Zuweisungen

Bei der bash gilt also die Faustregel: Niemals Leerschläge (resp. Whitespace) bei Zuweisungen!

Soll nach einer Programm-Fehlermeldung „gegoogelt“ werden, ist es oft treffender, wenn man englische Fehlermeldungen hat, was durch Übergabe einer leer definierten LANG Umgebungsvariable möglich ist.

Frage:: cat /etc/shadow liefert einen Fehler. Wie ermitteln Sie die englische Fehlermeldung?





Frage:: Verifizieren Sie die Vererbung einer mit export definierten Umgebungsvariablen, indem Sie nach Definition einer neuen Umgebungsvariable eine Sub-Shell (per sh oder bash) starten und die Variable anzeigen.





Ist auch wirklich eine neue (Sub-)Shell aktiv? Kontrollieren Sie dies mittels ps -f (ohne -e !)[5]

Die Sub-Shell können Sie per exit beenden, wodurch Sie wieder in der ursprünglichen Shell landen.

Umgebungsvariablen können nur jeweils „weitervererbt“ werden, sind also nicht „global“ !! Aber wo werden die vordefinierten Umgebungsvariablen gesetzt?

Beim Einloggen des Benutzers wird eine so genannte „Login-Shell“ gestartet und diese included die so genannten „Login-Scripts“: einerseits die Datei /etc/profile, andererseits aus dem Home-Verzeichnis des Benutzers die versteckte Datei .profile

Alle weiteren vom Benutzer gestarteten Programme (inkl. graphische Oberfläche) werden direkt oder indirekt von dieser Login-Shell gestartet und erben somit die in diesen profile-Dateien definierten Umgebungsvariablen.[6]

Jobs

Wird ein Programm gestartet, erhält dieses für dessen Laufzeit die Standard-Eingabe (stdin) von der Tastatur. Die Shell welche das Programm gestartet hat, ist solange von stdin abgekoppelt und blockiert.

Commands können auch im Hintergrund (engl. background) gestartet werden, in welchem Fall das Programm keine Tastatur Standard-Eingabe (stdin) erhält. Somit behält die Shell die Standard-Eingabe.

Sinnvoll ist dies nur, wenn keine Tastatur-Eingabe erforderlich ist, also z.B. für Programme wie gedit welche die Ein-/Ausgabe über die graphischen Oberfläche also in einem eigenen Fenster vornehmen:

bash
gedit datei1 &

Ein vorangesetztes sudo ist jedoch heikel, denn sudo erwartet ja (meist) eine Passworteingabe und wartet demzufolge geduldig und hoffnungslos im Hintergrund auf diese Benutzereingabe!

Statt ein Programm direkt im Hintergrund (mittels &) zu starten, kann ein Vordergrundprozess auch nachträglich in den Background befördert werden, wozu der Vordergrundprozess zuerst per Ctrl-Z angehalten wird und darauf per Shell-Kommando bg im Background wieder reaktiviert wird.

Umgekehrt kann per Kommando fg ein sich im Hintergrund befindlicher Prozess wieder in den Vordergrund gebracht werden.

  • Versuchen Sie beides anhand von gedit

Einen im Vordergrund laufenden Prozess, lässt sich meist per Ctrl-C beenden, wobei der betreffende Prozess hierzu bloss aufgefordert wird, d.h. sich dagegen auch wehren kann oder vor dem Beenden noch Aufräumarbeiten vornehmen kann.

Bei Hintergrund-Prozessen funktioniert Ctrl-C natürlich nicht, da Hintergrundprozesse ja von der StandardEingabe (Tastatur) abgekoppelt sind und diese Tastenkombination folglich nur die Shell erreichen (glücklicherweise ignoriert die Shell Ctrl-C). Versuchen Sie auch dies nach Aufruf von gedit.

Alternativ zu Ctrl-C lassen sich Prozesse aber auch per Kommando kill oder killall beenden. Bei ersterem muss die Prozess-ID (PID) (gemäss ps resp. ps -ef ) angegeben werden, bei killall hingegen der Name des Programmes. Laufen mehrere gleichnamige Programme, werden mit letzterem alle beendet!

  • Öffnen Sie mehrere „Terminal“ Fenster und geben Sie dann killall gnome-terminal-server ein….

Ein Prozess kann eine derartige Aufforderung auch ignorieren, was z.B. bei der bash Shell der Fall ist. Gegen ein „brutales“ SIGKILL (Signal Nr. 9) kann sich aber kein Prozess wehren, denn damit wird der Prozess vom Betriebssytem (Linux-Kenel) sofort beendet, d.h. der Prozess wird nicht wie vorher „zum Beenden aufgefordert“.

Ein killall -SIGKILL bash oder killall -9 bash beendet also brutal alle bash Shells welche mit der eigenen Benutzerid gestartet wurden!

SIGKILL (resp. das Signal -9) sollte man jedoch nur in Ausnahmefällen verwenden. Wie erwähnt können abgesehen vom User root (und ohne sudo-Recht) nur eigene Prozesse beenden

Standardmässig werden beim Beenden eines Prozesses auch dessen Child-Prozesse automatisch beendet – beim Beenden des „Terminal“ (z.B. per killall gnome-terminal-server) werden folglich auch die Shell und in der Folge auch alle aus der Shell gestarteten Vordergrund- und Hintergrund-Prozesse beendet – wie z.B. ein zuvor aus der Shell gestarteter gedit Prozess.

Shell Scripting

Ein „Shell Script“ ist eine Aneinanderreihung von Kommandozeilen in einer Textdatei, welche von einer Shell abgearbeitet werden kann. Bei Shell-Scripts ist wie bei normalen Programmen auch eine bedingte und/oder iterative Ausführung möglich.

Dienlich sind Shell-Scripts vorwiegend für einfache wiederkehrenden Aufgaben, wogegen für komplexe Vorgänge besser leistungsfähigere Scriptsprachen wie Python oder Perl oder gar compilierte Programme auf Basis C oder Java, etc. verwendet werden.

Shell-, Perl- und Python- Scripts werden intensiv auch bei der Linux Systeminstallation oder auch beim Systemstart verwendet – oder auch beim Installieren von Programmpaketen verwendet (z.B. mittels apt install ...) denn in diesem Fall wird zum Schluss des Installationsvorganges ein allenfalls im betreffenden Package vorhandenes „Post-Install-Script“ ausgeführt…

Script interpreter

Beim Starten eines Programmes oder einer Scriptdatei übergibt die Shell dem Linux-Kernel den Pfad zur betreffenden Datei. Der Kernel prüft darauf, ob die Datei gemäss dessen Dateirechte für den User ausführbar, also executable ist.

Folglich müssen Scripts welche direkt aufgerufen werden sollen, das Dateirecht execute gesetzt haben!

Ist dies der Fall, überprüft der Kernel den Beginn der Datei: falls es ein Binärprogramm (resp. eine ELFDatei) ist, startet er dieses. Eine Scriptdatei muss hingegen mit der so genannten „Shebang“ Zeichenfolge #! beginnen, hinter welcher der Pfad zum gewünschten „Kommandointerpreter“ angegeben wird.

Im Falle eines Shell-Scripts ist also hinter der „Shebang“ Zeichenfolge der Pfad zur Shell angegeben, also: #!/bin/sh

Der Kernel startet nach erkennen einer Shebang-Zeile dann den angegebenen Kommandointerpreter (also z.B. eine neue Shell) und übergibt dieser den Pfad zum Scriptdatei als Argument.

Dank diesem Mechanismus sind nicht nur Shell-Scripts mit beliebigen Shells möglich, sondern auch andere beliebige Script-Sprachen – sofern der betreffende Kommandointerpreter auch installiert ist.

Also z.B. auch Perl-Scripts (#!/usr/bin/perl), Phyton-Scripts (#!/usr/bin/phyton), oder Bash-Shell-Scripts (#!/bin/bash), etc. etc. , wobei die bash Shell ja bekanntlich eine erweiterte sh POSIX-Shell ist.

Für den gestarteten Interpreter ist die „Shebang“ Zeile übrigens bloss Kommentar, denn das Hash-Zeichen # ist bei allen aufgeführten Scriptsprachen immer das Zeichen für einen einzeiligen „Kommentar“.

  • Erstellen Sie folgendes Shell-Script namens myscript1
sh
#! /bin/sh
DIRS=`echo $PATH | tr ':' ' ' `
for dir in $DIRS ; do
 echo "Im Programmordner $dir sind `ls $dir | wc -l` Dateien"
done
echo insgesamt also `ls $DIRS | wc -l` Dateien.
  • Die erste Zeile ist die „Shebang“ Zeile.

  • Auf der Scriptdatei muss das „executable“ Flag gesetzt werden was mit chmod +x <scriptname> möglich ist.

  • $PATH ist bekanntlich eine durch Doppelpunkte getrennte Liste. Damit über diese Liste iteriert werden kann, müssen zuerst die Doppelpunkte durch Leerschläge ersetzt werden, was mittels Programmes tr (wie translate) mit den Argumenten Suchzeichen und Ersatzzeichen machbar ist.

  • Die for-Schleife wird über die in der Umgebungsvariable folders gespeicherten Ordnerliste iteriert

  • Um die Anzahl Einträge in einem Dateiordner zu zählen, wird der Output von ls Ordnerpfad in den Standard-Input von wc -l geleitet. wc steht für word count, die Option -l für lines.

  • Unter Verwendung von echo wird dann der Pfad sowie das Ergebnis der Zählung ausgegeben.

  • Die Scriptdatei kann durch Eingabe von myscript1 nicht gestartet werden, denn die Shell sucht ja nur in den Ordnern, welche in der Umgebungsvarialble PATH aufgeführt sind nach ausführbaren Programmen und Scripts. Vor die Datei muss also der Pfad zum aktuellen Ordern gesetzt werden...

  • Führen Sie die Datei deshalb mittels ./myscript1 aus (Achtung: keine Leerschläge nach . und / )

  • Stellen Sie eine Diskrepanz der Werte zur Gesamtsumme fest? Wenn ja, listen Sie mit ls -l / den RootOrdner auf (also den obersten Ordner im Verzeichnisbaum) und überlegen Sie, weshalb das so ist!

Wenn dies klappte, kopieren Sie myscript1 auf myscript2 und erweitern letzteres folgendermassen:

Mittels Programm file und einem oder mehreren Datei-Argumenten kann der Inhalt einer Datei ermittelt werden: Das Programm file versucht den Typ des Dateiinhaltes zu ermitteln, also ob es sich um eine Textdatei, ein Binärprogramm etc. oder (anhand der „Shebang“ Zeile) um eine Scriptdatei handelt.

  • Experimentieren Sie zuerst etwas mit dem Programm 'file'
  • Klappt auch dies, soll nun bei jedem Iterationsdurchlauf (d.h. in jedem Programmordner) die Anzahl Shell-, Python- sowie Perl-Scripts separat gezählt und angezeigt werden.[7]

Commandline Argumente an ein Script übergeben

Wird ein Script mit Argumenten aufgerufen, z.B. ./myscript aaa bbb ccc , sind diese Argumente innerhalb des Scripts mit $1 $2 $3 zugreifbar. $* wären alle Argumente und $0 ist der Aufruf selbst…

  • Versuchen Sie's!

Fehlerjournal

Wenn das System nicht so funktioniert wie es sollte, kann ein Blick in das Fehlerjournal nützlich sein. Unsere Ubunt-Distributionen verwenden das Init-System systemd, bei welchem das Fehlerjournal mittels Command journalctl betrachtet werden kann. Versuchen Sie's (Bedienung und Abbruch wie bei less).

Oft will man nur das Ende des Fehlerjournals betrachten, was mit journalctl -e einfach machbar ist.


  1. Sie kennen printf() vermutlich ja aus dem mcGl-Unterricht, es ist eine Funktion der „C Standard Library“. ↩︎

  2. Tipp: Kurzhilfe von cut per cut --help oder ausführlicher per man cut. ↩︎

  3. Normalerweise folgen Optionen vor den "normalen" Programmargumenten. find hat diesbezüglich eine unübliche Syntax, denn die Optionen sind erst am Schluss aufgeführt, also erst nach Angabe des <Startordners>. ↩︎

  4. https://www.gnu.org/software/gettext/manual/html_node/Locale-Environment-Variables.html#Locale-Environment-Variables ↩︎

  5. Tipp: Achten Sie sich sowohl auf die Process-ID als auch auf die Prozess-Parent ID (PID) ↩︎

  6. Die bash-Shell liest übrigens noch weitere Profildateien ein, vgl. man bash fast zuunterst unter FILES ... ↩︎

  7. Tipp: Den Standard Output von file ordnerpfad/* mittels grep suchkriterium filtern und danach mittels wc -l zählen und ausgeben… ↩︎