Files
2026-10-30 10:11:43 +01:00

583 lines
41 KiB
JSON
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
{
"$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 <br@runden.de>",
"owner": "Björn Runden <br@runden.de>",
"assist": "KI-unterstützt (Claude Opus 5.5), geprüft von Björn Runden <br@runden.de>",
"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 <PID>`, 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 <PID>`." },
{ "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"]
}
]
}