{
"$schema": "../schema/questions.schema.json",
"format": "lpic-sim-questions",
"meta": {
"file": "questions_103.json",
"brief": "Fragen zu Topic 103 GNU- und Unix-Befehle (LPIC-1 101-500, Objectives 5.0)",
"author": "Björn Runden
",
"owner": "Björn Runden
",
"assist": "KI-unterstützt (Claude Opus 5.5), geprüft von Björn Runden
",
"version": "0.1.0 (29.10.2026)"
},
"exam": "lpic1-101",
"questions": [
{
"id": "103.1-001",
"objective": "103.1",
"type": "single",
"difficulty": 1,
"question": "Eine Shell-Variable `PROJEKT` soll auch in Programmen sichtbar sein, die aus der aktuellen Shell gestartet werden. Welcher Befehl leistet das?",
"options": [
{ "id": "a", "text": "`export PROJEKT`", "correct": true, "explanation": "`export` übernimmt die Variable in die Umgebung, die an Kindprozesse vererbt wird." },
{ "id": "b", "text": "`set PROJEKT`", "correct": false, "explanation": "`set` setzt Shell-Optionen bzw. Positionsparameter; es exportiert keine Variable." },
{ "id": "c", "text": "`env PROJEKT`", "correct": false, "explanation": "`env` würde versuchen, ein Programm namens `PROJEKT` mit der aktuellen Umgebung zu starten." },
{ "id": "d", "text": "`local PROJEKT`", "correct": false, "explanation": "`local` erzeugt eine lokale Variable innerhalb einer Shell-Funktion." },
{ "id": "e", "text": "`declare -r PROJEKT`", "correct": false, "explanation": "`declare -r` macht die Variable schreibgeschützt, exportiert sie aber nicht (das wäre `declare -x`)." }
],
"explanation": "Shell-Variablen gelten nur in der aktuellen Shell, Umgebungsvariablen werden vererbt. Anzeige: `set` (alle Shell-Variablen und Funktionen), `env`/`printenv` (nur Umgebung).",
"references": ["man 1 bash (Abschnitt ENVIRONMENT)"]
},
{
"id": "103.1-002",
"objective": "103.1",
"type": "single",
"difficulty": 1,
"question": "Welcher Befehl gibt den Text `$HOME` **wörtlich** aus, also ohne ihn durch den Pfad des Home-Verzeichnisses zu ersetzen?",
"options": [
{ "id": "a", "text": "`echo '$HOME'`", "correct": true, "explanation": "In einfachen Anführungszeichen findet keinerlei Ersetzung statt." },
{ "id": "b", "text": "`echo \"$HOME\"`", "correct": false, "explanation": "In doppelten Anführungszeichen werden Variablen ersetzt; nur die Worttrennung unterbleibt." },
{ "id": "c", "text": "`echo $HOME`", "correct": false, "explanation": "Ohne Quoting wird die Variable ersetzt." },
{ "id": "d", "text": "`echo ${HOME}`", "correct": false, "explanation": "`${…}` ist die ausführliche Schreibweise der Variablenersetzung." },
{ "id": "e", "text": "`echo $(HOME)`", "correct": false, "explanation": "`$(…)` ist Befehlsersetzung: Die Shell versucht, einen Befehl `HOME` auszuführen." }
],
"explanation": "Quoting: `'…'` alles wörtlich, `\"…\"` Variablen und Befehlsersetzung aktiv, `\\` maskiert ein einzelnes Zeichen (z. B. `echo \\$HOME`).",
"references": ["man 1 bash (Abschnitt QUOTING)"]
},
{
"id": "103.1-003",
"objective": "103.1",
"type": "fill",
"difficulty": 2,
"question": "Welches Shell-Builtin zeigt an, ob `ls` ein Alias, eine Funktion, ein Builtin oder ein Programm im `PATH` ist? (nur der Befehlsname)",
"answers": ["type"],
"explanation": "`type ls` liefert z. B. `ls is aliased to 'ls --color=auto'`. `which` sucht dagegen nur Programme im `PATH` und kennt keine Aliase oder Builtins.",
"references": ["help type"]
},
{
"id": "103.1-004",
"objective": "103.1",
"type": "multi",
"difficulty": 2,
"question": "Welche Aussagen zur Bash-History treffen zu?",
"options": [
{ "id": "a", "text": "`!!` führt den zuletzt eingegebenen Befehl erneut aus.", "correct": true, "explanation": "History-Expansion: `!!` steht für den vorherigen Befehl, z. B. `sudo !!`." },
{ "id": "b", "text": "Die History wird standardmäßig in `~/.bash_history` gespeichert.", "correct": true, "explanation": "Die Datei legt `HISTFILE` fest; Standard ist `~/.bash_history`." },
{ "id": "c", "text": "`history -c` löscht die Datei `~/.bash_history` sofort.", "correct": false, "explanation": "`history -c` leert nur die History im Speicher der laufenden Shell." },
{ "id": "d", "text": "`HISTSIZE` legt die maximale Zeilenzahl der History-Datei fest.", "correct": false, "explanation": "`HISTSIZE` gilt für die History im Speicher, `HISTFILESIZE` für die Datei." },
{ "id": "e", "text": "`!42` zeigt Befehl Nummer 42 an, ohne ihn auszuführen.", "correct": false, "explanation": "`!42` führt den Befehl aus. Nur anzeigen: `!42:p`." }
],
"explanation": "Weitere Expansionen: `!$` letztes Argument, `!str` letzter Befehl, der mit `str` beginnt. Strg+R sucht rückwärts in der History.",
"references": ["man 1 bash (Abschnitt HISTORY EXPANSION)"]
},
{
"id": "103.1-005",
"objective": "103.1",
"type": "single",
"difficulty": 1,
"question": "Welcher Befehl gibt **nur** die Release-Version des laufenden Kernels aus (z. B. `6.1.0-18-amd64`)?",
"options": [
{ "id": "a", "text": "`uname -r`", "correct": true, "explanation": "`-r` (kernel release) gibt genau die Release-Bezeichnung aus." },
{ "id": "b", "text": "`uname -a`", "correct": false, "explanation": "`-a` gibt alle Informationen aus: Name, Host, Release, Version, Architektur …" },
{ "id": "c", "text": "`uname -m`", "correct": false, "explanation": "`-m` zeigt die Hardware-Architektur, z. B. `x86_64`." },
{ "id": "d", "text": "`uname -n`", "correct": false, "explanation": "`-n` zeigt den Hostnamen (nodename)." },
{ "id": "e", "text": "`uname -s`", "correct": false, "explanation": "`-s` zeigt den Kernelnamen, also `Linux`." }
],
"explanation": "`uname -r` wird oft in Pfaden genutzt, z. B. `/lib/modules/$(uname -r)/`.",
"references": ["man 1 uname"]
},
{
"id": "103.1-006",
"objective": "103.1",
"type": "single",
"difficulty": 2,
"question": "Wie entfernt man die Variable `TMPDIR` **vollständig** aus der aktuellen Shell?",
"options": [
{ "id": "a", "text": "`unset TMPDIR`", "correct": true, "explanation": "`unset` löscht die Variable; danach ist sie weder gesetzt noch exportiert." },
{ "id": "b", "text": "`TMPDIR=\"\"`", "correct": false, "explanation": "Die Variable bleibt gesetzt, nur ihr Wert ist leer." },
{ "id": "c", "text": "`export -n TMPDIR`", "correct": false, "explanation": "`export -n` nimmt nur das Export-Attribut weg; die Shell-Variable bleibt bestehen." },
{ "id": "d", "text": "`env -u TMPDIR`", "correct": false, "explanation": "`env -u` entfernt die Variable nur aus der Umgebung des damit gestarteten Befehls." },
{ "id": "e", "text": "`set -u TMPDIR`", "correct": false, "explanation": "`set -u` lässt die Shell bei Zugriff auf ungesetzte Variablen einen Fehler melden; `TMPDIR` wird dabei zum Positionsparameter." }
],
"explanation": "Unterschied gesetzt/leer: `${VAR-x}` liefert `x` nur, wenn `VAR` ungesetzt ist, `${VAR:-x}` auch bei leerem Wert.",
"references": ["help unset"]
},
{
"id": "103.2-001",
"objective": "103.2",
"type": "single",
"difficulty": 1,
"question": "Welche Befehlskette gibt genau die Zeilen 11 bis 20 einer Datei aus?",
"options": [
{ "id": "a", "text": "`head -n 20 datei | tail -n 10`", "correct": true, "explanation": "Erst die ersten 20 Zeilen, davon die letzten 10 – also 11 bis 20." },
{ "id": "b", "text": "`tail -n 20 datei | head -n 10`", "correct": false, "explanation": "Das liefert die ersten 10 der letzten 20 Zeilen der Datei." },
{ "id": "c", "text": "`sed -n '10,20p' datei`", "correct": false, "explanation": "Gibt Zeilen 10 bis 20 aus, also 11 Zeilen." },
{ "id": "d", "text": "`head -n 11-20 datei`", "correct": false, "explanation": "`head` kennt keine Bereichsangabe." },
{ "id": "e", "text": "`cut -c 11-20 datei`", "correct": false, "explanation": "`cut -c` wählt Zeichen 11 bis 20 jeder Zeile, keine Zeilen." }
],
"explanation": "Alternativ `sed -n '11,20p' datei`. `tail -n +11` gibt alles ab Zeile 11 aus.",
"references": ["man 1 head", "man 1 tail"]
},
{
"id": "103.2-002",
"objective": "103.2",
"type": "single",
"difficulty": 1,
"question": "Welcher Befehl gibt nur die Benutzernamen (das erste Feld) aus `/etc/passwd` aus?",
"options": [
{ "id": "a", "text": "`cut -d: -f1 /etc/passwd`", "correct": true, "explanation": "`-d:` setzt den Doppelpunkt als Trenner, `-f1` wählt das erste Feld." },
{ "id": "b", "text": "`cut -f1 /etc/passwd`", "correct": false, "explanation": "Ohne `-d` trennt `cut` an Tabulatoren; die Zeilen werden ganz ausgegeben." },
{ "id": "c", "text": "`sort -t: -k1 /etc/passwd`", "correct": false, "explanation": "Das sortiert nach dem ersten Feld, gibt aber vollständige Zeilen aus." },
{ "id": "d", "text": "`tr ':' ' ' < /etc/passwd`", "correct": false, "explanation": "`tr` ersetzt nur die Doppelpunkte durch Leerzeichen." },
{ "id": "e", "text": "`paste -d: /etc/passwd`", "correct": false, "explanation": "`paste` fügt Zeilen mehrerer Dateien nebeneinander; mit einer Datei gibt es sie unverändert aus." }
],
"explanation": "Gleichwertig: `awk -F: '{print $1}' /etc/passwd`.",
"references": ["man 1 cut"]
},
{
"id": "103.2-003",
"objective": "103.2",
"type": "single",
"difficulty": 2,
"question": "In einer unsortierten Datei sollen alle Zeilen mit der Anzahl ihres Vorkommens ausgegeben werden. Welche Befehlskette ist korrekt?",
"options": [
{ "id": "a", "text": "`sort datei | uniq -c`", "correct": true, "explanation": "`uniq` fasst nur benachbarte gleiche Zeilen zusammen; daher vorher sortieren." },
{ "id": "b", "text": "`uniq -c datei`", "correct": false, "explanation": "Ohne Sortierung werden gleiche, aber nicht benachbarte Zeilen getrennt gezählt." },
{ "id": "c", "text": "`sort -u datei | wc -l`", "correct": false, "explanation": "Das zählt nur die Anzahl verschiedener Zeilen." },
{ "id": "d", "text": "`uniq -d datei | sort`", "correct": false, "explanation": "`uniq -d` zeigt nur benachbarte doppelte Zeilen, ohne Zählung." },
{ "id": "e", "text": "`cat -n datei | uniq`", "correct": false, "explanation": "Durch die Zeilennummern sind alle Zeilen verschieden; nichts wird zusammengefasst." }
],
"explanation": "Häufigste Zeilen zuerst: `sort datei | uniq -c | sort -nr`.",
"references": ["man 1 uniq", "man 1 sort"]
},
{
"id": "103.3-001",
"objective": "103.3",
"type": "single",
"difficulty": 1,
"question": "Ein Verzeichnis soll rekursiv kopiert werden; Rechte, Eigentümer, Zeitstempel und symbolische Links sollen erhalten bleiben. Welcher Befehl ist geeignet?",
"options": [
{ "id": "a", "text": "`cp -a quelle ziel`", "correct": true, "explanation": "`-a` (archive) entspricht `-dR --preserve=all`: rekursiv, Links als Links, alle Attribute." },
{ "id": "b", "text": "`cp -r quelle ziel`", "correct": false, "explanation": "`-r` kopiert rekursiv, übernimmt aber Eigentümer und Zeitstempel nicht." },
{ "id": "c", "text": "`cp -p quelle ziel`", "correct": false, "explanation": "`-p` erhält Attribute, kopiert aber Verzeichnisse nicht rekursiv." },
{ "id": "d", "text": "`cp -l quelle ziel`", "correct": false, "explanation": "`-l` legt Hardlinks statt Kopien an." },
{ "id": "e", "text": "`mv -a quelle ziel`", "correct": false, "explanation": "`mv` verschiebt und kennt keine Option `-a`." }
],
"explanation": "Eigentümer kann nur root übernehmen; als normaler Benutzer gehören Kopien dem Kopierenden.",
"references": ["man 1 cp"]
},
{
"id": "103.3-002",
"objective": "103.3",
"type": "fill",
"difficulty": 2,
"question": "Geben Sie den `find`-Befehl ein, der unterhalb von `/var` alle Dateien findet, die **größer als 100 MiB** sind.",
"answers": ["find /var -size +100M", "find /var -type f -size +100M", "find /var -size +100M -type f"],
"explanation": "`-size +100M`: größer als 100 MiB (`k`, `M`, `G` als Einheiten). `-size -100M` wäre kleiner. `-type f` beschränkt auf reguläre Dateien.",
"references": ["man 1 find"]
},
{
"id": "103.3-003",
"objective": "103.3",
"type": "single",
"difficulty": 1,
"question": "Welcher Befehl erstellt ein gzip-komprimiertes tar-Archiv `backup.tar.gz` von `/etc`?",
"options": [
{ "id": "a", "text": "`tar -czf backup.tar.gz /etc`", "correct": true, "explanation": "`c` create, `z` gzip, `f` Archivdatei." },
{ "id": "b", "text": "`tar -xzf backup.tar.gz /etc`", "correct": false, "explanation": "`x` entpackt – hier würde nur `/etc` aus dem Archiv extrahiert." },
{ "id": "c", "text": "`tar -cjf backup.tar.gz /etc`", "correct": false, "explanation": "`j` komprimiert mit bzip2; der Name `.gz` wäre irreführend." },
{ "id": "d", "text": "`tar -tzf backup.tar.gz /etc`", "correct": false, "explanation": "`t` listet den Inhalt eines vorhandenen Archivs." },
{ "id": "e", "text": "`gzip -r /etc > backup.tar.gz`", "correct": false, "explanation": "`gzip -r` komprimiert jede Datei in `/etc` einzeln an Ort und Stelle; es entsteht kein Archiv." }
],
"explanation": "Kompression bei tar: `z` gzip, `j` bzip2, `J` xz. Modi: `c` erstellen, `x` entpacken, `t` auflisten.",
"references": ["man 1 tar"]
},
{
"id": "103.3-004",
"objective": "103.3",
"type": "multi",
"difficulty": 2,
"question": "Welche Dateinamen passen auf das Shell-Muster `d?t[0-9]*`?",
"options": [
{ "id": "a", "text": "`dat1`", "correct": true, "explanation": "`d`, beliebiges Zeichen `a`, `t`, Ziffer `1`, danach nichts (`*` darf leer sein)." },
{ "id": "b", "text": "`dot42.txt`", "correct": true, "explanation": "`d`, `o`, `t`, Ziffer `4`, Rest `2.txt` passt auf `*`." },
{ "id": "c", "text": "`dt1`", "correct": false, "explanation": "`?` verlangt genau ein Zeichen zwischen `d` und `t`." },
{ "id": "d", "text": "`data1`", "correct": false, "explanation": "Das vierte Zeichen `a` ist keine Ziffer." },
{ "id": "e", "text": "`Dat1`", "correct": false, "explanation": "Globbing unterscheidet Groß- und Kleinschreibung; `D` ist nicht `d`." }
],
"explanation": "Globbing: `*` beliebig viele Zeichen (auch keine), `?` genau ein Zeichen, `[…]` ein Zeichen aus der Menge, `[!…]` ein Zeichen nicht aus der Menge.",
"references": ["man 7 glob"]
},
{
"id": "103.3-005",
"objective": "103.3",
"type": "single",
"difficulty": 1,
"question": "Welcher Befehl ermittelt den Typ einer Datei anhand ihres Inhalts (z. B. „ELF 64-bit executable“ oder „gzip compressed data“)?",
"options": [
{ "id": "a", "text": "`file`", "correct": true, "explanation": "`file` vergleicht den Inhalt mit Signaturen (Magic Numbers)." },
{ "id": "b", "text": "`stat`", "correct": false, "explanation": "`stat` zeigt Metadaten aus dem Inode (Größe, Rechte, Zeiten), nicht den Inhaltstyp." },
{ "id": "c", "text": "`type`", "correct": false, "explanation": "`type` bestimmt, wie die Shell einen Befehlsnamen auflöst." },
{ "id": "d", "text": "`ls -l`", "correct": false, "explanation": "`ls -l` zeigt nur den Dateityp im Sinne von Datei/Verzeichnis/Link usw." },
{ "id": "e", "text": "`which`", "correct": false, "explanation": "`which` sucht ein Programm im `PATH`." }
],
"explanation": "Unter Linux bestimmt nicht die Endung den Typ, sondern der Inhalt; `file` wertet dazu die magic-Datenbank aus.",
"references": ["man 1 file"]
},
{
"id": "103.3-006",
"objective": "103.3",
"type": "single",
"difficulty": 2,
"question": "Der Master Boot Record (erster Sektor, 512 Byte) von `/dev/sda` soll in die Datei `mbr.img` gesichert werden. Welcher Befehl ist korrekt?",
"options": [
{ "id": "a", "text": "`dd if=/dev/sda of=mbr.img bs=512 count=1`", "correct": true, "explanation": "`if` Quelle, `of` Ziel, ein Block zu 512 Byte." },
{ "id": "b", "text": "`dd if=mbr.img of=/dev/sda bs=512 count=1`", "correct": false, "explanation": "Quelle und Ziel sind vertauscht – das würde den MBR mit der Datei überschreiben." },
{ "id": "c", "text": "`dd if=/dev/sda of=mbr.img bs=512 skip=1 count=1`", "correct": false, "explanation": "`skip=1` überspringt den ersten Block der Quelle – kopiert würde der zweite Sektor, nicht der MBR." },
{ "id": "d", "text": "`dd if=/dev/sda1 of=mbr.img bs=512 count=1`", "correct": false, "explanation": "`/dev/sda1` ist die erste Partition; der MBR liegt am Anfang der ganzen Platte." },
{ "id": "e", "text": "`cp /dev/sda mbr.img`", "correct": false, "explanation": "Das würde die gesamte Platte kopieren, nicht nur den ersten Sektor." }
],
"explanation": "Der MBR enthält Bootloader-Code (446 Byte), Partitionstabelle (64 Byte) und Signatur (2 Byte).",
"references": ["man 1 dd"]
},
{
"id": "103.4-001",
"objective": "103.4",
"type": "single",
"difficulty": 2,
"question": "Standardausgabe **und** Fehlerausgabe eines Befehls sollen in dieselbe Datei geschrieben werden. Welche Schreibweise ist korrekt?",
"options": [
{ "id": "a", "text": "`befehl > log.txt 2>&1`", "correct": true, "explanation": "Erst stdout in die Datei, dann stderr auf das (bereits umgelenkte) stdout." },
{ "id": "b", "text": "`befehl 2>&1 > log.txt`", "correct": false, "explanation": "Reihenfolge: stderr wird auf das ursprüngliche stdout (Terminal) gelegt, erst danach stdout in die Datei." },
{ "id": "c", "text": "`befehl 2> log.txt`", "correct": false, "explanation": "Nur die Fehlerausgabe landet in der Datei." },
{ "id": "d", "text": "`befehl | log.txt`", "correct": false, "explanation": "Die Pipe erwartet einen Befehl; `log.txt` würde als Programm gesucht." },
{ "id": "e", "text": "`befehl >> log.txt 1>&2`", "correct": false, "explanation": "`1>&2` lenkt stdout anschließend wieder auf stderr (Terminal) um; die Datei bleibt leer." }
],
"explanation": "Umleitungen werden von links nach rechts ausgewertet. Bash-Kurzform: `befehl &> log.txt`.",
"references": ["man 1 bash (Abschnitt REDIRECTION)"]
},
{
"id": "103.4-002",
"objective": "103.4",
"type": "fill",
"difficulty": 1,
"question": "Welche Umleitung (nur die Umleitung, ohne Befehl) verwirft die **Fehlerausgabe** eines Befehls?",
"answers": ["2>/dev/null", "2> /dev/null"],
"explanation": "Dateideskriptor 2 ist stderr; `/dev/null` verwirft alles, was hineingeschrieben wird.",
"references": ["man 4 null"]
},
{
"id": "103.4-003",
"objective": "103.4",
"type": "single",
"difficulty": 1,
"question": "Die Ausgabe eines Befehls soll auf dem Bildschirm erscheinen **und** gleichzeitig in `ausgabe.txt` gespeichert werden. Wie geht das?",
"options": [
{ "id": "a", "text": "`befehl | tee ausgabe.txt`", "correct": true, "explanation": "`tee` kopiert stdin nach stdout und zusätzlich in die Datei(en); `-a` hängt an." },
{ "id": "b", "text": "`befehl > ausgabe.txt | cat`", "correct": false, "explanation": "stdout geht vollständig in die Datei; an `cat` kommt nichts an." },
{ "id": "c", "text": "`befehl >> ausgabe.txt`", "correct": false, "explanation": "Hängt nur an die Datei an; auf dem Bildschirm erscheint nichts." },
{ "id": "d", "text": "`befehl | cat > ausgabe.txt`", "correct": false, "explanation": "Die Ausgabe landet nur in der Datei." },
{ "id": "e", "text": "`befehl 2>&1 ausgabe.txt`", "correct": false, "explanation": "`ausgabe.txt` würde als Argument an den Befehl übergeben." }
],
"explanation": "`tee` ist wie ein T-Stück in der Pipe. Mit `sudo tee datei` schreibt man z. B. als root in geschützte Dateien.",
"references": ["man 1 tee"]
},
{
"id": "103.4-004",
"objective": "103.4",
"type": "single",
"difficulty": 2,
"question": "Alle von `find` gefundenen `*.tmp`-Dateien sollen gelöscht werden, indem ihre Namen als **Argumente** an `rm` übergeben werden. Welche Befehlszeile tut das?",
"options": [
{ "id": "a", "text": "`find . -name '*.tmp' | xargs rm`", "correct": true, "explanation": "`xargs` liest Namen von stdin und hängt sie als Argumente an `rm`." },
{ "id": "b", "text": "`find . -name '*.tmp' | rm`", "correct": false, "explanation": "`rm` liest keine Dateinamen von stdin; es meldet fehlende Operanden." },
{ "id": "c", "text": "`find . -name '*.tmp' > rm`", "correct": false, "explanation": "Das schreibt die Liste in eine Datei namens `rm`." },
{ "id": "d", "text": "`find . -name '*.tmp' | tee rm`", "correct": false, "explanation": "`tee` schreibt die Liste in die Datei `rm` und auf den Bildschirm." },
{ "id": "e", "text": "`rm < find . -name '*.tmp'`", "correct": false, "explanation": "`<` erwartet eine Datei als Eingabe, keinen Befehl." }
],
"explanation": "Bei Namen mit Leerzeichen: `find … -print0 | xargs -0 rm`. Alternativ ohne Pipe: `find . -name '*.tmp' -delete` oder `-exec rm {} +`.",
"references": ["man 1 xargs"]
},
{
"id": "103.4-005",
"objective": "103.4",
"type": "multi",
"difficulty": 1,
"question": "Welche Aussagen zu Umleitungen und Pipes treffen zu?",
"options": [
{ "id": "a", "text": "`>>` hängt die Standardausgabe an eine Datei an.", "correct": true, "explanation": "Existiert die Datei nicht, wird sie angelegt." },
{ "id": "b", "text": "`<` liest die Standardeingabe aus einer Datei.", "correct": true, "explanation": "Beispiel: `sort < liste.txt`." },
{ "id": "c", "text": "`2>&1` leitet die Standardausgabe auf die Fehlerausgabe um.", "correct": false, "explanation": "Umgekehrt: stderr (2) wird dorthin geleitet, wohin stdout (1) gerade zeigt." },
{ "id": "d", "text": "`|` verbindet die Fehlerausgabe mit der Eingabe des nächsten Befehls.", "correct": false, "explanation": "Die Pipe verbindet stdout mit stdin; stderr nur mit `|&` bzw. `2>&1 |`." },
{ "id": "e", "text": "`>` hängt an, wenn die Datei bereits existiert.", "correct": false, "explanation": "`>` überschreibt (kürzt die Datei auf 0); nur `>>` hängt an." }
],
"explanation": "Dateideskriptoren: 0 stdin, 1 stdout, 2 stderr. `set -o noclobber` verhindert versehentliches Überschreiben mit `>`.",
"references": ["man 1 bash (Abschnitt REDIRECTION)"]
},
{
"id": "103.4-006",
"objective": "103.4",
"type": "single",
"difficulty": 1,
"question": "Mit welcher Schreibweise setzt die Bash die **Ausgabe** eines Befehls in die Kommandozeile ein, z. B. in `echo \"Heute ist …\"`?",
"options": [
{ "id": "a", "text": "`$(date +%A)`", "correct": true, "explanation": "Befehlsersetzung: Die Ausgabe von `date +%A` ersetzt den Ausdruck." },
{ "id": "b", "text": "`${date +%A}`", "correct": false, "explanation": "`${…}` ist Parameter-/Variablenersetzung und hier ein Syntaxfehler." },
{ "id": "c", "text": "`$((date +%A))`", "correct": false, "explanation": "`$((…))` ist arithmetische Expansion." },
{ "id": "d", "text": "`'date +%A'`", "correct": false, "explanation": "Einfache Anführungszeichen ergeben den Text wörtlich." },
{ "id": "e", "text": "`<(date +%A)`", "correct": false, "explanation": "Prozessersetzung liefert einen Dateinamen (z. B. `/dev/fd/63`), nicht den Text." }
],
"explanation": "Ältere, gleichwertige Schreibweise mit Backticks (Gravis-Zeichen). `$(…)` ist besser lesbar und verschachtelbar.",
"references": ["man 1 bash (Abschnitt Command Substitution)"]
},
{
"id": "103.5-001",
"objective": "103.5",
"type": "single",
"difficulty": 1,
"question": "Welches Signal kann ein Prozess weder abfangen noch ignorieren?",
"options": [
{ "id": "a", "text": "SIGKILL (9)", "correct": true, "explanation": "SIGKILL beendet den Prozess unmittelbar durch den Kernel; es gibt keinen Handler." },
{ "id": "b", "text": "SIGTERM (15)", "correct": false, "explanation": "SIGTERM ist die höfliche Aufforderung zum Beenden und kann abgefangen werden." },
{ "id": "c", "text": "SIGHUP (1)", "correct": false, "explanation": "SIGHUP wird oft abgefangen, z. B. um Konfiguration neu zu laden." },
{ "id": "d", "text": "SIGINT (2)", "correct": false, "explanation": "SIGINT (Strg+C) kann abgefangen werden." },
{ "id": "e", "text": "SIGUSR1 (10)", "correct": false, "explanation": "Benutzerdefiniertes Signal, das Programme frei abfangen." }
],
"explanation": "Neben SIGKILL kann auch SIGSTOP nicht abgefangen werden. Liste aller Signale: `kill -l`.",
"references": ["man 7 signal"]
},
{
"id": "103.5-002",
"objective": "103.5",
"type": "fill",
"difficulty": 1,
"question": "Welches Signal sendet `kill `, wenn kein Signal angegeben wird? (Name oder Nummer)",
"answers": ["SIGTERM", "TERM", "15"],
"case_sensitive": false,
"explanation": "Standard ist SIGTERM (15). Erst wenn ein Prozess darauf nicht reagiert, nimmt man SIGKILL (`kill -9`).",
"references": ["man 1 kill"]
},
{
"id": "103.5-003",
"objective": "103.5",
"type": "single",
"difficulty": 1,
"question": "Ein Skript soll weiterlaufen, nachdem sich der Benutzer abgemeldet hat. Welche Befehlszeile ist dafür gedacht?",
"options": [
{ "id": "a", "text": "`nohup ./skript.sh &`", "correct": true, "explanation": "`nohup` ignoriert SIGHUP und leitet die Ausgabe nach `nohup.out` um; `&` startet im Hintergrund." },
{ "id": "b", "text": "`./skript.sh &`", "correct": false, "explanation": "Hintergrundjobs können beim Abmelden SIGHUP erhalten und beendet werden." },
{ "id": "c", "text": "`bg ./skript.sh`", "correct": false, "explanation": "`bg` setzt einen gestoppten Job fort und erwartet eine Jobnummer, keinen Befehl." },
{ "id": "d", "text": "`nice ./skript.sh`", "correct": false, "explanation": "`nice` ändert nur die Priorität." },
{ "id": "e", "text": "`jobs ./skript.sh`", "correct": false, "explanation": "`jobs` listet Jobs der aktuellen Shell." }
],
"explanation": "Alternativen: `disown` für laufende Jobs, oder Terminal-Multiplexer wie `screen`/`tmux`, von denen man sich trennen und später wieder verbinden kann.",
"references": ["man 1 nohup"]
},
{
"id": "103.5-004",
"objective": "103.5",
"type": "single",
"difficulty": 1,
"question": "`jobs` zeigt drei Jobs. Wie holt man Job Nummer 2 in den Vordergrund?",
"options": [
{ "id": "a", "text": "`fg %2`", "correct": true, "explanation": "`fg` holt den angegebenen Job in den Vordergrund; `%2` ist die Jobspezifikation." },
{ "id": "b", "text": "`bg %2`", "correct": false, "explanation": "`bg` setzt einen gestoppten Job im Hintergrund fort." },
{ "id": "c", "text": "`jobs %2`", "correct": false, "explanation": "Zeigt nur den Status von Job 2." },
{ "id": "d", "text": "`kill -CONT %2`", "correct": false, "explanation": "Setzt den Job fort, er bleibt aber im Hintergrund." },
{ "id": "e", "text": "`wait %2`", "correct": false, "explanation": "`wait` wartet auf das Ende des Jobs, ohne ihn in den Vordergrund zu holen." }
],
"explanation": "Strg+Z stoppt den Vordergrundjob, `bg` lässt ihn im Hintergrund weiterlaufen, `fg` holt ihn zurück.",
"references": ["help fg", "help jobs"]
},
{
"id": "103.5-005",
"objective": "103.5",
"type": "multi",
"difficulty": 2,
"question": "Mit welchen Befehlen ermittelt man die Prozess-ID(s) laufender `sshd`-Prozesse anhand des Namens?",
"options": [
{ "id": "a", "text": "`pgrep sshd`", "correct": true, "explanation": "`pgrep` gibt die PIDs aller Prozesse aus, deren Name auf das Muster passt." },
{ "id": "b", "text": "`pidof sshd`", "correct": true, "explanation": "`pidof` gibt die PIDs eines Programms mit genau diesem Namen aus." },
{ "id": "c", "text": "`pkill sshd`", "correct": false, "explanation": "`pkill` sendet ein Signal (Standard SIGTERM) an die Prozesse – Vorsicht!" },
{ "id": "d", "text": "`ps -p sshd`", "correct": false, "explanation": "`-p` erwartet eine PID-Liste, keinen Namen (richtig wäre `ps -C sshd`)." },
{ "id": "e", "text": "`top -n sshd`", "correct": false, "explanation": "`-n` legt bei `top` die Anzahl der Durchläufe fest." }
],
"explanation": "Auch üblich: `ps aux | grep sshd`. `pgrep -a` zeigt zusätzlich die Befehlszeile, `pgrep -u` filtert nach Benutzer.",
"references": ["man 1 pgrep", "man 8 pidof"]
},
{
"id": "103.5-006",
"objective": "103.5",
"type": "single",
"difficulty": 1,
"question": "Welcher Befehl zeigt kompakt die Laufzeit des Systems, die Anzahl angemeldeter Benutzer und die Load Average der letzten 1, 5 und 15 Minuten?",
"options": [
{ "id": "a", "text": "`uptime`", "correct": true, "explanation": "`uptime` gibt genau diese Zeile aus (Werte aus `/proc/uptime` und `/proc/loadavg`)." },
{ "id": "b", "text": "`free`", "correct": false, "explanation": "`free` zeigt Arbeitsspeicher und Swap." },
{ "id": "c", "text": "`vmstat`", "correct": false, "explanation": "`vmstat` zeigt Prozess-, Speicher-, I/O- und CPU-Statistiken, aber keine Load Average." },
{ "id": "d", "text": "`ps aux`", "correct": false, "explanation": "`ps aux` listet Prozesse." },
{ "id": "e", "text": "`watch`", "correct": false, "explanation": "`watch` führt einen Befehl wiederholt aus und zeigt seine Ausgabe." }
],
"explanation": "Die Load Average ist die mittlere Zahl laufender bzw. auf CPU oder I/O wartender Prozesse. Sie steht auch in der ersten Zeile von `top` und `w`.",
"references": ["man 1 uptime"]
},
{
"id": "103.6-001",
"objective": "103.6",
"type": "single",
"difficulty": 1,
"question": "In welchem Bereich liegen Nice-Werte unter Linux, und welcher Wert bedeutet die **höchste** Priorität?",
"options": [
{ "id": "a", "text": "−20 bis 19; −20 ist die höchste Priorität", "correct": true, "explanation": "Je niedriger der Nice-Wert, desto „unfreundlicher“ ist der Prozess, also desto mehr CPU-Zeit bekommt er." },
{ "id": "b", "text": "−20 bis 19; 19 ist die höchste Priorität", "correct": false, "explanation": "19 ist die niedrigste Priorität." },
{ "id": "c", "text": "0 bis 39; 39 ist die höchste Priorität", "correct": false, "explanation": "Nice-Werte sind vorzeichenbehaftet und reichen von −20 bis 19." },
{ "id": "d", "text": "1 bis 99; 99 ist die höchste Priorität", "correct": false, "explanation": "1–99 ist der Bereich der Echtzeitprioritäten, keine Nice-Werte." },
{ "id": "e", "text": "−19 bis 20; 0 ist die höchste Priorität", "correct": false, "explanation": "Falscher Bereich; 0 ist der Standardwert." }
],
"explanation": "Standard ist 0. `nice` ohne `-n` startet mit +10. In `ps -l` erscheint der Wert in Spalte NI, in `top` als NI.",
"references": ["man 1 nice"]
},
{
"id": "103.6-002",
"objective": "103.6",
"type": "fill",
"difficulty": 2,
"question": "Geben Sie den Befehl ein, der den Nice-Wert des laufenden Prozesses mit der PID 1234 auf 10 setzt.",
"answers": ["renice -n 10 -p 1234", "renice 10 1234", "renice -n 10 1234", "renice 10 -p 1234", "renice +10 1234", "renice +10 -p 1234", "renice -n +10 -p 1234"],
"explanation": "`renice` ändert laufende Prozesse (`-p` PID, `-u` Benutzer, `-g` Prozessgruppe); `nice` gilt nur beim Starten.",
"references": ["man 1 renice"]
},
{
"id": "103.6-003",
"objective": "103.6",
"type": "multi",
"difficulty": 2,
"question": "Was darf ein **normaler Benutzer** (ohne besondere Limits) standardmäßig?",
"options": [
{ "id": "a", "text": "Ein Programm mit Nice-Wert 10 starten", "correct": true, "explanation": "Positive Nice-Werte (niedrigere Priorität) darf jeder setzen: `nice -n 10 programm`." },
{ "id": "b", "text": "Den Nice-Wert eines eigenen laufenden Prozesses erhöhen", "correct": true, "explanation": "Die eigene Priorität senken ist erlaubt: `renice -n 15 -p `." },
{ "id": "c", "text": "Ein Programm mit Nice-Wert −5 starten", "correct": false, "explanation": "Negative Nice-Werte erfordern root (bzw. CAP_SYS_NICE)." },
{ "id": "d", "text": "Den Nice-Wert eines Prozesses eines anderen Benutzers ändern", "correct": false, "explanation": "Nur eigene Prozesse; fremde nur als root." },
{ "id": "e", "text": "Den Nice-Wert eines eigenen Prozesses wieder unter den bisherigen Wert senken", "correct": false, "explanation": "Die Priorität wieder anheben darf standardmäßig nur root (Ausnahme: über `RLIMIT_NICE` erlaubte Bereiche)." }
],
"explanation": "Grundregel: Jeder darf seine Prozesse „netter“ machen, nur root darf Priorität erhöhen.",
"references": ["man 1 renice", "man 2 setpriority"]
},
{
"id": "103.7-001",
"objective": "103.7",
"type": "single",
"difficulty": 1,
"question": "Welche grep-Option gibt alle Zeilen aus, die **nicht** auf das Muster passen?",
"options": [
{ "id": "a", "text": "`-v`", "correct": true, "explanation": "`-v` (`--invert-match`) kehrt die Auswahl um." },
{ "id": "b", "text": "`-i`", "correct": false, "explanation": "`-i` ignoriert Groß-/Kleinschreibung." },
{ "id": "c", "text": "`-c`", "correct": false, "explanation": "`-c` gibt nur die Anzahl passender Zeilen aus." },
{ "id": "d", "text": "`-l`", "correct": false, "explanation": "`-l` gibt nur die Namen der Dateien mit Treffern aus." },
{ "id": "e", "text": "`-n`", "correct": false, "explanation": "`-n` stellt die Zeilennummer voran." }
],
"explanation": "Wichtige Optionen: `-E` erweiterte RE, `-F` feste Zeichenkette, `-r` rekursiv, `-w` ganzes Wort, `-o` nur den Treffer.",
"references": ["man 1 grep"]
},
{
"id": "103.7-002",
"objective": "103.7",
"type": "single",
"difficulty": 2,
"question": "Welcher Befehl gibt eine Konfigurationsdatei **ohne** Kommentarzeilen (beginnen mit `#`) und **ohne** Leerzeilen aus?",
"options": [
{ "id": "a", "text": "`grep -Ev '^(#|$)' datei`", "correct": true, "explanation": "Das Muster passt auf Zeilen, die mit `#` beginnen oder leer sind; `-v` kehrt um." },
{ "id": "b", "text": "`grep -v '#' datei`", "correct": false, "explanation": "Entfernt auch Zeilen mit `#` in der Mitte und lässt Leerzeilen stehen." },
{ "id": "c", "text": "`grep -E '^#|^$' datei`", "correct": false, "explanation": "Gibt nur Kommentar- und Leerzeilen aus." },
{ "id": "d", "text": "`grep -v '^#$' datei`", "correct": false, "explanation": "Entfernt nur Zeilen, die ausschließlich aus `#` bestehen." },
{ "id": "e", "text": "`grep -cv '^#' datei`", "correct": false, "explanation": "`-c` gibt nur eine Anzahl aus." }
],
"explanation": "Anker: `^` Zeilenanfang, `$` Zeilenende; `^$` ist eine leere Zeile. `|` (Alternative) und `( )` erfordern ERE (`-E`) oder in BRE `\\|` und `\\( \\)`.",
"references": ["man 7 regex", "man 1 grep"]
},
{
"id": "103.7-003",
"objective": "103.7",
"type": "fill",
"difficulty": 2,
"question": "Geben Sie den sed-Befehl ein, der in der Datei `datei` **jedes** Vorkommen von `foo` durch `bar` ersetzt und das Ergebnis auf stdout ausgibt.",
"answers": ["sed 's/foo/bar/g' datei", "sed \"s/foo/bar/g\" datei", "sed s/foo/bar/g datei", "sed -e 's/foo/bar/g' datei", "sed -e \"s/foo/bar/g\" datei"],
"explanation": "`s/alt/neu/` ersetzt das erste Vorkommen je Zeile, das Flag `g` alle. Mit `-i` wird die Datei selbst geändert.",
"references": ["man 1 sed"]
},
{
"id": "103.7-004",
"objective": "103.7",
"type": "multi",
"difficulty": 2,
"question": "Welche Aussagen zu regulären Ausdrücken (grep) treffen zu?",
"options": [
{ "id": "a", "text": "`.` passt auf genau ein beliebiges Zeichen.", "correct": true, "explanation": "Für einen wörtlichen Punkt: `\\.`." },
{ "id": "b", "text": "`*` bedeutet: das vorherige Element null- oder mehrmals.", "correct": true, "explanation": "`a*` passt auch auf die leere Zeichenkette; anders als beim Shell-Globbing." },
{ "id": "c", "text": "In Basic RE (grep ohne `-E`) bedeutet `+` „ein- oder mehrmals“.", "correct": false, "explanation": "In BRE ist `+` ein normales Zeichen; GNU grep versteht dort `\\+`. Mit `-E` ist `+` ein Quantor." },
{ "id": "d", "text": "`$` verankert am Zeilenanfang.", "correct": false, "explanation": "`$` ist das Zeilenende, `^` der Zeilenanfang." },
{ "id": "e", "text": "`[^a-z]` passt auf einen Kleinbuchstaben.", "correct": false, "explanation": "`^` am Anfang einer Klammer negiert: ein Zeichen, das **kein** Kleinbuchstabe ist." }
],
"explanation": "ERE-Zusätze: `+`, `?`, `{n,m}`, `|`, `( )`. Zeichenklassen: `[[:digit:]]`, `[[:space:]]`, `[[:alpha:]]`.",
"references": ["man 7 regex"]
},
{
"id": "103.8-001",
"objective": "103.8",
"type": "single",
"difficulty": 1,
"question": "Mit welcher Eingabe im Befehlsmodus von vi speichert man die Datei und beendet den Editor?",
"options": [
{ "id": "a", "text": "`:wq`", "correct": true, "explanation": "`:w` schreibt, `:q` beendet. Gleichwertig: `:x` und `ZZ`." },
{ "id": "b", "text": "`:q!`", "correct": false, "explanation": "Beendet ohne zu speichern und verwirft Änderungen." },
{ "id": "c", "text": "`:w`", "correct": false, "explanation": "Speichert nur, vi bleibt offen." },
{ "id": "d", "text": "`ZQ`", "correct": false, "explanation": "`ZQ` entspricht `:q!`, also beenden ohne Speichern." },
{ "id": "e", "text": "`:e!`", "correct": false, "explanation": "Lädt die Datei neu und verwirft ungespeicherte Änderungen." }
],
"explanation": "Mit Esc kommt man aus dem Einfügemodus in den Befehlsmodus. Doppelpunkt-Befehle sind Ex-Befehle.",
"references": ["man 1 vim", ":help ZZ"]
},
{
"id": "103.8-002",
"objective": "103.8",
"type": "fill",
"difficulty": 1,
"question": "Welche Tastenfolge löscht in vi im Befehlsmodus die **aktuelle Zeile** (und legt sie in den Puffer)?",
"answers": ["dd"],
"explanation": "`dd` löscht die Zeile, `5dd` fünf Zeilen, `yy` kopiert, `p` fügt ein, `u` macht rückgängig.",
"references": [":help dd"]
},
{
"id": "103.8-003",
"objective": "103.8",
"type": "single",
"difficulty": 1,
"question": "Wie sucht man in vi im Befehlsmodus **vorwärts** nach dem Wort `Port`?",
"options": [
{ "id": "a", "text": "`/Port`", "correct": true, "explanation": "`/` sucht vorwärts; `n` springt zum nächsten, `N` zum vorherigen Treffer." },
{ "id": "b", "text": "`?Port`", "correct": false, "explanation": "`?` sucht rückwärts." },
{ "id": "c", "text": "`:s/Port`", "correct": false, "explanation": "`:s` ist das Ersetzen in der aktuellen Zeile." },
{ "id": "d", "text": "`fPort`", "correct": false, "explanation": "`f` springt zum nächsten Vorkommen eines einzelnen Zeichens in der aktuellen Zeile (hier `P`)." },
{ "id": "e", "text": "`nPort`", "correct": false, "explanation": "`n` wiederholt die letzte Suche; die folgenden Zeichen würden als weitere Befehle gelesen." }
],
"explanation": "Suchen und ersetzen in der ganzen Datei: `:%s/alt/neu/g`.",
"references": [":help /", ":help n"]
},
{
"id": "103.8-004",
"objective": "103.8",
"type": "multi",
"difficulty": 1,
"question": "Welche Tasten wechseln in vi aus dem Befehlsmodus in den **Einfügemodus**?",
"options": [
{ "id": "a", "text": "`i`", "correct": true, "explanation": "Einfügen vor dem Cursor." },
{ "id": "b", "text": "`o`", "correct": true, "explanation": "Öffnet eine neue Zeile unterhalb und wechselt in den Einfügemodus." },
{ "id": "c", "text": "`x`", "correct": false, "explanation": "Löscht das Zeichen unter dem Cursor; man bleibt im Befehlsmodus." },
{ "id": "d", "text": "`p`", "correct": false, "explanation": "Fügt den Pufferinhalt ein (paste); man bleibt im Befehlsmodus." },
{ "id": "e", "text": "`u`", "correct": false, "explanation": "Macht die letzte Änderung rückgängig." }
],
"explanation": "Einfügemodus auch mit `a`/`A` (nach Cursor/Zeilenende), `I` (Zeilenanfang), `O` (neue Zeile oberhalb). Der Standard-Editor wird über `EDITOR`/`VISUAL` festgelegt.",
"references": [":help insert"]
}
]
}