222 lines
15 KiB
JSON
222 lines
15 KiB
JSON
{
|
||
"$schema": "../schema/questions.schema.json",
|
||
"format": "lpic-sim-questions",
|
||
"meta": {
|
||
"file": "questions_105_set2.json",
|
||
"brief": "Zweiter Fragensatz zu Topic 105 Shells und Shell-Skripte (LPIC-1 102-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 (30.10.2026)"
|
||
},
|
||
"exam": "lpic1-102",
|
||
"questions": [
|
||
{
|
||
"id": "105.1-007",
|
||
"objective": "105.1",
|
||
"type": "single",
|
||
"difficulty": 1,
|
||
"question": "Welcher Befehl gibt **nur die Umgebungsvariablen** aus (ohne reine Shell-Variablen und Funktionen)?",
|
||
"options": [
|
||
{ "id": "a", "text": "`env`", "correct": true, "explanation": "`env` ohne Argumente (wie `printenv`) zeigt die exportierte Umgebung." },
|
||
{ "id": "b", "text": "`set`", "correct": false, "explanation": "`set` zeigt zusätzlich alle Shell-Variablen und Funktionen." },
|
||
{ "id": "c", "text": "`declare -f`", "correct": false, "explanation": "`declare -f` zeigt die definierten Funktionen." },
|
||
{ "id": "d", "text": "`alias`", "correct": false, "explanation": "`alias` zeigt die definierten Aliase." },
|
||
{ "id": "e", "text": "`export -f`", "correct": false, "explanation": "`export -f name` exportiert eine Funktion; ohne Namen listet es exportierte Funktionen." }
|
||
],
|
||
"explanation": "Umgebung = exportierte Variablen, die Kindprozesse erben. `export -p` listet sie in wiederverwendbarer Form.",
|
||
"references": ["man 1 env", "man 1 printenv"]
|
||
},
|
||
{
|
||
"id": "105.1-008",
|
||
"objective": "105.1",
|
||
"type": "fill",
|
||
"difficulty": 1,
|
||
"question": "Welche Datei im Home-Verzeichnis führt die Bash beim **Beenden einer Login-Shell** aus? (Dateiname)",
|
||
"answers": ["~/.bash_logout", ".bash_logout"],
|
||
"explanation": "Typischer Inhalt: Bildschirm leeren (`clear`) oder temporäre Dateien aufräumen.",
|
||
"references": ["man 1 bash (Abschnitt INVOCATION)"]
|
||
},
|
||
{
|
||
"id": "105.1-009",
|
||
"objective": "105.1",
|
||
"type": "single",
|
||
"difficulty": 1,
|
||
"question": "Wie entfernt man den Alias `ll` aus der aktuellen Shell?",
|
||
"options": [
|
||
{ "id": "a", "text": "`unalias ll`", "correct": true, "explanation": "`unalias` entfernt Aliase; `unalias -a` alle." },
|
||
{ "id": "b", "text": "`unset ll`", "correct": false, "explanation": "`unset` entfernt Variablen und Funktionen, keine Aliase." },
|
||
{ "id": "c", "text": "`alias ll=''`", "correct": false, "explanation": "Setzt einen leeren Alias – `ll` bleibt definiert." },
|
||
{ "id": "d", "text": "`alias -d ll`", "correct": false, "explanation": "`alias` kennt keine Option `-d`." },
|
||
{ "id": "e", "text": "`export -n ll`", "correct": false, "explanation": "`export -n` nimmt Variablen das Export-Attribut, hat mit Aliasen nichts zu tun." }
|
||
],
|
||
"explanation": "Ein Alias in `~/.bashrc` kommt in jeder neuen Shell wieder – dort muss er dauerhaft entfernt werden.",
|
||
"references": ["help unalias"]
|
||
},
|
||
{
|
||
"id": "105.1-010",
|
||
"objective": "105.1",
|
||
"type": "multi",
|
||
"difficulty": 2,
|
||
"question": "Welche Dateien liest eine interaktive **Nicht-Login**-Bash auf einem Debian-System?",
|
||
"options": [
|
||
{ "id": "a", "text": "`/etc/bash.bashrc`", "correct": true, "explanation": "Systemweite Datei für interaktive Shells (bei Debian einkompiliert)." },
|
||
{ "id": "b", "text": "`~/.bashrc`", "correct": true, "explanation": "Persönliche Datei für interaktive Nicht-Login-Shells." },
|
||
{ "id": "c", "text": "`/etc/profile`", "correct": false, "explanation": "Wird nur von Login-Shells gelesen." },
|
||
{ "id": "d", "text": "`~/.bash_profile`", "correct": false, "explanation": "Wird nur von Login-Shells gelesen." },
|
||
{ "id": "e", "text": "`~/.bash_logout`", "correct": false, "explanation": "Wird nur beim Beenden einer Login-Shell gelesen." }
|
||
],
|
||
"explanation": "Beispiel Nicht-Login-Shell: ein neues Terminalfenster in einer grafischen Sitzung oder `bash` aus einer Shell heraus.",
|
||
"references": ["man 1 bash (Abschnitt INVOCATION)"]
|
||
},
|
||
{
|
||
"id": "105.1-011",
|
||
"objective": "105.1",
|
||
"type": "single",
|
||
"difficulty": 2,
|
||
"question": "Die Shell-Funktion `gruss` soll auch in Bash-Prozessen verfügbar sein, die aus der aktuellen Shell gestartet werden. Welcher Befehl leistet das?",
|
||
"options": [
|
||
{ "id": "a", "text": "`export -f gruss`", "correct": true, "explanation": "`-f` exportiert die Funktion in die Umgebung; Kind-Bashs übernehmen sie." },
|
||
{ "id": "b", "text": "`declare -x gruss`", "correct": false, "explanation": "Exportiert eine **Variable** namens `gruss`, nicht die Funktion." },
|
||
{ "id": "c", "text": "`readonly -f gruss`", "correct": false, "explanation": "Macht die Funktion nur schreibgeschützt." },
|
||
{ "id": "d", "text": "`local gruss`", "correct": false, "explanation": "`local` legt lokale Variablen innerhalb einer Funktion an." },
|
||
{ "id": "e", "text": "`alias gruss=gruss`", "correct": false, "explanation": "Aliase werden nie an Kindprozesse vererbt." }
|
||
],
|
||
"explanation": "Für Skripte ist meist besser, gemeinsame Funktionen in eine Datei zu legen und mit `source` einzubinden.",
|
||
"references": ["help export"]
|
||
},
|
||
{
|
||
"id": "105.1-012",
|
||
"objective": "105.1",
|
||
"type": "single",
|
||
"difficulty": 2,
|
||
"question": "`sort` soll **einmalig** mit `LC_ALL=C` laufen, ohne die Variable in der aktuellen Shell zu verändern. Welche Zeile leistet das?",
|
||
"options": [
|
||
{ "id": "a", "text": "`LC_ALL=C sort liste.txt`", "correct": true, "explanation": "Eine Zuweisung direkt vor dem Befehl gilt nur für diesen einen Prozess." },
|
||
{ "id": "b", "text": "`export LC_ALL=C; sort liste.txt`", "correct": false, "explanation": "Die Variable bleibt danach in der Shell gesetzt." },
|
||
{ "id": "c", "text": "`LC_ALL=C; sort liste.txt`", "correct": false, "explanation": "Durch das Semikolon wird die Zuweisung ein eigener Befehl und bleibt in der Shell bestehen." },
|
||
{ "id": "d", "text": "`sort liste.txt LC_ALL=C`", "correct": false, "explanation": "Hinter dem Befehl ist `LC_ALL=C` nur ein Argument (Dateiname) für `sort`." },
|
||
{ "id": "e", "text": "`set LC_ALL=C sort liste.txt`", "correct": false, "explanation": "`set` setzt hier Positionsparameter, keine Variable." }
|
||
],
|
||
"explanation": "Gleichwertig: `env LC_ALL=C sort liste.txt`. `LC_ALL=C` sorgt für byteweise, reproduzierbare Sortierung.",
|
||
"references": ["man 1 bash (Abschnitt SIMPLE COMMAND EXPANSION)"]
|
||
},
|
||
{
|
||
"id": "105.1-013",
|
||
"objective": "105.1",
|
||
"type": "fill",
|
||
"difficulty": 1,
|
||
"question": "Welcher Befehl (ohne Argumente) listet alle in der aktuellen Shell definierten Aliase auf?",
|
||
"answers": ["alias", "alias -p"],
|
||
"explanation": "Ausgabe in der Form `alias ll='ls -l'`, direkt wiederverwendbar.",
|
||
"references": ["help alias"]
|
||
},
|
||
{
|
||
"id": "105.2-007",
|
||
"objective": "105.2",
|
||
"type": "single",
|
||
"difficulty": 1,
|
||
"question": "Welche `if`-Anweisung ist in der Bash syntaktisch korrekt?",
|
||
"options": [
|
||
{ "id": "a", "text": "`if [ \"$a\" -eq 5 ]; then echo ja; fi`", "correct": true, "explanation": "Leerzeichen innerhalb der Klammern, `;` bzw. Zeilenumbruch vor `then`, Abschluss mit `fi`." },
|
||
{ "id": "b", "text": "`if [\"$a\" -eq 5]; then echo ja; fi`", "correct": false, "explanation": "Ohne Leerzeichen sucht die Shell einen Befehl namens `[5` bzw. `[\"…\"`." },
|
||
{ "id": "c", "text": "`if [ \"$a\" -eq 5 ] then echo ja; fi`", "correct": false, "explanation": "Vor `then` fehlt `;` oder ein Zeilenumbruch." },
|
||
{ "id": "d", "text": "`if [ \"$a\" -eq 5 ]; then echo ja; endif`", "correct": false, "explanation": "`endif` ist csh-Syntax; die Bash schließt mit `fi`." },
|
||
{ "id": "e", "text": "`if ( $a -eq 5 ) { echo ja }`", "correct": false, "explanation": "C-ähnliche Syntax; `( )` startet eine Subshell, `{ }` braucht `;`." }
|
||
],
|
||
"explanation": "Variablen in `[ ]` immer in Anführungszeichen setzen, sonst entstehen bei leeren Werten Syntaxfehler. Bash-Alternative: `[[ … ]]`.",
|
||
"references": ["man 1 test", "help if"]
|
||
},
|
||
{
|
||
"id": "105.2-008",
|
||
"objective": "105.2",
|
||
"type": "single",
|
||
"difficulty": 1,
|
||
"question": "Mit welchem Operator prüft `test` bzw. `[ ]`, ob eine **Zahl größer** als eine andere ist?",
|
||
"options": [
|
||
{ "id": "a", "text": "`-gt`", "correct": true, "explanation": "greater than: `[ \"$n\" -gt 10 ]`." },
|
||
{ "id": "b", "text": "`>`", "correct": false, "explanation": "In `[ ]` ist `>` eine Umleitung – es entsteht eine Datei namens `10`." },
|
||
{ "id": "c", "text": "`-ge`", "correct": false, "explanation": "`-ge` bedeutet größer **oder gleich**." },
|
||
{ "id": "d", "text": "`-lt`", "correct": false, "explanation": "`-lt` bedeutet kleiner als." },
|
||
{ "id": "e", "text": "`-ne`", "correct": false, "explanation": "`-ne` bedeutet ungleich." }
|
||
],
|
||
"explanation": "Zahlen: `-eq -ne -lt -le -gt -ge`. Zeichenketten: `=`, `!=`. In `(( ))` darf man `>` als Zahlvergleich schreiben.",
|
||
"references": ["man 1 test"]
|
||
},
|
||
{
|
||
"id": "105.2-009",
|
||
"objective": "105.2",
|
||
"type": "fill",
|
||
"difficulty": 1,
|
||
"question": "Mit welcher Anweisung (Befehl mit Argument) beendet sich ein Skript mit dem Exit-Status 3?",
|
||
"answers": ["exit 3"],
|
||
"explanation": "Ohne Argument liefert `exit` den Status des zuletzt ausgeführten Befehls. Gültig sind 0–255.",
|
||
"references": ["help exit"]
|
||
},
|
||
{
|
||
"id": "105.2-010",
|
||
"objective": "105.2",
|
||
"type": "single",
|
||
"difficulty": 2,
|
||
"question": "Welche `case`-Anweisung ist korrekt aufgebaut?",
|
||
"options": [
|
||
{ "id": "a", "text": "`case \"$1\" in start) echo an ;; *) echo unbekannt ;; esac`", "correct": true, "explanation": "Muster mit `)`, jeder Zweig endet mit `;;`, Abschluss mit `esac`." },
|
||
{ "id": "b", "text": "`case \"$1\" in start) echo an ;; done`", "correct": false, "explanation": "`done` beendet Schleifen; `case` endet mit `esac`." },
|
||
{ "id": "c", "text": "`switch \"$1\" case start: echo an endsw`", "correct": false, "explanation": "Das ist csh-Syntax." },
|
||
{ "id": "d", "text": "`case \"$1\" { start: echo an }`", "correct": false, "explanation": "C-ähnliche Syntax, in der Bash ungültig." },
|
||
{ "id": "e", "text": "`case \"$1\" in \"start\" then echo an fi`", "correct": false, "explanation": "Vermischt `if`-Syntax mit `case`." }
|
||
],
|
||
"explanation": "Muster dürfen Globbing nutzen und mit `|` kombiniert werden: `start|begin)`. `*)` fängt alles Übrige ab.",
|
||
"references": ["man 1 bash (Abschnitt Compound Commands)"]
|
||
},
|
||
{
|
||
"id": "105.2-011",
|
||
"objective": "105.2",
|
||
"type": "single",
|
||
"difficulty": 2,
|
||
"question": "Wie liest ein Skript die Datei `hosts.txt` **zeilenweise** in einer Schleife?",
|
||
"options": [
|
||
{ "id": "a", "text": "`while read zeile; do echo \"$zeile\"; done < hosts.txt`", "correct": true, "explanation": "Die Umleitung gilt für die ganze Schleife; `read` liest bei jedem Durchlauf die nächste Zeile." },
|
||
{ "id": "b", "text": "`for zeile in hosts.txt; do echo \"$zeile\"; done`", "correct": false, "explanation": "Durchläuft nur das eine Wort `hosts.txt`, nicht den Dateiinhalt." },
|
||
{ "id": "c", "text": "`while read zeile < hosts.txt; do echo \"$zeile\"; done`", "correct": false, "explanation": "Die Datei wird bei jedem Durchlauf neu geöffnet – es wird endlos die erste Zeile gelesen." },
|
||
{ "id": "d", "text": "`until read zeile; do echo \"$zeile\"; done < hosts.txt`", "correct": false, "explanation": "`until` läuft, solange `read` **fehlschlägt** – also erst am Dateiende." },
|
||
{ "id": "e", "text": "`read -a zeile hosts.txt`", "correct": false, "explanation": "`read -a` liest eine Zeile in ein Array; `hosts.txt` wäre ein weiterer Variablenname." }
|
||
],
|
||
"explanation": "Robuste Form: `while IFS= read -r zeile; do …; done < datei` (keine Backslash-Auswertung, Leerraum bleibt erhalten).",
|
||
"references": ["help read", "help while"]
|
||
},
|
||
{
|
||
"id": "105.2-012",
|
||
"objective": "105.2",
|
||
"type": "multi",
|
||
"difficulty": 2,
|
||
"question": "Welche Aussagen zu Shell-Skripten treffen zu?",
|
||
"options": [
|
||
{ "id": "a", "text": "`echo $(( 3 + 4 ))` gibt `7` aus.", "correct": true, "explanation": "`$(( ))` ist arithmetische Expansion (Ganzzahlen)." },
|
||
{ "id": "b", "text": "Bei `befehl1 && befehl2` läuft `befehl2` nur, wenn `befehl1` erfolgreich war.", "correct": true, "explanation": "`&&` prüft den Exit-Status 0." },
|
||
{ "id": "c", "text": "Bei `befehl1 || befehl2` läuft `befehl2` nur, wenn `befehl1` erfolgreich war.", "correct": false, "explanation": "`||` führt `befehl2` nur bei einem **Fehler** von `befehl1` aus." },
|
||
{ "id": "d", "text": "`test -z \"$x\"` ist wahr, wenn `$x` nicht leer ist.", "correct": false, "explanation": "`-z` ist wahr bei **leerem** String; `-n` bei nicht leerem." },
|
||
{ "id": "e", "text": "In doppelten Anführungszeichen verhalten sich `\"$*\"` und `\"$@\"` gleich.", "correct": false, "explanation": "`\"$*\"` ergibt ein einziges Wort, `\"$@\"` jedes Argument als eigenes Wort." }
|
||
],
|
||
"explanation": "Typisches Muster: `cd /verzeichnis || exit 1` bricht ab, wenn der Wechsel scheitert.",
|
||
"references": ["man 1 bash (Abschnitte Lists, Arithmetic Expansion)"]
|
||
},
|
||
{
|
||
"id": "105.2-013",
|
||
"objective": "105.2",
|
||
"type": "single",
|
||
"difficulty": 1,
|
||
"question": "Welcher Befehl gibt die Zahlen 1 bis 5 jeweils in einer **eigenen Zeile** aus?",
|
||
"options": [
|
||
{ "id": "a", "text": "`seq 1 5`", "correct": true, "explanation": "`seq` gibt eine Zahlenfolge aus, standardmäßig eine Zahl pro Zeile." },
|
||
{ "id": "b", "text": "`echo {1..5}`", "correct": false, "explanation": "Die Klammererweiterung erzeugt `1 2 3 4 5` in **einer** Zeile." },
|
||
{ "id": "c", "text": "`seq 5 1`", "correct": false, "explanation": "Ohne negative Schrittweite (`seq 5 -1 1`) gibt das nichts aus." },
|
||
{ "id": "d", "text": "`range 1 5`", "correct": false, "explanation": "Einen Befehl `range` gibt es nicht." },
|
||
{ "id": "e", "text": "`echo $(1..5)`", "correct": false, "explanation": "Befehlsersetzung: Die Shell sucht einen Befehl `1..5`." }
|
||
],
|
||
"explanation": "In Schleifen: `for i in $(seq 1 5)` oder `for i in {1..5}`. `seq -w` füllt mit führenden Nullen auf.",
|
||
"references": ["man 1 seq"]
|
||
}
|
||
]
|
||
}
|