neue Fragn
This commit is contained in:
1 parent
07dbc01c92
commit
6a8035cced
16 files changed
+3422
-16
No files matched your search
@@ -23,7 +23,7 @@ lpic/
|
|||||||
```
|
```
|
||||||
|
|
||||||
## Prüfungssimulator
|
## Prüfungssimulator
|
||||||
`simulator/index.html` im Browser öffnen (kein Server nötig): LPIC-1 101/102 mit je 90 Fragen, Lern- und Prüfungsmodus,
|
`simulator/index.html` im Browser öffnen (kein Server nötig): LPIC-1 101/102 mit je 200 Fragen, Lern- und Prüfungsmodus,
|
||||||
Speichern/Export/Import der Sitzung. Details und Fragenformat: [simulator/README.md](simulator/README.md).
|
Speichern/Export/Import der Sitzung. Details und Fragenformat: [simulator/README.md](simulator/README.md).
|
||||||
Code für Übungen und Lab (`bash/`, `ansible/`, `stacks/`) wird bei Bedarf angelegt.
|
Code für Übungen und Lab (`bash/`, `ansible/`, `stacks/`) wird bei Bedarf angelegt.
|
||||||
|
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ Messbar am Ende:
|
|||||||
- [ ] Objectives als Gliederung in `ai/context/knowledge/topics/` anlegen
|
- [ ] Objectives als Gliederung in `ai/context/knowledge/topics/` anlegen
|
||||||
- [ ] Lab-Umgebung festlegen (lokale Container/VMs)
|
- [ ] Lab-Umgebung festlegen (lokale Container/VMs)
|
||||||
- [x] Prüfungssimulator LPIC-1 mit 180 Fragen (29.10.2026)
|
- [x] Prüfungssimulator LPIC-1 mit 180 Fragen (29.10.2026)
|
||||||
|
- [x] Zweiter Fragensatz: je 200 Fragen für 101 und 102 (30.10.2026)
|
||||||
- [ ] Fragen fachlich durchsehen (br) und laufend ergänzen
|
- [ ] Fragen fachlich durchsehen (br) und laufend ergänzen
|
||||||
- [ ] LPIC-2 (201/202) als weitere Prüfungen im Simulator
|
- [ ] LPIC-2 (201/202) als weitere Prüfungen im Simulator
|
||||||
|
|
||||||
@@ -61,3 +62,4 @@ Betreiber testet den Simulator und sieht die Fragen fachlich durch (Rückmeldung
|
|||||||
- 29.10.2026 – Prüfungssimulator gebaut (`simulator/`), Objectives 5.0 und LPI-Regeln recherchiert (Knowledge `research/lpi_exam_format`). Tests lokal: `build_bank.py -c` ok (180 Fragen); `tests/selftest.html` 40/40, `tests/ui_smoke.html` 27/27 in Chromium headless unter `file://` und über lokalen `http.server`; Start und Darstellung zusätzlich in Firefox headless geprüft. Nicht getestet: Mobilgeräte (nur 400-px-Fenster), Safari.
|
- 29.10.2026 – Prüfungssimulator gebaut (`simulator/`), Objectives 5.0 und LPI-Regeln recherchiert (Knowledge `research/lpi_exam_format`). Tests lokal: `build_bank.py -c` ok (180 Fragen); `tests/selftest.html` 40/40, `tests/ui_smoke.html` 27/27 in Chromium headless unter `file://` und über lokalen `http.server`; Start und Darstellung zusätzlich in Firefox headless geprüft. Nicht getestet: Mobilgeräte (nur 400-px-Fenster), Safari.
|
||||||
- 29.10.2026 – Bank verschlüsselt (ChaCha20, gegen Python-`cryptography` und RFC-8439-Vektor geprüft), Prüfvermerk `review`, Export `build_bank.py -e` → `simulator/dist/`; Lückentext-Feld war links verschoben (input inline-block, `margin:auto` griff nicht) → `display:block`. Tests: selftest 44/44, ui_smoke 27/27; Export über `python3 -m http.server 8080` (alle Schnittstellen) ausgeliefert und geprüft.
|
- 29.10.2026 – Bank verschlüsselt (ChaCha20, gegen Python-`cryptography` und RFC-8439-Vektor geprüft), Prüfvermerk `review`, Export `build_bank.py -e` → `simulator/dist/`; Lückentext-Feld war links verschoben (input inline-block, `margin:auto` griff nicht) → `display:block`. Tests: selftest 44/44, ui_smoke 27/27; Export über `python3 -m http.server 8080` (alle Schnittstellen) ausgeliefert und geprüft.
|
||||||
- 29.10.2026 – Prüferpaket: Doku nach `simulator/docs/` (exam_format, question_rules, decisions, REVIEW) und `simulator/AGENTS.md`; `build_bank.py -b` → `simulator/release/lpic-sim_<datum>.tar.gz` (ohne PSK, `dist/`, `release/`, Caches; ohne `ai/` und Umgebungsdaten). Entpackt in leerem Verzeichnis geprüft: Build, selftest 44/44, ui_smoke 27/27, alle Doku-Links innerhalb des Pakets. Lizenz klärt jeder Prüfer selbst (Betreiber).
|
- 29.10.2026 – Prüferpaket: Doku nach `simulator/docs/` (exam_format, question_rules, decisions, REVIEW) und `simulator/AGENTS.md`; `build_bank.py -b` → `simulator/release/lpic-sim_<datum>.tar.gz` (ohne PSK, `dist/`, `release/`, Caches; ohne `ai/` und Umgebungsdaten). Entpackt in leerem Verzeichnis geprüft: Build, selftest 44/44, ui_smoke 27/27, alle Doku-Links innerhalb des Pakets. Lizenz klärt jeder Prüfer selbst (Betreiber).
|
||||||
|
- 30.10.2026 – Je 110 weitere Fragen für 101 und 102 (`questions_*_set2.json`, nach Gewicht verteilt) → je 200, gesamt 400; Qualitätsprüfung (Backticks, Buchstabenbezüge, doppelte Fragetexte) ohne Befund. Export-Fehler behoben: `build_bank.py -e` löschte das ganze `dist/` samt fremder Datei `lpic.tar.gz` (aus `~/Downloads` wiederhergestellt) – ersetzt jetzt nur noch `index.html`, `css`, `js`, `vendor`, Verzeichnis bleibt (laufender Server liefert weiter). Tests: selftest 44/44, ui_smoke 27/27; Server :8080 liefert 2×200 Fragen; Prüferpaket `release/lpic-sim_2026-10-30.tar.gz` neu.
|
||||||
+1
-1
@@ -17,7 +17,7 @@
|
|||||||
| Weg | Aufruf |
|
| Weg | Aufruf |
|
||||||
|---|---|
|
|---|---|
|
||||||
| Lokal | `index.html` im Browser öffnen (Doppelklick genügt, kein Server nötig) |
|
| Lokal | `index.html` im Browser öffnen (Doppelklick genügt, kein Server nötig) |
|
||||||
| Export + Webserver | `python3 tools/build_bank.py -e` schreibt nur die Laufzeitdateien nach `dist/` (ohne `data/`, `tools/`, `tests/`), dann `python3 -m http.server 8080 -d dist` |
|
| Export + Webserver | `python3 tools/build_bank.py -e` schreibt nur die Laufzeitdateien nach `dist/` (ohne `data/`, `tools/`, `tests/`); andere Dateien in `dist/` bleiben erhalten, ein laufender Server liefert sofort den neuen Stand. Start: `python3 -m http.server 8080 -d dist` |
|
||||||
|
|
||||||
**Startseite:** Prüfung wählen (LPIC-1 101 oder 102), Modus wählen, im Lernmodus optional Topics, Anzahl und Reihenfolge.
|
**Startseite:** Prüfung wählen (LPIC-1 101 oder 102), Modus wählen, im Lernmodus optional Topics, Anzahl und Reihenfolge.
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,221 @@
|
|||||||
|
{
|
||||||
|
"$schema": "../schema/questions.schema.json",
|
||||||
|
"format": "lpic-sim-questions",
|
||||||
|
"meta": {
|
||||||
|
"file": "questions_101_set2.json",
|
||||||
|
"brief": "Zweiter Fragensatz zu Topic 101 Systemarchitektur (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 (30.10.2026)"
|
||||||
|
},
|
||||||
|
"exam": "lpic1-101",
|
||||||
|
"questions": [
|
||||||
|
{
|
||||||
|
"id": "101.1-004",
|
||||||
|
"objective": "101.1",
|
||||||
|
"type": "single",
|
||||||
|
"difficulty": 1,
|
||||||
|
"question": "Welcher Befehl listet die am PCI-Bus erkannten Geräte auf, z. B. Netzwerk- und Grafikkarten?",
|
||||||
|
"options": [
|
||||||
|
{ "id": "a", "text": "`lspci`", "correct": true, "explanation": "Liest die PCI-Informationen aus `/sys` bzw. `/proc/bus/pci`; `-k` zeigt zusätzlich den Treiber." },
|
||||||
|
{ "id": "b", "text": "`lsusb`", "correct": false, "explanation": "Listet USB-Geräte." },
|
||||||
|
{ "id": "c", "text": "`lsblk`", "correct": false, "explanation": "Listet Blockgeräte (Platten, Partitionen)." },
|
||||||
|
{ "id": "d", "text": "`lsmod`", "correct": false, "explanation": "Listet geladene Kernelmodule." },
|
||||||
|
{ "id": "e", "text": "`lscpu`", "correct": false, "explanation": "Zeigt Informationen zur CPU-Architektur." }
|
||||||
|
],
|
||||||
|
"explanation": "`lspci -v` ausführlich, `lspci -nn` mit Hersteller- und Geräte-IDs; `lsusb -t` zeigt den USB-Baum.",
|
||||||
|
"references": ["man 8 lspci"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "101.1-005",
|
||||||
|
"objective": "101.1",
|
||||||
|
"type": "fill",
|
||||||
|
"difficulty": 1,
|
||||||
|
"question": "Welcher Befehl (nur der Name) entlädt ein Kernelmodul, **ohne** Abhängigkeiten zu berücksichtigen – das Gegenstück zu `insmod`?",
|
||||||
|
"answers": ["rmmod"],
|
||||||
|
"explanation": "`rmmod` entfernt genau ein Modul; mit Abhängigkeiten entlädt man über `modprobe -r`.",
|
||||||
|
"references": ["man 8 rmmod"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "101.1-006",
|
||||||
|
"objective": "101.1",
|
||||||
|
"type": "single",
|
||||||
|
"difficulty": 2,
|
||||||
|
"question": "Das Kernelmodul `nouveau` soll beim Start **nicht** automatisch geladen werden. Wie erreicht man das üblicherweise?",
|
||||||
|
"options": [
|
||||||
|
{ "id": "a", "text": "Eine Datei unter `/etc/modprobe.d/` mit der Zeile `blacklist nouveau` anlegen", "correct": true, "explanation": "modprobe wertet die Konfiguration in `/etc/modprobe.d/*.conf` aus; ggf. initramfs neu erzeugen." },
|
||||||
|
{ "id": "b", "text": "`nouveau` in `/etc/modules` eintragen", "correct": false, "explanation": "`/etc/modules` (Debian) listet Module, die beim Start **geladen** werden sollen." },
|
||||||
|
{ "id": "c", "text": "Die Zeile `nouveau` aus `/proc/modules` löschen", "correct": false, "explanation": "`/proc/modules` ist nur eine Laufzeitanzeige und nicht beschreibbar." },
|
||||||
|
{ "id": "d", "text": "`blacklist nouveau` in `/etc/sysctl.conf` eintragen", "correct": false, "explanation": "`sysctl.conf` setzt Kernelparameter unter `/proc/sys`, keine Modulregeln." },
|
||||||
|
{ "id": "e", "text": "`rmmod nouveau` einmal ausführen", "correct": false, "explanation": "Entlädt das Modul nur bis zum nächsten Start." }
|
||||||
|
],
|
||||||
|
"explanation": "Modulparameter setzt man ebenfalls dort: `options <modul> <param>=<wert>`.",
|
||||||
|
"references": ["man 5 modprobe.d"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "101.1-007",
|
||||||
|
"objective": "101.1",
|
||||||
|
"type": "multi",
|
||||||
|
"difficulty": 2,
|
||||||
|
"question": "Welche Aussagen zu udev treffen zu?",
|
||||||
|
"options": [
|
||||||
|
{ "id": "a", "text": "udev legt Gerätedateien unter `/dev` dynamisch an, wenn der Kernel neue Hardware meldet.", "correct": true, "explanation": "udev reagiert auf Kernel-Ereignisse (uevents) und verwaltet `/dev`." },
|
||||||
|
{ "id": "b", "text": "Eigene udev-Regeln legt man unter `/etc/udev/rules.d/` ab.", "correct": true, "explanation": "Regeln dort haben Vorrang vor denen der Pakete unter `/usr/lib/udev/rules.d/` bzw. `/lib/udev/rules.d/`." },
|
||||||
|
{ "id": "c", "text": "udev speichert seine Regeln in `/proc/udev`.", "correct": false, "explanation": "Einen solchen Pfad gibt es nicht." },
|
||||||
|
{ "id": "d", "text": "`udevadm monitor` löscht alle udev-Regeln.", "correct": false, "explanation": "`udevadm monitor` zeigt eintreffende Ereignisse live an." },
|
||||||
|
{ "id": "e", "text": "D-Bus ist das Dateisystem, in dem udev die Gerätedateien anlegt.", "correct": false, "explanation": "D-Bus ist ein Nachrichtensystem zwischen Prozessen; Gerätedateien liegen im devtmpfs unter `/dev`." }
|
||||||
|
],
|
||||||
|
"explanation": "Beispiel einer Regel: feste Namen für Geräte über Attribute wie Seriennummer. `udevadm info` zeigt die Attribute eines Geräts.",
|
||||||
|
"references": ["man 7 udev", "man 8 udevadm"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "101.2-005",
|
||||||
|
"objective": "101.2",
|
||||||
|
"type": "single",
|
||||||
|
"difficulty": 1,
|
||||||
|
"question": "Im GRUB-2-Menü soll für **einen** Start ein zusätzlicher Kernel-Parameter gesetzt werden. Was tut man?",
|
||||||
|
"options": [
|
||||||
|
{ "id": "a", "text": "Den Eintrag markieren, `e` drücken, die `linux`-Zeile ergänzen und mit Strg+X bzw. F10 starten", "correct": true, "explanation": "Die Änderung gilt nur für diesen Start; nichts wird gespeichert." },
|
||||||
|
{ "id": "b", "text": "`/boot/grub/grub.cfg` bearbeiten und neu starten", "correct": false, "explanation": "Wirkt dauerhaft (bis zur nächsten Neuerzeugung) – und die Datei soll man nicht von Hand ändern." },
|
||||||
|
{ "id": "c", "text": "`c` drücken und `reboot` eingeben", "correct": false, "explanation": "`c` öffnet die GRUB-Kommandozeile; `reboot` startet nur neu." },
|
||||||
|
{ "id": "d", "text": "Im BIOS-Setup den Parameter eintragen", "correct": false, "explanation": "Die Firmware kennt keine Kernel-Parameter." },
|
||||||
|
{ "id": "e", "text": "Nach dem Start `echo param > /proc/cmdline` ausführen", "correct": false, "explanation": "`/proc/cmdline` ist nur lesbar, und der Kernel läuft dann bereits." }
|
||||||
|
],
|
||||||
|
"explanation": "Typische Einmal-Parameter für die Fehlersuche: `systemd.unit=rescue.target`, `nomodeset`, `init=/bin/bash`.",
|
||||||
|
"references": ["info grub"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "101.2-006",
|
||||||
|
"objective": "101.2",
|
||||||
|
"type": "fill",
|
||||||
|
"difficulty": 2,
|
||||||
|
"question": "Welcher Kernel-Parameter in der Form `systemd.unit=…` lässt systemd direkt in das Rettungs-Target starten? (vollständiger Parameter)",
|
||||||
|
"answers": ["systemd.unit=rescue.target"],
|
||||||
|
"explanation": "Für eine minimale Notfall-Shell: `systemd.unit=emergency.target`. Klassisch wirken auch `single` bzw. `1`.",
|
||||||
|
"references": ["man 7 kernel-command-line", "man 7 systemd.special"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "101.2-007",
|
||||||
|
"objective": "101.2",
|
||||||
|
"type": "single",
|
||||||
|
"difficulty": 2,
|
||||||
|
"question": "Mit welchem Werkzeug zeigt und ändert man unter Linux die **Boot-Einträge der UEFI-Firmware** (z. B. Bootreihenfolge)?",
|
||||||
|
"options": [
|
||||||
|
{ "id": "a", "text": "`efibootmgr`", "correct": true, "explanation": "Liest und schreibt die EFI-Variablen; `-v` zeigt Details, `-o` setzt die Reihenfolge." },
|
||||||
|
{ "id": "b", "text": "`mokutil`", "correct": false, "explanation": "Verwaltet Machine Owner Keys für Secure Boot." },
|
||||||
|
{ "id": "c", "text": "`update-initramfs`", "correct": false, "explanation": "Erzeugt die initramfs neu." },
|
||||||
|
{ "id": "d", "text": "`fdisk -l`", "correct": false, "explanation": "Zeigt Partitionstabellen." },
|
||||||
|
{ "id": "e", "text": "`lsblk`", "correct": false, "explanation": "Listet Blockgeräte." }
|
||||||
|
],
|
||||||
|
"explanation": "Bei UEFI startet die Firmware eine `.efi`-Datei von der EFI-Systempartition; die Einträge stehen im NVRAM.",
|
||||||
|
"references": ["man 8 efibootmgr"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "101.2-008",
|
||||||
|
"objective": "101.2",
|
||||||
|
"type": "single",
|
||||||
|
"difficulty": 1,
|
||||||
|
"question": "Welche Datei legt bei **SysV-init** den Standard-Runlevel und das Startverhalten fest?",
|
||||||
|
"options": [
|
||||||
|
{ "id": "a", "text": "`/etc/inittab`", "correct": true, "explanation": "z. B. `id:3:initdefault:` für Runlevel 3." },
|
||||||
|
{ "id": "b", "text": "`/etc/init.d/`", "correct": false, "explanation": "Verzeichnis mit den Startskripten der Dienste." },
|
||||||
|
{ "id": "c", "text": "`/etc/rc.local`", "correct": false, "explanation": "Lokales Skript, das am Ende des Starts läuft." },
|
||||||
|
{ "id": "d", "text": "`/etc/systemd/system/default.target`", "correct": false, "explanation": "Entspricht dem Standard-Runlevel bei **systemd**." },
|
||||||
|
{ "id": "e", "text": "`/boot/grub/grub.cfg`", "correct": false, "explanation": "Konfiguration des Bootloaders." }
|
||||||
|
],
|
||||||
|
"explanation": "SysV-init: `/etc/inittab` → Skripte in `/etc/rcN.d/` (S = starten, K = beenden), die auf `/etc/init.d/` verlinken.",
|
||||||
|
"references": ["man 5 inittab"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "101.2-009",
|
||||||
|
"objective": "101.2",
|
||||||
|
"type": "multi",
|
||||||
|
"difficulty": 2,
|
||||||
|
"question": "Welche Aussagen zur Analyse des Systemstarts treffen zu?",
|
||||||
|
"options": [
|
||||||
|
{ "id": "a", "text": "`journalctl -b -1` zeigt die Meldungen des vorherigen Starts, sofern das Journal persistent gespeichert wird.", "correct": true, "explanation": "Ohne `/var/log/journal` gibt es nur den aktuellen Start." },
|
||||||
|
{ "id": "b", "text": "`systemd-analyze blame` listet Units nach ihrer Startdauer.", "correct": true, "explanation": "Hilft, langsame Dienste zu finden; `systemd-analyze` allein zeigt die Gesamtzeit." },
|
||||||
|
{ "id": "c", "text": "`dmesg` zeigt die Meldungen aller bisherigen Starts.", "correct": false, "explanation": "Der Ring-Buffer enthält nur den laufenden Start." },
|
||||||
|
{ "id": "d", "text": "Der Bootloader wird vom Kernel geladen.", "correct": false, "explanation": "Umgekehrt: Der Bootloader lädt den Kernel." },
|
||||||
|
{ "id": "e", "text": "Die initramfs wird erst nach systemd geladen.", "correct": false, "explanation": "Die initramfs ist vor dem echten Root-Dateisystem aktiv; systemd läuft oft schon in ihr." }
|
||||||
|
],
|
||||||
|
"explanation": "Für klassische Systeme stehen Startmeldungen auch in `/var/log/messages` bzw. `/var/log/syslog`.",
|
||||||
|
"references": ["man 1 systemd-analyze", "man 1 journalctl"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "101.3-005",
|
||||||
|
"objective": "101.3",
|
||||||
|
"type": "single",
|
||||||
|
"difficulty": 1,
|
||||||
|
"question": "Der Befehl `runlevel` gibt `N 5` aus. Was bedeutet das?",
|
||||||
|
"options": [
|
||||||
|
{ "id": "a", "text": "Es gab keinen vorherigen Runlevel (N); der aktuelle ist 5.", "correct": true, "explanation": "Erstes Feld: vorheriger Runlevel, zweites: aktueller." },
|
||||||
|
{ "id": "b", "text": "Das System startet in 5 Minuten neu.", "correct": false, "explanation": "`runlevel` plant nichts." },
|
||||||
|
{ "id": "c", "text": "Netzwerk ist deaktiviert (N), 5 Benutzer sind angemeldet.", "correct": false, "explanation": "Mit Benutzern oder Netzwerk hat die Ausgabe nichts zu tun." },
|
||||||
|
{ "id": "d", "text": "Der aktuelle Runlevel ist N (normal), der vorherige 5.", "correct": false, "explanation": "Reihenfolge vertauscht; N bedeutet „none“." },
|
||||||
|
{ "id": "e", "text": "Runlevel 5 ist fehlgeschlagen.", "correct": false, "explanation": "Fehler zeigt `runlevel` nicht an." }
|
||||||
|
],
|
||||||
|
"explanation": "Unter systemd wird der Runlevel aus dem aktiven Target abgeleitet (`graphical.target` → 5).",
|
||||||
|
"references": ["man 8 runlevel"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "101.3-006",
|
||||||
|
"objective": "101.3",
|
||||||
|
"type": "fill",
|
||||||
|
"difficulty": 1,
|
||||||
|
"question": "Mit welchem `systemctl`-Befehl (vollständig) zeigt man das aktuelle **Standard-Target** an?",
|
||||||
|
"answers": ["systemctl get-default"],
|
||||||
|
"explanation": "Gegenstück: `systemctl set-default <target>`.",
|
||||||
|
"references": ["man 1 systemctl"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "101.3-007",
|
||||||
|
"objective": "101.3",
|
||||||
|
"type": "single",
|
||||||
|
"difficulty": 1,
|
||||||
|
"question": "Welcher Befehl sendet eine Nachricht an die Terminals **aller** angemeldeten Benutzer?",
|
||||||
|
"options": [
|
||||||
|
{ "id": "a", "text": "`wall`", "correct": true, "explanation": "write all: liest den Text von stdin oder als Argument." },
|
||||||
|
{ "id": "b", "text": "`write`", "correct": false, "explanation": "Schreibt an **einen** bestimmten Benutzer." },
|
||||||
|
{ "id": "c", "text": "`mesg`", "correct": false, "explanation": "Erlaubt bzw. verbietet den Empfang von Nachrichten am eigenen Terminal." },
|
||||||
|
{ "id": "d", "text": "`logger`", "correct": false, "explanation": "Schreibt ins Systemprotokoll." },
|
||||||
|
{ "id": "e", "text": "`notify`", "correct": false, "explanation": "Kein Standardbefehl für Terminalnachrichten." }
|
||||||
|
],
|
||||||
|
"explanation": "`shutdown` benachrichtigt angemeldete Benutzer ebenfalls per wall.",
|
||||||
|
"references": ["man 1 wall"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "101.3-008",
|
||||||
|
"objective": "101.3",
|
||||||
|
"type": "single",
|
||||||
|
"difficulty": 1,
|
||||||
|
"question": "Welcher Befehl startet ein systemd-System **sofort neu**?",
|
||||||
|
"options": [
|
||||||
|
{ "id": "a", "text": "`systemctl reboot`", "correct": true, "explanation": "Entspricht dem Wechsel zu `reboot.target`; ebenso `reboot` oder `shutdown -r now`." },
|
||||||
|
{ "id": "b", "text": "`systemctl restart`", "correct": false, "explanation": "Startet **Units** neu und erwartet einen Unit-Namen." },
|
||||||
|
{ "id": "c", "text": "`systemctl isolate poweroff.target`", "correct": false, "explanation": "Schaltet das System aus." },
|
||||||
|
{ "id": "d", "text": "`telinit 0`", "correct": false, "explanation": "Runlevel 0 hält bzw. schaltet aus." },
|
||||||
|
{ "id": "e", "text": "`shutdown -h now`", "correct": false, "explanation": "`-h` hält an bzw. schaltet aus." }
|
||||||
|
],
|
||||||
|
"explanation": "Weitere: `systemctl poweroff`, `systemctl halt`, `systemctl suspend`.",
|
||||||
|
"references": ["man 1 systemctl"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "101.3-009",
|
||||||
|
"objective": "101.3",
|
||||||
|
"type": "multi",
|
||||||
|
"difficulty": 1,
|
||||||
|
"question": "Welche Zuordnungen der klassischen SysV-Runlevels sind korrekt?",
|
||||||
|
"options": [
|
||||||
|
{ "id": "a", "text": "Runlevel 0: System anhalten (halt/poweroff)", "correct": true, "explanation": "`telinit 0` fährt herunter." },
|
||||||
|
{ "id": "b", "text": "Runlevel 6: Neustart", "correct": true, "explanation": "`telinit 6` startet neu." },
|
||||||
|
{ "id": "c", "text": "Runlevel 1: grafischer Mehrbenutzerbetrieb", "correct": false, "explanation": "Runlevel 1 ist der Einzelbenutzermodus." },
|
||||||
|
{ "id": "d", "text": "Runlevel 5: Einzelbenutzermodus", "correct": false, "explanation": "Runlevel 5 ist (bei vielen Distributionen) Mehrbenutzer mit grafischer Anmeldung." },
|
||||||
|
{ "id": "e", "text": "Runlevel 3: Neustart", "correct": false, "explanation": "Runlevel 3 ist Mehrbenutzer ohne grafische Oberfläche." }
|
||||||
|
],
|
||||||
|
"explanation": "Die Bedeutung von 2–5 war distributionsabhängig; 0, 1 und 6 sind überall gleich.",
|
||||||
|
"references": ["man 8 init"]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -0,0 +1,369 @@
|
|||||||
|
{
|
||||||
|
"$schema": "../schema/questions.schema.json",
|
||||||
|
"format": "lpic-sim-questions",
|
||||||
|
"meta": {
|
||||||
|
"file": "questions_102_set2.json",
|
||||||
|
"brief": "Zweiter Fragensatz zu Topic 102 Linux-Installation und Paketverwaltung (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 (30.10.2026)"
|
||||||
|
},
|
||||||
|
"exam": "lpic1-101",
|
||||||
|
"questions": [
|
||||||
|
{
|
||||||
|
"id": "102.1-004",
|
||||||
|
"objective": "102.1",
|
||||||
|
"type": "single",
|
||||||
|
"difficulty": 1,
|
||||||
|
"question": "Wofür nutzt Linux eine Swap-Partition bzw. Swap-Datei?",
|
||||||
|
"options": [
|
||||||
|
{ "id": "a", "text": "Zum Auslagern selten genutzter Speicherseiten bei knappem Arbeitsspeicher (und für den Ruhezustand)", "correct": true, "explanation": "Swap erweitert den virtuellen Speicher; Hibernate schreibt den RAM-Inhalt dorthin." },
|
||||||
|
{ "id": "b", "text": "Zum Ablegen temporärer Dateien statt `/tmp`", "correct": false, "explanation": "Swap enthält kein Dateisystem für Dateien." },
|
||||||
|
{ "id": "c", "text": "Als Sicherungskopie der Partitionstabelle", "correct": false, "explanation": "Die GPT-Sicherung liegt am Plattenende, nicht im Swap." },
|
||||||
|
{ "id": "d", "text": "Zum Starten des Kernels", "correct": false, "explanation": "Kernel und initramfs liegen in `/boot`." },
|
||||||
|
{ "id": "e", "text": "Als Cache für Paketdownloads", "correct": false, "explanation": "Paket-Caches liegen unter `/var/cache`." }
|
||||||
|
],
|
||||||
|
"explanation": "Aktive Swap-Bereiche zeigen `swapon --show` und `free -h`.",
|
||||||
|
"references": ["man 8 swapon"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "102.1-005",
|
||||||
|
"objective": "102.1",
|
||||||
|
"type": "single",
|
||||||
|
"difficulty": 2,
|
||||||
|
"question": "Warum legt man `/boot` häufig auf eine **eigene, unverschlüsselte** Partition?",
|
||||||
|
"options": [
|
||||||
|
{ "id": "a", "text": "Damit der Bootloader Kernel und initramfs lesen kann, auch wenn das Root-Dateisystem verschlüsselt ist oder in LVM/RAID liegt", "correct": true, "explanation": "Die initramfs entschlüsselt bzw. aktiviert dann das eigentliche Root-Dateisystem." },
|
||||||
|
{ "id": "b", "text": "Weil `/boot` die Benutzerdaten enthält", "correct": false, "explanation": "Benutzerdaten liegen in `/home`." },
|
||||||
|
{ "id": "c", "text": "Weil `/boot` ständig wächst und das Root-Dateisystem füllen würde", "correct": false, "explanation": "`/boot` ist klein und wächst kaum." },
|
||||||
|
{ "id": "d", "text": "Weil Swap in `/boot` liegen muss", "correct": false, "explanation": "Swap ist ein eigener Bereich." },
|
||||||
|
{ "id": "e", "text": "Weil `/boot` immer XFS sein muss", "correct": false, "explanation": "Dafür gibt es keine solche Vorgabe; üblich ist ext4." }
|
||||||
|
],
|
||||||
|
"explanation": "Bei UEFI kommt zusätzlich die EFI-Systempartition (FAT) hinzu.",
|
||||||
|
"references": ["man 7 hier"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "102.1-006",
|
||||||
|
"objective": "102.1",
|
||||||
|
"type": "fill",
|
||||||
|
"difficulty": 1,
|
||||||
|
"question": "Unter welchem Pfad wird die EFI-Systempartition üblicherweise eingehängt?",
|
||||||
|
"answers": ["/boot/efi", "/efi"],
|
||||||
|
"explanation": "Dort liegen z. B. `EFI/debian/grubx64.efi` oder `shimx64.efi`.",
|
||||||
|
"references": ["UEFI-Spezifikation, Abschnitt EFI System Partition"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "102.1-007",
|
||||||
|
"objective": "102.1",
|
||||||
|
"type": "multi",
|
||||||
|
"difficulty": 2,
|
||||||
|
"question": "Welche Verzeichnisse müssen laut klassischer FHS-Vorgabe auf dem **Root-Dateisystem** liegen und dürfen keine eigene Partition sein?",
|
||||||
|
"options": [
|
||||||
|
{ "id": "a", "text": "`/etc`", "correct": true, "explanation": "Konfiguration wird gebraucht, bevor weitere Dateisysteme eingehängt sind (z. B. `/etc/fstab`)." },
|
||||||
|
{ "id": "b", "text": "`/sbin`", "correct": true, "explanation": "Programme wie `mount` und `fsck` müssen beim Start verfügbar sein." },
|
||||||
|
{ "id": "c", "text": "`/home`", "correct": false, "explanation": "Typischer Kandidat für eine eigene Partition." },
|
||||||
|
{ "id": "d", "text": "`/var`", "correct": false, "explanation": "Kann (und sollte oft) eigenständig sein." },
|
||||||
|
{ "id": "e", "text": "`/tmp`", "correct": false, "explanation": "Kann eigene Partition oder tmpfs im RAM sein." }
|
||||||
|
],
|
||||||
|
"explanation": "Ebenso `/bin`, `/lib`, `/dev`. Bei zusammengeführtem `/usr` (usrmerge) sind `/bin`, `/sbin`, `/lib` Links nach `/usr`; dann bindet die initramfs `/usr` früh ein.",
|
||||||
|
"references": ["man 7 hier"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "102.2-004",
|
||||||
|
"objective": "102.2",
|
||||||
|
"type": "single",
|
||||||
|
"difficulty": 1,
|
||||||
|
"question": "Wie installiert man GRUB 2 in den Bootsektor (MBR) der ersten Festplatte eines BIOS-Systems?",
|
||||||
|
"options": [
|
||||||
|
{ "id": "a", "text": "`grub-install /dev/sda`", "correct": true, "explanation": "Ziel ist das ganze Gerät, nicht eine Partition." },
|
||||||
|
{ "id": "b", "text": "`grub-install /dev/sda1`", "correct": false, "explanation": "Installiert in den Bootsektor einer Partition – unüblich und nicht der MBR." },
|
||||||
|
{ "id": "c", "text": "`grub-mkconfig /dev/sda`", "correct": false, "explanation": "`grub-mkconfig` erzeugt nur die Konfiguration." },
|
||||||
|
{ "id": "d", "text": "`update-grub /dev/sda`", "correct": false, "explanation": "`update-grub` schreibt nur `grub.cfg`." },
|
||||||
|
{ "id": "e", "text": "`dd if=/boot/grub of=/dev/sda`", "correct": false, "explanation": "`/boot/grub` ist ein Verzeichnis; so zerstört man im schlimmsten Fall die Platte." }
|
||||||
|
],
|
||||||
|
"explanation": "Bei UEFI: `grub-install --target=x86_64-efi --efi-directory=/boot/efi`.",
|
||||||
|
"references": ["man 8 grub-install"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "102.2-005",
|
||||||
|
"objective": "102.2",
|
||||||
|
"type": "fill",
|
||||||
|
"difficulty": 1,
|
||||||
|
"question": "Welche Variable in `/etc/default/grub` legt fest, wie viele Sekunden das GRUB-Menü wartet?",
|
||||||
|
"answers": ["GRUB_TIMEOUT"],
|
||||||
|
"explanation": "Nach Änderung `update-grub` bzw. `grub-mkconfig -o …` ausführen. `GRUB_DEFAULT` legt den Standardeintrag fest.",
|
||||||
|
"references": ["info grub (Simple configuration)"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "102.2-006",
|
||||||
|
"objective": "102.2",
|
||||||
|
"type": "single",
|
||||||
|
"difficulty": 2,
|
||||||
|
"question": "Was bezeichnet `(hd0,1)` in **GRUB 2**?",
|
||||||
|
"options": [
|
||||||
|
{ "id": "a", "text": "Die erste Partition der ersten Festplatte", "correct": true, "explanation": "GRUB 2 zählt Platten ab 0, Partitionen ab 1." },
|
||||||
|
{ "id": "b", "text": "Die zweite Partition der ersten Festplatte", "correct": false, "explanation": "So wäre es bei GRUB Legacy (Partitionen ab 0)." },
|
||||||
|
{ "id": "c", "text": "Die erste Partition der zweiten Festplatte", "correct": false, "explanation": "Die zweite Platte wäre `hd1`." },
|
||||||
|
{ "id": "d", "text": "Die ganze erste Festplatte", "correct": false, "explanation": "Das wäre `(hd0)`." },
|
||||||
|
{ "id": "e", "text": "Das CD-Laufwerk", "correct": false, "explanation": "Optische Laufwerke heißen meist `(cd)`." }
|
||||||
|
],
|
||||||
|
"explanation": "Oft mit Tabellentyp: `(hd0,gpt1)` bzw. `(hd0,msdos1)`.",
|
||||||
|
"references": ["info grub (Device syntax)"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "102.2-007",
|
||||||
|
"objective": "102.2",
|
||||||
|
"type": "single",
|
||||||
|
"difficulty": 2,
|
||||||
|
"question": "Wo trägt man bei GRUB 2 **dauerhaft** zusätzliche Kernel-Parameter für alle Einträge ein?",
|
||||||
|
"options": [
|
||||||
|
{ "id": "a", "text": "In `GRUB_CMDLINE_LINUX` bzw. `GRUB_CMDLINE_LINUX_DEFAULT` in `/etc/default/grub`, danach `update-grub`", "correct": true, "explanation": "`grub-mkconfig` übernimmt die Werte in jede `linux`-Zeile." },
|
||||||
|
{ "id": "b", "text": "Direkt in `/boot/grub/grub.cfg`", "correct": false, "explanation": "Wird bei der nächsten Neuerzeugung überschrieben." },
|
||||||
|
{ "id": "c", "text": "In `/proc/cmdline`", "correct": false, "explanation": "Nur lesbar und nur die Anzeige des laufenden Starts." },
|
||||||
|
{ "id": "d", "text": "In `/etc/sysctl.conf`", "correct": false, "explanation": "Setzt Laufzeitparameter (`/proc/sys`), keine Boot-Parameter." },
|
||||||
|
{ "id": "e", "text": "In `/etc/modprobe.d/`", "correct": false, "explanation": "Optionen für Kernelmodule, keine Kernel-Befehlszeile." }
|
||||||
|
],
|
||||||
|
"explanation": "`GRUB_CMDLINE_LINUX_DEFAULT` gilt nur für normale Einträge, nicht für den Recovery-Modus.",
|
||||||
|
"references": ["info grub (Simple configuration)"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "102.3-003",
|
||||||
|
"objective": "102.3",
|
||||||
|
"type": "fill",
|
||||||
|
"difficulty": 1,
|
||||||
|
"question": "Welche Umgebungsvariable nennt zusätzliche Verzeichnisse, in denen der dynamische Linker **vorrangig** nach Shared Libraries sucht?",
|
||||||
|
"answers": ["LD_LIBRARY_PATH"],
|
||||||
|
"explanation": "Mehrere Pfade durch `:` getrennt. Für Programme mit SUID wird sie aus Sicherheitsgründen ignoriert.",
|
||||||
|
"references": ["man 8 ld.so"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "102.3-004",
|
||||||
|
"objective": "102.3",
|
||||||
|
"type": "single",
|
||||||
|
"difficulty": 2,
|
||||||
|
"question": "In welcher Datei legt `ldconfig` den Cache der bekannten Shared Libraries ab?",
|
||||||
|
"options": [
|
||||||
|
{ "id": "a", "text": "`/etc/ld.so.cache`", "correct": true, "explanation": "Binärer Cache, den der dynamische Linker beim Programmstart liest." },
|
||||||
|
{ "id": "b", "text": "`/etc/ld.so.conf`", "correct": false, "explanation": "Konfiguration der zusätzlichen Suchpfade." },
|
||||||
|
{ "id": "c", "text": "`/etc/ld.so.preload`", "correct": false, "explanation": "Liste von Bibliotheken, die jedem Programm vorab geladen werden." },
|
||||||
|
{ "id": "d", "text": "`/lib64/ld-linux-x86-64.so.2`", "correct": false, "explanation": "Das ist der dynamische Linker selbst." },
|
||||||
|
{ "id": "e", "text": "`/proc/ld`", "correct": false, "explanation": "Diesen Pfad gibt es nicht." }
|
||||||
|
],
|
||||||
|
"explanation": "Bibliotheksnamen: `libname.so.<version>` (soname), dazu Symlinks; `ldconfig` pflegt sie.",
|
||||||
|
"references": ["man 8 ldconfig"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "102.4-006",
|
||||||
|
"objective": "102.4",
|
||||||
|
"type": "single",
|
||||||
|
"difficulty": 1,
|
||||||
|
"question": "Wie installiert man die heruntergeladene Datei `tool_1.2_amd64.deb` mit dpkg?",
|
||||||
|
"options": [
|
||||||
|
{ "id": "a", "text": "`dpkg -i tool_1.2_amd64.deb`", "correct": true, "explanation": "`-i` (install) installiert bzw. aktualisiert aus der Datei." },
|
||||||
|
{ "id": "b", "text": "`dpkg -x tool_1.2_amd64.deb`", "correct": false, "explanation": "`-x` entpackt nur den Inhalt in ein Verzeichnis." },
|
||||||
|
{ "id": "c", "text": "`dpkg -c tool_1.2_amd64.deb`", "correct": false, "explanation": "`-c` listet den Inhalt." },
|
||||||
|
{ "id": "d", "text": "`dpkg -I tool_1.2_amd64.deb`", "correct": false, "explanation": "`-I` zeigt Informationen (control) zur Datei." },
|
||||||
|
{ "id": "e", "text": "`dpkg -r tool_1.2_amd64.deb`", "correct": false, "explanation": "`-r` entfernt ein installiertes Paket." }
|
||||||
|
],
|
||||||
|
"explanation": "dpkg löst keine Abhängigkeiten auf; fehlende Pakete holt anschließend `apt-get install -f`. Mit apt direkt: `apt install ./tool_1.2_amd64.deb`.",
|
||||||
|
"references": ["man 1 dpkg"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "102.4-007",
|
||||||
|
"objective": "102.4",
|
||||||
|
"type": "fill",
|
||||||
|
"difficulty": 1,
|
||||||
|
"question": "Mit welchem `apt-cache`-Aufruf (Befehl und Unterbefehl, ohne Suchbegriff) durchsucht man Paketnamen und -beschreibungen nach einem Stichwort?",
|
||||||
|
"answers": ["apt-cache search"],
|
||||||
|
"explanation": "Beispiel: `apt-cache search webserver`. Details zu einem Paket: `apt-cache show <paket>`.",
|
||||||
|
"references": ["man 8 apt-cache"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "102.4-008",
|
||||||
|
"objective": "102.4",
|
||||||
|
"type": "single",
|
||||||
|
"difficulty": 2,
|
||||||
|
"question": "Nach `dpkg -i` meldet dpkg fehlende Abhängigkeiten. Welcher Befehl installiert sie nach und schließt die Installation ab?",
|
||||||
|
"options": [
|
||||||
|
{ "id": "a", "text": "`apt-get install -f`", "correct": true, "explanation": "`-f` (fix-broken) installiert fehlende Abhängigkeiten aus den Quellen." },
|
||||||
|
{ "id": "b", "text": "`dpkg --configure -a`", "correct": false, "explanation": "Konfiguriert entpackte Pakete, lädt aber keine fehlenden Pakete." },
|
||||||
|
{ "id": "c", "text": "`apt-get update`", "correct": false, "explanation": "Aktualisiert nur die Paketlisten." },
|
||||||
|
{ "id": "d", "text": "`apt-get autoclean`", "correct": false, "explanation": "Löscht veraltete .deb-Dateien aus dem Cache." },
|
||||||
|
{ "id": "e", "text": "`apt-get check`", "correct": false, "explanation": "Prüft nur auf Probleme, behebt nichts." }
|
||||||
|
],
|
||||||
|
"explanation": "`apt-get install -f` ohne Paketnamen versucht, das System in einen konsistenten Zustand zu bringen.",
|
||||||
|
"references": ["man 8 apt-get"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "102.4-009",
|
||||||
|
"objective": "102.4",
|
||||||
|
"type": "single",
|
||||||
|
"difficulty": 2,
|
||||||
|
"question": "Welche Zeile ist ein gültiger Eintrag in `/etc/apt/sources.list`?",
|
||||||
|
"options": [
|
||||||
|
{ "id": "a", "text": "`deb http://deb.debian.org/debian bookworm main`", "correct": true, "explanation": "Typ, URI, Distribution (Suite), Komponente(n)." },
|
||||||
|
{ "id": "b", "text": "`http://deb.debian.org/debian deb bookworm main`", "correct": false, "explanation": "Der Typ `deb` bzw. `deb-src` steht am Anfang." },
|
||||||
|
{ "id": "c", "text": "`repo=http://deb.debian.org/debian`", "correct": false, "explanation": "Das ist keine sources.list-Syntax." },
|
||||||
|
{ "id": "d", "text": "`deb bookworm main http://deb.debian.org/debian`", "correct": false, "explanation": "Die URI steht direkt nach dem Typ." },
|
||||||
|
{ "id": "e", "text": "`[main] baseurl=http://deb.debian.org/debian`", "correct": false, "explanation": "Ähnelt yum-Repo-Dateien, nicht apt." }
|
||||||
|
],
|
||||||
|
"explanation": "Neueres Format: `*.sources`-Dateien (deb822) unter `/etc/apt/sources.list.d/` mit `Types:`, `URIs:`, `Suites:`, `Components:`.",
|
||||||
|
"references": ["man 5 sources.list"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "102.4-010",
|
||||||
|
"objective": "102.4",
|
||||||
|
"type": "multi",
|
||||||
|
"difficulty": 2,
|
||||||
|
"question": "Mit welchen Befehlen sieht man die **Abhängigkeiten** eines Debian-Pakets aus den Paketquellen?",
|
||||||
|
"options": [
|
||||||
|
{ "id": "a", "text": "`apt-cache depends nginx`", "correct": true, "explanation": "Listet Depends, Recommends, Conflicts usw." },
|
||||||
|
{ "id": "b", "text": "`apt-cache show nginx`", "correct": true, "explanation": "Zeigt die Paketbeschreibung inklusive Feld `Depends:`." },
|
||||||
|
{ "id": "c", "text": "`dpkg -L nginx`", "correct": false, "explanation": "Listet die Dateien eines installierten Pakets." },
|
||||||
|
{ "id": "d", "text": "`apt-get download nginx`", "correct": false, "explanation": "Lädt nur die .deb-Datei herunter." },
|
||||||
|
{ "id": "e", "text": "`apt-get autoremove nginx`", "correct": false, "explanation": "Entfernt nicht mehr benötigte Abhängigkeiten." }
|
||||||
|
],
|
||||||
|
"explanation": "Umgekehrte Richtung (wer hängt von X ab): `apt-cache rdepends <paket>`.",
|
||||||
|
"references": ["man 8 apt-cache"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "102.4-011",
|
||||||
|
"objective": "102.4",
|
||||||
|
"type": "single",
|
||||||
|
"difficulty": 2,
|
||||||
|
"question": "Was bedeutet der Status `ii` am Zeilenanfang der Ausgabe von `dpkg -l`?",
|
||||||
|
"options": [
|
||||||
|
{ "id": "a", "text": "Gewünscht: installieren, tatsächlich: installiert", "correct": true, "explanation": "Erstes Zeichen = gewünschter Zustand, zweites = aktueller Zustand." },
|
||||||
|
{ "id": "b", "text": "Entfernt, aber Konfigurationsdateien vorhanden", "correct": false, "explanation": "Das ist `rc`." },
|
||||||
|
{ "id": "c", "text": "Installation abgebrochen, Paket defekt", "correct": false, "explanation": "Das zeigt z. B. `iU` (unpacked) oder `iF` (half-configured)." },
|
||||||
|
{ "id": "d", "text": "Paket ist zur Aktualisierung vorgemerkt", "correct": false, "explanation": "Ein solcher Status steht nicht in den ersten beiden Zeichen." },
|
||||||
|
{ "id": "e", "text": "Paket ist nicht bekannt", "correct": false, "explanation": "Unbekannte Pakete erscheinen gar nicht oder als `un`." }
|
||||||
|
],
|
||||||
|
"explanation": "Installierte Pakete zählen: `dpkg -l | grep '^ii' | wc -l`.",
|
||||||
|
"references": ["man 1 dpkg-query"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "102.5-006",
|
||||||
|
"objective": "102.5",
|
||||||
|
"type": "single",
|
||||||
|
"difficulty": 1,
|
||||||
|
"question": "Welcher dnf-Befehl sucht Pakete anhand eines Stichworts in Name und Beschreibung?",
|
||||||
|
"options": [
|
||||||
|
{ "id": "a", "text": "`dnf search nginx`", "correct": true, "explanation": "Durchsucht Namen und Zusammenfassungen in den Repositories." },
|
||||||
|
{ "id": "b", "text": "`dnf info nginx`", "correct": false, "explanation": "Zeigt Details zu einem bekannten Paket." },
|
||||||
|
{ "id": "c", "text": "`dnf provides nginx`", "correct": false, "explanation": "Sucht, welches Paket eine Datei oder Fähigkeit bereitstellt." },
|
||||||
|
{ "id": "d", "text": "`dnf check-update`", "correct": false, "explanation": "Listet verfügbare Aktualisierungen." },
|
||||||
|
{ "id": "e", "text": "`dnf history`", "correct": false, "explanation": "Zeigt vergangene Transaktionen." }
|
||||||
|
],
|
||||||
|
"explanation": "Die meisten Unterbefehle funktionieren gleich mit `yum`.",
|
||||||
|
"references": ["man 8 dnf"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "102.5-007",
|
||||||
|
"objective": "102.5",
|
||||||
|
"type": "fill",
|
||||||
|
"difficulty": 2,
|
||||||
|
"question": "Mit welchem dnf-Unterbefehl (Befehl und Unterbefehl, ohne Argument) findet man heraus, welches Paket eine Datei wie `/usr/bin/dig` bereitstellt – auch wenn es nicht installiert ist?",
|
||||||
|
"answers": ["dnf provides", "dnf whatprovides", "yum provides", "yum whatprovides"],
|
||||||
|
"explanation": "Für installierte Pakete genügt `rpm -qf`; `provides` durchsucht die Repositories.",
|
||||||
|
"references": ["man 8 dnf"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "102.5-008",
|
||||||
|
"objective": "102.5",
|
||||||
|
"type": "single",
|
||||||
|
"difficulty": 1,
|
||||||
|
"question": "Wo liegen bei yum bzw. dnf die Definitionen der Paket-Repositories?",
|
||||||
|
"options": [
|
||||||
|
{ "id": "a", "text": "In `*.repo`-Dateien unter `/etc/yum.repos.d/`", "correct": true, "explanation": "Abschnitte mit `[id]`, `name=`, `baseurl=` bzw. `metalink=`, `enabled=`, `gpgcheck=`." },
|
||||||
|
{ "id": "b", "text": "In `/etc/apt/sources.list`", "correct": false, "explanation": "Das ist apt (Debian)." },
|
||||||
|
{ "id": "c", "text": "In `/var/lib/rpm/`", "correct": false, "explanation": "Dort liegt die RPM-Datenbank der installierten Pakete." },
|
||||||
|
{ "id": "d", "text": "In `/etc/zypp/repos.d/`", "correct": false, "explanation": "Das ist zypper (openSUSE)." },
|
||||||
|
{ "id": "e", "text": "In `/etc/rpmrc`", "correct": false, "explanation": "Allgemeine rpm-Einstellungen, keine Repositories." }
|
||||||
|
],
|
||||||
|
"explanation": "Globale Einstellungen: `/etc/dnf/dnf.conf` bzw. `/etc/yum.conf`. Repos auflisten: `dnf repolist`.",
|
||||||
|
"references": ["man 5 yum.conf", "man 5 dnf.conf"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "102.5-009",
|
||||||
|
"objective": "102.5",
|
||||||
|
"type": "single",
|
||||||
|
"difficulty": 2,
|
||||||
|
"question": "`rpm -V openssh-server` gibt die Zeile `S.5....T. c /etc/ssh/sshd_config` aus. Was bedeutet sie?",
|
||||||
|
"options": [
|
||||||
|
{ "id": "a", "text": "Größe, Prüfsumme und Änderungszeit der Konfigurationsdatei weichen vom Paketstand ab.", "correct": true, "explanation": "`S` Größe, `5` Digest, `T` mtime; `c` kennzeichnet eine Konfigurationsdatei." },
|
||||||
|
{ "id": "b", "text": "Die Datei fehlt.", "correct": false, "explanation": "Fehlende Dateien meldet rpm mit `missing`." },
|
||||||
|
{ "id": "c", "text": "Nur die Rechte der Datei wurden geändert.", "correct": false, "explanation": "Rechteänderungen zeigt `M` an der zweiten Stelle." },
|
||||||
|
{ "id": "d", "text": "Das Paket ist beschädigt und muss neu installiert werden.", "correct": false, "explanation": "Angepasste Konfigurationsdateien sind normal." },
|
||||||
|
{ "id": "e", "text": "Die Signatur des Pakets ist ungültig.", "correct": false, "explanation": "Signaturen prüft `rpm -K paket.rpm`." }
|
||||||
|
],
|
||||||
|
"explanation": "Ein Punkt bedeutet „Test bestanden“. Weitere Zeichen: `U` Eigentümer, `G` Gruppe, `L` Linkziel.",
|
||||||
|
"references": ["man 8 rpm (Abschnitt VERIFY OPTIONS)"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "102.5-010",
|
||||||
|
"objective": "102.5",
|
||||||
|
"type": "multi",
|
||||||
|
"difficulty": 2,
|
||||||
|
"question": "Welche Aussagen zu zypper treffen zu?",
|
||||||
|
"options": [
|
||||||
|
{ "id": "a", "text": "`zypper install nano` installiert das Paket samt Abhängigkeiten.", "correct": true, "explanation": "Kurzform `zypper in nano`." },
|
||||||
|
{ "id": "b", "text": "`zypper refresh` aktualisiert die Metadaten der Repositories.", "correct": true, "explanation": "Kurzform `zypper ref`; entspricht `apt-get update`." },
|
||||||
|
{ "id": "c", "text": "`zypper search nano` installiert alle Treffer.", "correct": false, "explanation": "`search` sucht nur." },
|
||||||
|
{ "id": "d", "text": "`zypper repos` löscht alle Repositories.", "correct": false, "explanation": "`repos` (`lr`) listet sie; entfernen: `removerepo`." },
|
||||||
|
{ "id": "e", "text": "zypper verwaltet Debian-Pakete.", "correct": false, "explanation": "zypper arbeitet mit RPM-Paketen (openSUSE, SLES)." }
|
||||||
|
],
|
||||||
|
"explanation": "Weitere: `zypper update`, `zypper remove`, `zypper addrepo`, `zypper what-provides`.",
|
||||||
|
"references": ["man 8 zypper"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "102.5-011",
|
||||||
|
"objective": "102.5",
|
||||||
|
"type": "single",
|
||||||
|
"difficulty": 1,
|
||||||
|
"question": "Wie entfernt man das installierte Paket `nano` direkt mit rpm?",
|
||||||
|
"options": [
|
||||||
|
{ "id": "a", "text": "`rpm -e nano`", "correct": true, "explanation": "`-e` (erase) entfernt das Paket; abhängige Pakete verhindern das." },
|
||||||
|
{ "id": "b", "text": "`rpm -r nano`", "correct": false, "explanation": "rpm kennt `-r` nicht zum Entfernen." },
|
||||||
|
{ "id": "c", "text": "`rpm -U nano`", "correct": false, "explanation": "`-U` aktualisiert aus einer Paketdatei." },
|
||||||
|
{ "id": "d", "text": "`rpm -qe nano`", "correct": false, "explanation": "Keine gültige Kombination." },
|
||||||
|
{ "id": "e", "text": "`rpm -d nano`", "correct": false, "explanation": "`-d` gehört zu Abfragen (Dokumentationsdateien, `-qd`)." }
|
||||||
|
],
|
||||||
|
"explanation": "Mit Abhängigkeitsauflösung: `dnf remove nano`.",
|
||||||
|
"references": ["man 8 rpm"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "102.6-003",
|
||||||
|
"objective": "102.6",
|
||||||
|
"type": "single",
|
||||||
|
"difficulty": 1,
|
||||||
|
"question": "Was unterscheidet einen Linux-**Container** grundlegend von einer virtuellen Maschine?",
|
||||||
|
"options": [
|
||||||
|
{ "id": "a", "text": "Container teilen sich den Kernel des Hosts; eine VM bringt einen eigenen Kernel auf virtueller Hardware mit.", "correct": true, "explanation": "Container isolieren Prozesse über Namespaces und cgroups." },
|
||||||
|
{ "id": "b", "text": "Container benötigen immer einen Hypervisor vom Typ 1.", "correct": false, "explanation": "Container brauchen gar keinen Hypervisor." },
|
||||||
|
{ "id": "c", "text": "In einem Container läuft stets ein anderes Betriebssystem als Linux.", "correct": false, "explanation": "Linux-Container nutzen den Linux-Kernel des Hosts." },
|
||||||
|
{ "id": "d", "text": "VMs starten schneller, weil sie keinen Kernel laden.", "correct": false, "explanation": "VMs booten einen eigenen Kernel; Container starten meist schneller." },
|
||||||
|
{ "id": "e", "text": "Container haben keinen Zugriff auf Netzwerk.", "correct": false, "explanation": "Container haben normalerweise eigene virtuelle Netzwerkschnittstellen." }
|
||||||
|
],
|
||||||
|
"explanation": "Begriffe aus 102.6: Systemcontainer (vollständiges Userland) und Anwendungscontainer (einzelne Anwendung).",
|
||||||
|
"references": ["man 7 namespaces", "man 7 cgroups"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "102.6-004",
|
||||||
|
"objective": "102.6",
|
||||||
|
"type": "multi",
|
||||||
|
"difficulty": 2,
|
||||||
|
"question": "Welche Aussagen zur Virtualisierung treffen zu?",
|
||||||
|
"options": [
|
||||||
|
{ "id": "a", "text": "Paravirtualisierte Treiber (z. B. virtio) verbessern die I/O-Leistung von Gästen.", "correct": true, "explanation": "Der Gast weiß, dass er virtualisiert läuft, und spricht mit dem Hypervisor über effiziente Schnittstellen." },
|
||||||
|
{ "id": "b", "text": "Ein Hypervisor vom Typ 1 läuft direkt auf der Hardware.", "correct": true, "explanation": "Beispiele: Xen, KVM (als Teil des Linux-Kernels), ESXi. Typ 2 läuft auf einem Host-Betriebssystem." },
|
||||||
|
{ "id": "c", "text": "Jeder Container enthält einen eigenen Kernel.", "correct": false, "explanation": "Container nutzen den Kernel des Hosts." },
|
||||||
|
{ "id": "d", "text": "cloud-init läuft auf dem Hypervisor und konfiguriert alle Gäste von außen.", "correct": false, "explanation": "cloud-init läuft **im** Gast beim ersten Start." },
|
||||||
|
{ "id": "e", "text": "Ohne Gasterweiterungen kann eine VM nicht starten.", "correct": false, "explanation": "Gasterweiterungen verbessern Leistung und Integration, sind aber nicht nötig." }
|
||||||
|
],
|
||||||
|
"explanation": "In VMs zeigt `systemd-detect-virt` die erkannte Virtualisierung an.",
|
||||||
|
"references": ["man 1 systemd-detect-virt"]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -0,0 +1,713 @@
|
|||||||
|
{
|
||||||
|
"$schema": "../schema/questions.schema.json",
|
||||||
|
"format": "lpic-sim-questions",
|
||||||
|
"meta": {
|
||||||
|
"file": "questions_103_set2.json",
|
||||||
|
"brief": "Zweiter Fragensatz 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 (30.10.2026)"
|
||||||
|
},
|
||||||
|
"exam": "lpic1-101",
|
||||||
|
"questions": [
|
||||||
|
{
|
||||||
|
"id": "103.1-007",
|
||||||
|
"objective": "103.1",
|
||||||
|
"type": "single",
|
||||||
|
"difficulty": 1,
|
||||||
|
"question": "Wie öffnet man die Manpage zum **Dateiformat** von `/etc/passwd` statt zum Befehl `passwd`?",
|
||||||
|
"options": [
|
||||||
|
{ "id": "a", "text": "`man 5 passwd`", "correct": true, "explanation": "Abschnitt 5 enthält Dateiformate und Konventionen." },
|
||||||
|
{ "id": "b", "text": "`man passwd`", "correct": false, "explanation": "Zeigt den ersten Treffer – meist Abschnitt 1, den Befehl." },
|
||||||
|
{ "id": "c", "text": "`man 1 passwd`", "correct": false, "explanation": "Abschnitt 1 sind Benutzerbefehle." },
|
||||||
|
{ "id": "d", "text": "`man -k passwd`", "correct": false, "explanation": "Sucht nur in den Kurzbeschreibungen (wie `apropos`)." },
|
||||||
|
{ "id": "e", "text": "`man 8 passwd`", "correct": false, "explanation": "Abschnitt 8 sind Administrationsbefehle." }
|
||||||
|
],
|
||||||
|
"explanation": "Wichtige Abschnitte: 1 Befehle, 2 Systemaufrufe, 3 Bibliotheksfunktionen, 4 Gerätedateien, 5 Dateiformate, 7 Verschiedenes, 8 Administration.",
|
||||||
|
"references": ["man 1 man"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "103.1-008",
|
||||||
|
"objective": "103.1",
|
||||||
|
"type": "fill",
|
||||||
|
"difficulty": 1,
|
||||||
|
"question": "Welcher Befehl (nur der Name) durchsucht die Kurzbeschreibungen aller Manpages nach einem Stichwort – gleichwertig zu `man -k`?",
|
||||||
|
"answers": ["apropos"],
|
||||||
|
"explanation": "Die Datenbank dafür pflegt `mandb`. `whatis` zeigt die Kurzbeschreibung zu einem exakten Namen.",
|
||||||
|
"references": ["man 1 apropos"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "103.1-009",
|
||||||
|
"objective": "103.1",
|
||||||
|
"type": "single",
|
||||||
|
"difficulty": 1,
|
||||||
|
"question": "Was bewirkt `cd -` in der Bash?",
|
||||||
|
"options": [
|
||||||
|
{ "id": "a", "text": "Wechsel in das vorherige Arbeitsverzeichnis (`$OLDPWD`)", "correct": true, "explanation": "Praktisch zum Hin- und Herspringen; der neue Pfad wird ausgegeben." },
|
||||||
|
{ "id": "b", "text": "Wechsel in das Home-Verzeichnis", "correct": false, "explanation": "Das macht `cd` ohne Argument oder `cd ~`." },
|
||||||
|
{ "id": "c", "text": "Wechsel in das übergeordnete Verzeichnis", "correct": false, "explanation": "Das macht `cd ..`." },
|
||||||
|
{ "id": "d", "text": "Wechsel in das Wurzelverzeichnis", "correct": false, "explanation": "Das macht `cd /`." },
|
||||||
|
{ "id": "e", "text": "Fehlermeldung, da `-` kein Verzeichnis ist", "correct": false, "explanation": "`-` hat bei `cd` eine eigene Bedeutung." }
|
||||||
|
],
|
||||||
|
"explanation": "Das aktuelle Verzeichnis steht in `$PWD` bzw. wird mit `pwd` ausgegeben.",
|
||||||
|
"references": ["help cd"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "103.1-010",
|
||||||
|
"objective": "103.1",
|
||||||
|
"type": "single",
|
||||||
|
"difficulty": 1,
|
||||||
|
"question": "Welche Ausgabe erzeugt `echo \"Pfad: $HOME\"` für die Benutzerin `anna` mit dem Home-Verzeichnis `/home/anna`?",
|
||||||
|
"options": [
|
||||||
|
{ "id": "a", "text": "`Pfad: /home/anna`", "correct": true, "explanation": "In doppelten Anführungszeichen wird `$HOME` ersetzt; die Anführungszeichen selbst erscheinen nicht." },
|
||||||
|
{ "id": "b", "text": "`Pfad: $HOME`", "correct": false, "explanation": "So wäre es mit einfachen Anführungszeichen." },
|
||||||
|
{ "id": "c", "text": "`\"Pfad: /home/anna\"`", "correct": false, "explanation": "Die Shell entfernt die Anführungszeichen vor der Übergabe an `echo`." },
|
||||||
|
{ "id": "d", "text": "`Pfad:`", "correct": false, "explanation": "`HOME` ist gesetzt, also wird ein Wert eingesetzt." },
|
||||||
|
{ "id": "e", "text": "Eine Fehlermeldung", "correct": false, "explanation": "Der Befehl ist korrekt." }
|
||||||
|
],
|
||||||
|
"explanation": "Reihenfolge der Verarbeitung: Quoting erkennen → Expansionen → Anführungszeichen entfernen → Befehl ausführen.",
|
||||||
|
"references": ["man 1 bash (Abschnitt QUOTING)"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "103.1-011",
|
||||||
|
"objective": "103.1",
|
||||||
|
"type": "multi",
|
||||||
|
"difficulty": 2,
|
||||||
|
"question": "Im aktuellen Verzeichnis existiert eine Datei `axb`. Welche Befehle geben trotzdem genau den Text `a*b` aus?",
|
||||||
|
"options": [
|
||||||
|
{ "id": "a", "text": "`echo 'a*b'`", "correct": true, "explanation": "In einfachen Anführungszeichen findet kein Globbing statt." },
|
||||||
|
{ "id": "b", "text": "`echo a\\*b`", "correct": true, "explanation": "Der Backslash maskiert den Stern." },
|
||||||
|
{ "id": "c", "text": "`echo a*b`", "correct": false, "explanation": "Das Muster passt auf `axb` – ausgegeben wird `axb`." },
|
||||||
|
{ "id": "d", "text": "`echo $(a*b)`", "correct": false, "explanation": "Befehlsersetzung: Die Shell versucht `axb` als Befehl auszuführen." },
|
||||||
|
{ "id": "e", "text": "`echo {a*b}`", "correct": false, "explanation": "Ohne Komma keine Klammererweiterung; das Muster `{a*b}` trifft nichts, ausgegeben wird `{a*b}` mit Klammern." }
|
||||||
|
],
|
||||||
|
"explanation": "Auch `echo \"a*b\"` funktioniert: In doppelten Anführungszeichen gibt es kein Globbing.",
|
||||||
|
"references": ["man 1 bash (Abschnitt Pathname Expansion)"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "103.1-012",
|
||||||
|
"objective": "103.1",
|
||||||
|
"type": "single",
|
||||||
|
"difficulty": 1,
|
||||||
|
"question": "Mit welcher Tastenkombination durchsucht man in der Bash die History **rückwärts interaktiv**?",
|
||||||
|
"options": [
|
||||||
|
{ "id": "a", "text": "Strg+R", "correct": true, "explanation": "reverse-i-search; erneutes Strg+R springt zum nächsten älteren Treffer." },
|
||||||
|
{ "id": "b", "text": "Strg+C", "correct": false, "explanation": "Bricht den laufenden Befehl bzw. die Eingabe ab (SIGINT)." },
|
||||||
|
{ "id": "c", "text": "Strg+D", "correct": false, "explanation": "Dateiende (EOF); in einer leeren Zeile beendet es die Shell." },
|
||||||
|
{ "id": "d", "text": "Strg+Z", "correct": false, "explanation": "Hält den Vordergrundprozess an (SIGTSTP)." },
|
||||||
|
{ "id": "e", "text": "Strg+L", "correct": false, "explanation": "Leert den Bildschirm." }
|
||||||
|
],
|
||||||
|
"explanation": "Pfeil hoch/runter blättert durch die History, `history` listet sie nummeriert.",
|
||||||
|
"references": ["man 1 bash (Abschnitt READLINE)"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "103.1-013",
|
||||||
|
"objective": "103.1",
|
||||||
|
"type": "fill",
|
||||||
|
"difficulty": 1,
|
||||||
|
"question": "Welcher Befehl (nur der Name) gibt den absoluten Pfad des aktuellen Arbeitsverzeichnisses aus?",
|
||||||
|
"answers": ["pwd"],
|
||||||
|
"explanation": "print working directory; `pwd -P` löst symbolische Links auf.",
|
||||||
|
"references": ["help pwd"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "103.2-004",
|
||||||
|
"objective": "103.2",
|
||||||
|
"type": "single",
|
||||||
|
"difficulty": 1,
|
||||||
|
"question": "Eine Datei enthält die Zeilen `10`, `9` und `100`. Welcher Befehl sortiert sie **numerisch** aufsteigend (9, 10, 100)?",
|
||||||
|
"options": [
|
||||||
|
{ "id": "a", "text": "`sort -n zahlen.txt`", "correct": true, "explanation": "`-n` vergleicht den Zahlenwert." },
|
||||||
|
{ "id": "b", "text": "`sort zahlen.txt`", "correct": false, "explanation": "Lexikalisch: `10`, `100`, `9`." },
|
||||||
|
{ "id": "c", "text": "`sort -r zahlen.txt`", "correct": false, "explanation": "Lexikalisch absteigend." },
|
||||||
|
{ "id": "d", "text": "`sort -u zahlen.txt`", "correct": false, "explanation": "Entfernt Duplikate, sortiert aber lexikalisch." },
|
||||||
|
{ "id": "e", "text": "`sort -k zahlen.txt`", "correct": false, "explanation": "`-k` erwartet eine Feldangabe." }
|
||||||
|
],
|
||||||
|
"explanation": "Kombinierbar: `sort -t: -k3 -n /etc/passwd` sortiert nach UID.",
|
||||||
|
"references": ["man 1 sort"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "103.2-005",
|
||||||
|
"objective": "103.2",
|
||||||
|
"type": "fill",
|
||||||
|
"difficulty": 1,
|
||||||
|
"question": "Welcher Befehl (nur der Name) gibt eine Datei in umgekehrter Zeilenreihenfolge aus (letzte Zeile zuerst)?",
|
||||||
|
"answers": ["tac"],
|
||||||
|
"explanation": "`tac` ist `cat` rückwärts. Zeichen innerhalb einer Zeile umkehren würde `rev`.",
|
||||||
|
"references": ["man 1 tac"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "103.2-006",
|
||||||
|
"objective": "103.2",
|
||||||
|
"type": "single",
|
||||||
|
"difficulty": 1,
|
||||||
|
"question": "Welcher Befehl wandelt alle Kleinbuchstaben in `namen.txt` in Großbuchstaben um?",
|
||||||
|
"options": [
|
||||||
|
{ "id": "a", "text": "`tr 'a-z' 'A-Z' < namen.txt`", "correct": true, "explanation": "`tr` liest nur von stdin und ersetzt Zeichen der ersten Menge durch die der zweiten." },
|
||||||
|
{ "id": "b", "text": "`tr 'A-Z' 'a-z' < namen.txt`", "correct": false, "explanation": "Umgekehrte Richtung: Groß- zu Kleinbuchstaben." },
|
||||||
|
{ "id": "c", "text": "`tr -d 'a-z' < namen.txt`", "correct": false, "explanation": "`-d` löscht die Kleinbuchstaben." },
|
||||||
|
{ "id": "d", "text": "`tr 'a-z' 'A-Z' namen.txt`", "correct": false, "explanation": "`tr` nimmt keine Dateinamen an; die Datei würde als weitere Zeichenmenge gelesen." },
|
||||||
|
{ "id": "e", "text": "`cut -c A-Z namen.txt`", "correct": false, "explanation": "`cut -c` erwartet Zeichenpositionen." }
|
||||||
|
],
|
||||||
|
"explanation": "Mit Klassen: `tr '[:lower:]' '[:upper:]'`. `tr -s ' '` fasst Leerzeichen zusammen.",
|
||||||
|
"references": ["man 1 tr"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "103.2-007",
|
||||||
|
"objective": "103.2",
|
||||||
|
"type": "multi",
|
||||||
|
"difficulty": 2,
|
||||||
|
"question": "Welche Aussagen zu Prüfsummen-Werkzeugen treffen zu?",
|
||||||
|
"options": [
|
||||||
|
{ "id": "a", "text": "`sha256sum datei.iso` berechnet die SHA-256-Prüfsumme der Datei.", "correct": true, "explanation": "Ausgabe: Hash und Dateiname." },
|
||||||
|
{ "id": "b", "text": "`sha256sum -c SHA256SUMS` prüft Dateien gegen eine Liste von Prüfsummen.", "correct": true, "explanation": "Meldet je Datei `OK` oder `FAILED`." },
|
||||||
|
{ "id": "c", "text": "`md5sum` gilt heute als kryptografisch sicher gegen gezielte Manipulation.", "correct": false, "explanation": "MD5 ist gebrochen; für Integrität gegen Angreifer SHA-256/SHA-512 nutzen." },
|
||||||
|
{ "id": "d", "text": "`wc -c` berechnet eine Prüfsumme.", "correct": false, "explanation": "`wc -c` zählt Bytes." },
|
||||||
|
{ "id": "e", "text": "`nl` verschlüsselt eine Datei.", "correct": false, "explanation": "`nl` nummeriert Zeilen." }
|
||||||
|
],
|
||||||
|
"explanation": "Im Objective genannt: `md5sum`, `sha256sum`, `sha512sum`. Weitere Filter: `nl`, `od`, `paste`, `split`, `zcat`, `xzcat`, `bzcat`.",
|
||||||
|
"references": ["man 1 sha256sum"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "103.3-007",
|
||||||
|
"objective": "103.3",
|
||||||
|
"type": "single",
|
||||||
|
"difficulty": 1,
|
||||||
|
"question": "Welcher Befehl legt `projekt/2026/oktober` an, auch wenn `projekt` und `projekt/2026` noch nicht existieren?",
|
||||||
|
"options": [
|
||||||
|
{ "id": "a", "text": "`mkdir -p projekt/2026/oktober`", "correct": true, "explanation": "`-p` (parents) legt fehlende übergeordnete Verzeichnisse mit an und meldet keinen Fehler, wenn sie existieren." },
|
||||||
|
{ "id": "b", "text": "`mkdir projekt/2026/oktober`", "correct": false, "explanation": "Scheitert, wenn ein übergeordnetes Verzeichnis fehlt." },
|
||||||
|
{ "id": "c", "text": "`mkdir -r projekt/2026/oktober`", "correct": false, "explanation": "`mkdir` hat keine Option `-r`." },
|
||||||
|
{ "id": "d", "text": "`touch -d projekt/2026/oktober`", "correct": false, "explanation": "`touch -d` setzt einen Zeitstempel aus einer Datumsangabe." },
|
||||||
|
{ "id": "e", "text": "`cp -r projekt/2026/oktober`", "correct": false, "explanation": "`cp` kopiert und braucht ein Ziel." }
|
||||||
|
],
|
||||||
|
"explanation": "`mkdir -m 750 dir` setzt die Rechte direkt beim Anlegen.",
|
||||||
|
"references": ["man 1 mkdir"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "103.3-008",
|
||||||
|
"objective": "103.3",
|
||||||
|
"type": "fill",
|
||||||
|
"difficulty": 2,
|
||||||
|
"question": "Welcher `find`-Test (Option mit Wert) wählt Dateien aus, deren Inhalt vor **weniger als 2 Tagen** geändert wurde?",
|
||||||
|
"answers": ["-mtime -2"],
|
||||||
|
"explanation": "`-mtime n` zählt in 24-Stunden-Einheiten: `-2` weniger als 2, `+2` mehr als 2, `2` genau 2. Minutengenau: `-mmin`.",
|
||||||
|
"references": ["man 1 find"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "103.3-009",
|
||||||
|
"objective": "103.3",
|
||||||
|
"type": "single",
|
||||||
|
"difficulty": 1,
|
||||||
|
"question": "Das Verzeichnis `alt` enthält noch Dateien. Welcher Befehl löscht es **samt Inhalt**?",
|
||||||
|
"options": [
|
||||||
|
{ "id": "a", "text": "`rm -r alt`", "correct": true, "explanation": "`-r` löscht rekursiv; mit `-f` ohne Rückfragen – vorsichtig verwenden." },
|
||||||
|
{ "id": "b", "text": "`rmdir alt`", "correct": false, "explanation": "`rmdir` löscht nur leere Verzeichnisse." },
|
||||||
|
{ "id": "c", "text": "`rm -d alt`", "correct": false, "explanation": "`-d` löscht nur leere Verzeichnisse." },
|
||||||
|
{ "id": "d", "text": "`unlink alt`", "correct": false, "explanation": "`unlink` entfernt genau eine Datei, keine Verzeichnisse." },
|
||||||
|
{ "id": "e", "text": "`rmdir -p alt`", "correct": false, "explanation": "Entfernt leere Verzeichnisse samt leerer Elternverzeichnisse." }
|
||||||
|
],
|
||||||
|
"explanation": "`rm -i` fragt vor jedem Löschen nach.",
|
||||||
|
"references": ["man 1 rm"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "103.3-010",
|
||||||
|
"objective": "103.3",
|
||||||
|
"type": "single",
|
||||||
|
"difficulty": 1,
|
||||||
|
"question": "Was passiert bei `gzip bericht.txt`?",
|
||||||
|
"options": [
|
||||||
|
{ "id": "a", "text": "Es entsteht `bericht.txt.gz`, die Originaldatei wird entfernt.", "correct": true, "explanation": "gzip ersetzt die Datei durch die komprimierte Fassung; `-k` behält das Original." },
|
||||||
|
{ "id": "b", "text": "Es entsteht `bericht.txt.gz`, die Originaldatei bleibt erhalten.", "correct": false, "explanation": "Nur mit `-k` (keep) oder `-c` und Umleitung." },
|
||||||
|
{ "id": "c", "text": "Es entsteht ein tar-Archiv `bericht.tar.gz`.", "correct": false, "explanation": "gzip komprimiert einzelne Dateien und erstellt keine Archive." },
|
||||||
|
{ "id": "d", "text": "Die Datei wird entpackt.", "correct": false, "explanation": "Entpacken: `gunzip` bzw. `gzip -d`." },
|
||||||
|
{ "id": "e", "text": "Die Datei wird in ein ZIP-Archiv gelegt.", "correct": false, "explanation": "ZIP erstellt `zip`." }
|
||||||
|
],
|
||||||
|
"explanation": "Gleiches Verhalten bei `bzip2` (`.bz2`) und `xz` (`.xz`). Lesen ohne Entpacken: `zcat`, `bzcat`, `xzcat`.",
|
||||||
|
"references": ["man 1 gzip"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "103.3-011",
|
||||||
|
"objective": "103.3",
|
||||||
|
"type": "single",
|
||||||
|
"difficulty": 2,
|
||||||
|
"question": "Wie erstellt man mit `cpio` ein Archiv aller `.conf`-Dateien unterhalb des aktuellen Verzeichnisses?",
|
||||||
|
"options": [
|
||||||
|
{ "id": "a", "text": "`find . -name '*.conf' | cpio -o > conf.cpio`", "correct": true, "explanation": "cpio liest die Dateiliste von stdin; `-o` (copy-out) schreibt das Archiv auf stdout." },
|
||||||
|
{ "id": "b", "text": "`cpio -o *.conf conf.cpio`", "correct": false, "explanation": "cpio nimmt Dateinamen nicht als Argumente, sondern von stdin." },
|
||||||
|
{ "id": "c", "text": "`find . -name '*.conf' | cpio -i > conf.cpio`", "correct": false, "explanation": "`-i` (copy-in) liest ein Archiv und entpackt." },
|
||||||
|
{ "id": "d", "text": "`cpio -c conf.cpio .`", "correct": false, "explanation": "Keine gültige Erstellung eines Archivs." },
|
||||||
|
{ "id": "e", "text": "`tar -cpio conf.cpio *.conf`", "correct": false, "explanation": "Vermischt Optionen von tar und cpio." }
|
||||||
|
],
|
||||||
|
"explanation": "Entpacken: `cpio -idv < conf.cpio`. cpio ist u. a. das Format der initramfs.",
|
||||||
|
"references": ["man 1 cpio"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "103.3-012",
|
||||||
|
"objective": "103.3",
|
||||||
|
"type": "multi",
|
||||||
|
"difficulty": 1,
|
||||||
|
"question": "Welche Aussagen zu `touch` treffen zu?",
|
||||||
|
"options": [
|
||||||
|
{ "id": "a", "text": "`touch neu.txt` legt eine leere Datei an, wenn sie noch nicht existiert.", "correct": true, "explanation": "Gängiger Weg, eine leere Datei zu erzeugen." },
|
||||||
|
{ "id": "b", "text": "Bei einer bestehenden Datei aktualisiert `touch` die Zeitstempel.", "correct": true, "explanation": "Zugriffs- und Änderungszeit werden auf jetzt gesetzt (`-a`/`-m` einzeln)." },
|
||||||
|
{ "id": "c", "text": "`touch` leert den Inhalt einer bestehenden Datei.", "correct": false, "explanation": "Der Inhalt bleibt unverändert; leeren z. B. mit `> datei` oder `truncate -s 0`." },
|
||||||
|
{ "id": "d", "text": "`touch` legt Verzeichnisse an.", "correct": false, "explanation": "Verzeichnisse legt `mkdir` an." },
|
||||||
|
{ "id": "e", "text": "`touch` darf nur root verwenden.", "correct": false, "explanation": "Jeder Benutzer mit Schreibrecht im Verzeichnis darf das." }
|
||||||
|
],
|
||||||
|
"explanation": "`touch -d '2026-10-01 12:00' datei` setzt einen bestimmten Zeitstempel.",
|
||||||
|
"references": ["man 1 touch"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "103.3-013",
|
||||||
|
"objective": "103.3",
|
||||||
|
"type": "single",
|
||||||
|
"difficulty": 1,
|
||||||
|
"question": "Alle `.log`-Dateien sollen nach `archiv/` verschoben werden; vor dem Überschreiben vorhandener Dateien soll nachgefragt werden. Welcher Befehl leistet das?",
|
||||||
|
"options": [
|
||||||
|
{ "id": "a", "text": "`mv -i *.log archiv/`", "correct": true, "explanation": "`-i` (interactive) fragt vor dem Überschreiben." },
|
||||||
|
{ "id": "b", "text": "`mv -f *.log archiv/`", "correct": false, "explanation": "`-f` überschreibt ohne Nachfrage." },
|
||||||
|
{ "id": "c", "text": "`mv -n *.log archiv/`", "correct": false, "explanation": "`-n` überschreibt nie und fragt auch nicht." },
|
||||||
|
{ "id": "d", "text": "`cp -i *.log archiv/`", "correct": false, "explanation": "Kopiert nur, die Originale bleiben." },
|
||||||
|
{ "id": "e", "text": "`mv -u *.log archiv/`", "correct": false, "explanation": "`-u` verschiebt nur, wenn die Quelle neuer ist – ohne Nachfrage." }
|
||||||
|
],
|
||||||
|
"explanation": "Auf demselben Dateisystem benennt `mv` nur um (schnell); über Dateisystemgrenzen wird kopiert und gelöscht.",
|
||||||
|
"references": ["man 1 mv"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "103.4-007",
|
||||||
|
"objective": "103.4",
|
||||||
|
"type": "single",
|
||||||
|
"difficulty": 1,
|
||||||
|
"question": "Wie nennt man die Konstruktion `cat << ENDE` gefolgt von mehreren Zeilen und einer abschließenden Zeile `ENDE`?",
|
||||||
|
"options": [
|
||||||
|
{ "id": "a", "text": "Here-Document", "correct": true, "explanation": "Die Zeilen bis zur Endmarke werden dem Befehl als stdin übergeben." },
|
||||||
|
{ "id": "b", "text": "Here-String", "correct": false, "explanation": "Here-String ist `<<< \"text\"` – eine einzelne Zeichenkette." },
|
||||||
|
{ "id": "c", "text": "Pipe", "correct": false, "explanation": "Eine Pipe verbindet stdout und stdin zweier Befehle." },
|
||||||
|
{ "id": "d", "text": "Prozessersetzung", "correct": false, "explanation": "Prozessersetzung ist `<(befehl)`." },
|
||||||
|
{ "id": "e", "text": "Befehlsersetzung", "correct": false, "explanation": "Befehlsersetzung ist `$(befehl)`." }
|
||||||
|
],
|
||||||
|
"explanation": "Mit `<< 'ENDE'` (Endmarke in Anführungszeichen) werden Variablen im Text nicht ersetzt; `<<-` entfernt führende Tabulatoren.",
|
||||||
|
"references": ["man 1 bash (Abschnitt Here Documents)"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "103.4-008",
|
||||||
|
"objective": "103.4",
|
||||||
|
"type": "fill",
|
||||||
|
"difficulty": 2,
|
||||||
|
"question": "Welcher Operator übergibt in der Bash eine einzelne Zeichenkette als Standardeingabe, z. B. `bc ___ \"2+3\"`? (nur der Operator)",
|
||||||
|
"answers": ["<<<"],
|
||||||
|
"explanation": "Here-String: `bc <<< \"2+3\"` gibt `5` aus. Gleichwertig: `echo \"2+3\" | bc`.",
|
||||||
|
"references": ["man 1 bash (Abschnitt Here Strings)"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "103.4-009",
|
||||||
|
"objective": "103.4",
|
||||||
|
"type": "single",
|
||||||
|
"difficulty": 1,
|
||||||
|
"question": "Was bewirkt in der Bash `befehl &> ausgabe.txt`?",
|
||||||
|
"options": [
|
||||||
|
{ "id": "a", "text": "Standardausgabe und Fehlerausgabe werden in `ausgabe.txt` geschrieben.", "correct": true, "explanation": "Kurzform für `> ausgabe.txt 2>&1`." },
|
||||||
|
{ "id": "b", "text": "Der Befehl läuft im Hintergrund und schreibt nur stdout in die Datei.", "correct": false, "explanation": "`&>` ist eine Umleitung, kein Hintergrundstart." },
|
||||||
|
{ "id": "c", "text": "Nur die Fehlerausgabe wird umgeleitet.", "correct": false, "explanation": "Das wäre `2>`." },
|
||||||
|
{ "id": "d", "text": "Die Ausgabe wird an die Datei angehängt.", "correct": false, "explanation": "`&>` überschreibt; anhängen: `&>>`." },
|
||||||
|
{ "id": "e", "text": "Die Datei wird als Eingabe gelesen.", "correct": false, "explanation": "Eingabe wäre `<`." }
|
||||||
|
],
|
||||||
|
"explanation": "`&>` ist Bash-spezifisch; in POSIX-sh schreibt man `> datei 2>&1`.",
|
||||||
|
"references": ["man 1 bash (Abschnitt REDIRECTION)"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "103.4-010",
|
||||||
|
"objective": "103.4",
|
||||||
|
"type": "single",
|
||||||
|
"difficulty": 1,
|
||||||
|
"question": "Die Ausgabe soll auf dem Bildschirm erscheinen und an `log.txt` **angehängt** werden. Welche Zeile ist richtig?",
|
||||||
|
"options": [
|
||||||
|
{ "id": "a", "text": "`befehl | tee -a log.txt`", "correct": true, "explanation": "`-a` (append) hängt an, statt zu überschreiben." },
|
||||||
|
{ "id": "b", "text": "`befehl | tee log.txt`", "correct": false, "explanation": "Überschreibt `log.txt`." },
|
||||||
|
{ "id": "c", "text": "`befehl | tee >> log.txt`", "correct": false, "explanation": "`tee` ohne Datei gibt nur auf stdout aus, und das landet per `>>` in der Datei – auf dem Bildschirm erscheint nichts." },
|
||||||
|
{ "id": "d", "text": "`befehl >> log.txt | tee`", "correct": false, "explanation": "stdout geht vollständig in die Datei; `tee` erhält nichts." },
|
||||||
|
{ "id": "e", "text": "`befehl 2>> log.txt`", "correct": false, "explanation": "Hängt nur die Fehlerausgabe an." }
|
||||||
|
],
|
||||||
|
"explanation": "Mehrere Ziele gleichzeitig: `befehl | tee a.txt b.txt`.",
|
||||||
|
"references": ["man 1 tee"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "103.4-011",
|
||||||
|
"objective": "103.4",
|
||||||
|
"type": "multi",
|
||||||
|
"difficulty": 2,
|
||||||
|
"question": "Welche Aussagen zu `xargs` treffen zu?",
|
||||||
|
"options": [
|
||||||
|
{ "id": "a", "text": "Mit `-n 1` wird der Befehl für jedes Argument einzeln aufgerufen.", "correct": true, "explanation": "`-n` begrenzt die Argumente pro Aufruf." },
|
||||||
|
{ "id": "b", "text": "Mit `-0` liest xargs durch NUL-Zeichen getrennte Namen, passend zu `find -print0`.", "correct": true, "explanation": "So funktionieren auch Namen mit Leerzeichen oder Zeilenumbrüchen." },
|
||||||
|
{ "id": "c", "text": "xargs liest die Argumente aus einer als Parameter angegebenen Datei, nie von stdin.", "correct": false, "explanation": "Standard ist stdin; eine Datei nur mit `-a`." },
|
||||||
|
{ "id": "d", "text": "xargs ruft den Befehl immer genau einmal pro Eingabezeile auf.", "correct": false, "explanation": "Standardmäßig bündelt xargs möglichst viele Argumente in einem Aufruf." },
|
||||||
|
{ "id": "e", "text": "Mit `-I {}` werden alle geschweiften Klammern aus der Eingabe gelöscht.", "correct": false, "explanation": "`-I {}` legt einen Platzhalter fest, der durch jedes Eingabeelement ersetzt wird." }
|
||||||
|
],
|
||||||
|
"explanation": "Beispiel mit Platzhalter: `ls *.txt | xargs -I {} cp {} /sicherung/`.",
|
||||||
|
"references": ["man 1 xargs"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "103.4-012",
|
||||||
|
"objective": "103.4",
|
||||||
|
"type": "single",
|
||||||
|
"difficulty": 2,
|
||||||
|
"question": "Wie leitet man Standardausgabe **und** Fehlerausgabe eines Befehls gemeinsam an `less` weiter?",
|
||||||
|
"options": [
|
||||||
|
{ "id": "a", "text": "`befehl 2>&1 | less`", "correct": true, "explanation": "stderr wird vor der Pipe auf stdout gelegt; beides fließt in die Pipe." },
|
||||||
|
{ "id": "b", "text": "`befehl | less 2>&1`", "correct": false, "explanation": "Die Umleitung gilt hier für `less`, nicht für `befehl`." },
|
||||||
|
{ "id": "c", "text": "`befehl 2> | less`", "correct": false, "explanation": "Syntaxfehler: `2>` braucht ein Ziel." },
|
||||||
|
{ "id": "d", "text": "`befehl > less 2>&1`", "correct": false, "explanation": "Schreibt in eine **Datei** namens `less`." },
|
||||||
|
{ "id": "e", "text": "`befehl & less`", "correct": false, "explanation": "Startet `befehl` im Hintergrund und danach `less` ohne Eingabe." }
|
||||||
|
],
|
||||||
|
"explanation": "Bash-Kurzform: `befehl |& less`.",
|
||||||
|
"references": ["man 1 bash (Abschnitt Pipelines)"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "103.4-013",
|
||||||
|
"objective": "103.4",
|
||||||
|
"type": "single",
|
||||||
|
"difficulty": 1,
|
||||||
|
"question": "Was liefert `cat /dev/null`?",
|
||||||
|
"options": [
|
||||||
|
{ "id": "a", "text": "Nichts – Lesen ergibt sofort Dateiende.", "correct": true, "explanation": "`/dev/null` verwirft Geschriebenes und liefert beim Lesen nichts." },
|
||||||
|
{ "id": "b", "text": "Endlos Nullbytes", "correct": false, "explanation": "Das liefert `/dev/zero`." },
|
||||||
|
{ "id": "c", "text": "Zufallsdaten", "correct": false, "explanation": "Das liefern `/dev/random` und `/dev/urandom`." },
|
||||||
|
{ "id": "d", "text": "Den Inhalt der zuletzt verworfenen Ausgaben", "correct": false, "explanation": "Verworfenes wird nicht gespeichert." },
|
||||||
|
{ "id": "e", "text": "Eine Fehlermeldung „Permission denied“", "correct": false, "explanation": "`/dev/null` ist für alle les- und schreibbar." }
|
||||||
|
],
|
||||||
|
"explanation": "Praktisch: `cat /dev/null > datei` leert eine Datei, ohne sie zu löschen.",
|
||||||
|
"references": ["man 4 null"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "103.5-007",
|
||||||
|
"objective": "103.5",
|
||||||
|
"type": "single",
|
||||||
|
"difficulty": 1,
|
||||||
|
"question": "Welcher Befehl zeigt **alle** Prozesse aller Benutzer mit Benutzer, CPU- und Speicheranteil an?",
|
||||||
|
"options": [
|
||||||
|
{ "id": "a", "text": "`ps aux`", "correct": true, "explanation": "BSD-Syntax: `a` alle mit Terminal, `u` benutzerorientiert, `x` auch ohne Terminal." },
|
||||||
|
{ "id": "b", "text": "`ps`", "correct": false, "explanation": "Ohne Optionen nur die Prozesse des aktuellen Terminals." },
|
||||||
|
{ "id": "c", "text": "`jobs`", "correct": false, "explanation": "Zeigt nur Jobs der aktuellen Shell." },
|
||||||
|
{ "id": "d", "text": "`pstree`", "correct": false, "explanation": "Zeigt die Prozesshierarchie ohne CPU- und Speicherwerte." },
|
||||||
|
{ "id": "e", "text": "`free`", "correct": false, "explanation": "Zeigt nur die Speicherbelegung insgesamt." }
|
||||||
|
],
|
||||||
|
"explanation": "Gleichwertig in System-V-Syntax: `ps -ef` (ohne %CPU/%MEM). Fortlaufend: `top` bzw. `htop`.",
|
||||||
|
"references": ["man 1 ps"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "103.5-008",
|
||||||
|
"objective": "103.5",
|
||||||
|
"type": "fill",
|
||||||
|
"difficulty": 1,
|
||||||
|
"question": "Welcher Befehl (nur der Name) stellt laufende Prozesse als Baum ihrer Eltern-Kind-Beziehungen dar?",
|
||||||
|
"answers": ["pstree"],
|
||||||
|
"explanation": "`pstree -p` zeigt zusätzlich die PIDs. Auch `ps -ef --forest` zeigt eine Baumansicht.",
|
||||||
|
"references": ["man 1 pstree"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "103.5-009",
|
||||||
|
"objective": "103.5",
|
||||||
|
"type": "single",
|
||||||
|
"difficulty": 1,
|
||||||
|
"question": "Welches Signal veranlasst viele Daemons, ihre **Konfiguration neu einzulesen**, ohne sich zu beenden?",
|
||||||
|
"options": [
|
||||||
|
{ "id": "a", "text": "SIGHUP (1)", "correct": true, "explanation": "Ursprünglich „Terminal aufgelegt“; Daemons ohne Terminal nutzen es als Reload-Signal." },
|
||||||
|
{ "id": "b", "text": "SIGKILL (9)", "correct": false, "explanation": "Beendet den Prozess sofort." },
|
||||||
|
{ "id": "c", "text": "SIGSTOP (19)", "correct": false, "explanation": "Hält den Prozess an." },
|
||||||
|
{ "id": "d", "text": "SIGCONT (18)", "correct": false, "explanation": "Setzt einen angehaltenen Prozess fort." },
|
||||||
|
{ "id": "e", "text": "SIGINT (2)", "correct": false, "explanation": "Unterbrechung, wie Strg+C – Programme beenden sich meist." }
|
||||||
|
],
|
||||||
|
"explanation": "Beispiel: `kill -HUP $(pidof rsyslogd)`. Bei systemd entsprechend `systemctl reload`.",
|
||||||
|
"references": ["man 7 signal"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "103.5-010",
|
||||||
|
"objective": "103.5",
|
||||||
|
"type": "single",
|
||||||
|
"difficulty": 1,
|
||||||
|
"question": "Welcher Befehl sendet SIGTERM an **alle** Prozesse mit dem Namen `httpd`?",
|
||||||
|
"options": [
|
||||||
|
{ "id": "a", "text": "`killall httpd`", "correct": true, "explanation": "`killall` wählt Prozesse nach Namen; ebenso `pkill httpd`." },
|
||||||
|
{ "id": "b", "text": "`kill httpd`", "correct": false, "explanation": "`kill` erwartet PIDs oder Jobspezifikationen." },
|
||||||
|
{ "id": "c", "text": "`pidof -k httpd`", "correct": false, "explanation": "`pidof` gibt nur PIDs aus." },
|
||||||
|
{ "id": "d", "text": "`pgrep -k httpd`", "correct": false, "explanation": "`pgrep` sucht nur; senden würde `pkill`." },
|
||||||
|
{ "id": "e", "text": "`top -k httpd`", "correct": false, "explanation": "`top` hat keine solche Option; im Programm beendet man mit der Taste `k`." }
|
||||||
|
],
|
||||||
|
"explanation": "Anderes Signal: `killall -HUP httpd` bzw. `pkill -HUP httpd`.",
|
||||||
|
"references": ["man 1 killall", "man 1 pkill"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "103.5-011",
|
||||||
|
"objective": "103.5",
|
||||||
|
"type": "multi",
|
||||||
|
"difficulty": 2,
|
||||||
|
"question": "Welche Aussagen zur Bedienung von `top` treffen zu?",
|
||||||
|
"options": [
|
||||||
|
{ "id": "a", "text": "Mit der Taste `k` sendet man einem Prozess ein Signal.", "correct": true, "explanation": "top fragt nach PID und Signal (Standard SIGTERM)." },
|
||||||
|
{ "id": "b", "text": "Mit der Taste `q` beendet man top.", "correct": true, "explanation": "quit." },
|
||||||
|
{ "id": "c", "text": "Mit der Taste `r` startet man das System neu.", "correct": false, "explanation": "`r` ändert den Nice-Wert eines Prozesses (renice)." },
|
||||||
|
{ "id": "d", "text": "Mit `M` sortiert top nach PID.", "correct": false, "explanation": "`M` sortiert nach Speicherverbrauch, `P` nach CPU." },
|
||||||
|
{ "id": "e", "text": "Mit `h` wird top im Hintergrund versteckt.", "correct": false, "explanation": "`h` zeigt die Hilfe." }
|
||||||
|
],
|
||||||
|
"explanation": "Nicht interaktiv, z. B. für Skripte: `top -b -n 1`.",
|
||||||
|
"references": ["man 1 top"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "103.5-012",
|
||||||
|
"objective": "103.5",
|
||||||
|
"type": "single",
|
||||||
|
"difficulty": 2,
|
||||||
|
"question": "Wie trennt man sich in **GNU screen** von der laufenden Sitzung, ohne sie zu beenden?",
|
||||||
|
"options": [
|
||||||
|
{ "id": "a", "text": "Strg+A, dann D", "correct": true, "explanation": "detach; wieder verbinden mit `screen -r`." },
|
||||||
|
{ "id": "b", "text": "Strg+B, dann D", "correct": false, "explanation": "Das ist die Standard-Tastenfolge von **tmux** (wieder verbinden: `tmux attach`)." },
|
||||||
|
{ "id": "c", "text": "Strg+D", "correct": false, "explanation": "Beendet die Shell im Fenster." },
|
||||||
|
{ "id": "d", "text": "Strg+Z", "correct": false, "explanation": "Hält den Vordergrundprozess an." },
|
||||||
|
{ "id": "e", "text": "Strg+C", "correct": false, "explanation": "Unterbricht den laufenden Befehl." }
|
||||||
|
],
|
||||||
|
"explanation": "Laufende Sitzungen auflisten: `screen -ls` bzw. `tmux ls`.",
|
||||||
|
"references": ["man 1 screen", "man 1 tmux"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "103.5-013",
|
||||||
|
"objective": "103.5",
|
||||||
|
"type": "single",
|
||||||
|
"difficulty": 1,
|
||||||
|
"question": "Was bewirkt `watch -n 5 df -h`?",
|
||||||
|
"options": [
|
||||||
|
{ "id": "a", "text": "`df -h` wird alle 5 Sekunden ausgeführt und die Ausgabe im Vollbild aktualisiert.", "correct": true, "explanation": "`-n` legt das Intervall fest (Standard 2 Sekunden); `-d` hebt Änderungen hervor." },
|
||||||
|
{ "id": "b", "text": "`df -h` läuft fünfmal und beendet sich dann.", "correct": false, "explanation": "`watch` läuft, bis man es mit Strg+C beendet." },
|
||||||
|
{ "id": "c", "text": "`df -h` startet in 5 Sekunden einmalig.", "correct": false, "explanation": "Einmalig verzögert wäre `sleep 5; df -h`." },
|
||||||
|
{ "id": "d", "text": "Es überwacht 5 Dateisysteme und alarmiert bei Fehlern.", "correct": false, "explanation": "`watch` alarmiert nicht von selbst." },
|
||||||
|
{ "id": "e", "text": "Es setzt den Nice-Wert von df auf 5.", "correct": false, "explanation": "Das wäre `nice -n 5 df -h`." }
|
||||||
|
],
|
||||||
|
"explanation": "Im Objective 103.5 genannt: `watch`, `screen`, `tmux`, `nohup`, `ps`, `top`, `free`, `uptime`, `pgrep`, `pkill`, `killall`.",
|
||||||
|
"references": ["man 1 watch"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "103.6-004",
|
||||||
|
"objective": "103.6",
|
||||||
|
"type": "fill",
|
||||||
|
"difficulty": 1,
|
||||||
|
"question": "Geben Sie den Befehl ein, der `./backup.sh` mit dem Nice-Wert 15 startet.",
|
||||||
|
"answers": ["nice -n 15 ./backup.sh", "nice -15 ./backup.sh", "nice --adjustment=15 ./backup.sh", "nice -n 15 backup.sh", "nice -15 backup.sh"],
|
||||||
|
"explanation": "Achtung: Bei `nice -15` ist der Bindestrich die Option, nicht das Vorzeichen; negativ wäre `nice --15` bzw. `nice -n -15`.",
|
||||||
|
"references": ["man 1 nice"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "103.6-005",
|
||||||
|
"objective": "103.6",
|
||||||
|
"type": "single",
|
||||||
|
"difficulty": 1,
|
||||||
|
"question": "In welcher Spalte zeigt `top` den Nice-Wert eines Prozesses?",
|
||||||
|
"options": [
|
||||||
|
{ "id": "a", "text": "NI", "correct": true, "explanation": "NI = nice value (−20 bis 19)." },
|
||||||
|
{ "id": "b", "text": "PR", "correct": false, "explanation": "PR ist die vom Kernel verwendete Priorität (meist 20 + NI)." },
|
||||||
|
{ "id": "c", "text": "S", "correct": false, "explanation": "S ist der Prozesszustand (R, S, D, Z, T)." },
|
||||||
|
{ "id": "d", "text": "RES", "correct": false, "explanation": "Belegter physischer Speicher." },
|
||||||
|
{ "id": "e", "text": "VIRT", "correct": false, "explanation": "Virtueller Speicher." }
|
||||||
|
],
|
||||||
|
"explanation": "In `ps -l` heißen die Spalten ebenfalls `PRI` und `NI`.",
|
||||||
|
"references": ["man 1 top"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "103.6-006",
|
||||||
|
"objective": "103.6",
|
||||||
|
"type": "single",
|
||||||
|
"difficulty": 1,
|
||||||
|
"question": "Welchen Nice-Wert erhält ein Programm, das mit `nice ./job.sh` (ohne weitere Optionen) gestartet wird?",
|
||||||
|
"options": [
|
||||||
|
{ "id": "a", "text": "10", "correct": true, "explanation": "Ohne Angabe erhöht `nice` den Wert um 10 (ausgehend von 0)." },
|
||||||
|
{ "id": "b", "text": "0", "correct": false, "explanation": "0 ist der Standard ohne `nice`." },
|
||||||
|
{ "id": "c", "text": "19", "correct": false, "explanation": "19 ist der niedrigste mögliche Vorrang, aber nicht der Standard von `nice`." },
|
||||||
|
{ "id": "d", "text": "−10", "correct": false, "explanation": "Negative Werte nur mit Root-Rechten und ausdrücklicher Angabe." },
|
||||||
|
{ "id": "e", "text": "1", "correct": false, "explanation": "Die Standarderhöhung ist 10." }
|
||||||
|
],
|
||||||
|
"explanation": "`nice` ohne Befehl gibt den aktuellen Nice-Wert der Shell aus.",
|
||||||
|
"references": ["man 1 nice"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "103.6-007",
|
||||||
|
"objective": "103.6",
|
||||||
|
"type": "single",
|
||||||
|
"difficulty": 2,
|
||||||
|
"question": "Wie setzt root den Nice-Wert **aller** laufenden Prozesse der Benutzerin `anna` auf 5?",
|
||||||
|
"options": [
|
||||||
|
{ "id": "a", "text": "`renice -n 5 -u anna`", "correct": true, "explanation": "`-u` wählt alle Prozesse eines Benutzers." },
|
||||||
|
{ "id": "b", "text": "`nice -n 5 -u anna`", "correct": false, "explanation": "`nice` startet neue Befehle und kennt kein `-u`." },
|
||||||
|
{ "id": "c", "text": "`renice -n 5 -p anna`", "correct": false, "explanation": "`-p` erwartet PIDs." },
|
||||||
|
{ "id": "d", "text": "`usermod -n 5 anna`", "correct": false, "explanation": "`usermod` hat keine Nice-Option." },
|
||||||
|
{ "id": "e", "text": "`ulimit -e 5 anna`", "correct": false, "explanation": "`ulimit -e` setzt eine Obergrenze der Priorität für die eigene Shell, nicht für fremde Prozesse." }
|
||||||
|
],
|
||||||
|
"explanation": "Mit `-g` wählt `renice` eine Prozessgruppe.",
|
||||||
|
"references": ["man 1 renice"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "103.7-005",
|
||||||
|
"objective": "103.7",
|
||||||
|
"type": "single",
|
||||||
|
"difficulty": 1,
|
||||||
|
"question": "Welche grep-Option ignoriert die Groß- und Kleinschreibung?",
|
||||||
|
"options": [
|
||||||
|
{ "id": "a", "text": "`-i`", "correct": true, "explanation": "`--ignore-case`." },
|
||||||
|
{ "id": "b", "text": "`-w`", "correct": false, "explanation": "Trifft nur ganze Wörter." },
|
||||||
|
{ "id": "c", "text": "`-x`", "correct": false, "explanation": "Trifft nur ganze Zeilen." },
|
||||||
|
{ "id": "d", "text": "`-c`", "correct": false, "explanation": "Zählt passende Zeilen." },
|
||||||
|
{ "id": "e", "text": "`-h`", "correct": false, "explanation": "Unterdrückt Dateinamen in der Ausgabe." }
|
||||||
|
],
|
||||||
|
"explanation": "Kombinierbar, z. B. `grep -iw error /var/log/syslog`.",
|
||||||
|
"references": ["man 1 grep"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "103.7-006",
|
||||||
|
"objective": "103.7",
|
||||||
|
"type": "fill",
|
||||||
|
"difficulty": 1,
|
||||||
|
"question": "Welche grep-Option (nur die Option) durchsucht Verzeichnisse **rekursiv**?",
|
||||||
|
"answers": ["-r", "-R", "--recursive", "--dereference-recursive"],
|
||||||
|
"explanation": "`-r` folgt symbolischen Links nur auf der Befehlszeile, `-R` allen. Beispiel: `grep -rn PermitRootLogin /etc/ssh/`.",
|
||||||
|
"references": ["man 1 grep"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "103.7-007",
|
||||||
|
"objective": "103.7",
|
||||||
|
"type": "single",
|
||||||
|
"difficulty": 2,
|
||||||
|
"question": "Welcher erweiterte reguläre Ausdruck (`grep -E`) passt sowohl auf `color` als auch auf `colour`?",
|
||||||
|
"options": [
|
||||||
|
{ "id": "a", "text": "`colou?r`", "correct": true, "explanation": "`?` bedeutet: vorheriges Zeichen null- oder einmal." },
|
||||||
|
{ "id": "b", "text": "`colo.r`", "correct": false, "explanation": "`.` verlangt genau ein Zeichen zwischen `colo` und `r` – passt auf `colour`, nicht auf `color`." },
|
||||||
|
{ "id": "c", "text": "`colo[u]r`", "correct": false, "explanation": "Die Klammer verlangt genau ein `u`." },
|
||||||
|
{ "id": "d", "text": "`colo(u)+r`", "correct": false, "explanation": "`+` verlangt mindestens ein `u`." },
|
||||||
|
{ "id": "e", "text": "`^colour$`", "correct": false, "explanation": "Passt nur auf Zeilen, die genau `colour` lauten." }
|
||||||
|
],
|
||||||
|
"explanation": "In Basic RE schreibt man unter GNU grep `colou\\?r`.",
|
||||||
|
"references": ["man 7 regex"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "103.7-008",
|
||||||
|
"objective": "103.7",
|
||||||
|
"type": "single",
|
||||||
|
"difficulty": 1,
|
||||||
|
"question": "Welche sed-Option ändert die Datei **direkt** (in place), statt das Ergebnis auf stdout auszugeben?",
|
||||||
|
"options": [
|
||||||
|
{ "id": "a", "text": "`-i`", "correct": true, "explanation": "`-i.bak` legt zusätzlich eine Sicherung an." },
|
||||||
|
{ "id": "b", "text": "`-n`", "correct": false, "explanation": "Unterdrückt die automatische Ausgabe (zusammen mit `p`)." },
|
||||||
|
{ "id": "c", "text": "`-e`", "correct": false, "explanation": "Leitet ein sed-Skript ein (mehrere `-e` möglich)." },
|
||||||
|
{ "id": "d", "text": "`-E`", "correct": false, "explanation": "Aktiviert erweiterte reguläre Ausdrücke." },
|
||||||
|
{ "id": "e", "text": "`-s`", "correct": false, "explanation": "Behandelt mehrere Dateien getrennt." }
|
||||||
|
],
|
||||||
|
"explanation": "Vor `sed -i` an wichtigen Dateien das Ergebnis ohne `-i` prüfen.",
|
||||||
|
"references": ["man 1 sed"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "103.7-009",
|
||||||
|
"objective": "103.7",
|
||||||
|
"type": "single",
|
||||||
|
"difficulty": 1,
|
||||||
|
"question": "Was gibt `sed '/^#/d' app.conf` aus?",
|
||||||
|
"options": [
|
||||||
|
{ "id": "a", "text": "Den Inhalt von `app.conf` ohne die Zeilen, die mit `#` beginnen", "correct": true, "explanation": "`/muster/d` löscht passende Zeilen aus der Ausgabe; die Datei bleibt unverändert." },
|
||||||
|
{ "id": "b", "text": "Nur die Zeilen, die mit `#` beginnen", "correct": false, "explanation": "Das wäre `sed -n '/^#/p'`." },
|
||||||
|
{ "id": "c", "text": "Nichts – die Datei wird gelöscht", "correct": false, "explanation": "`d` löscht Zeilen aus dem Datenstrom, keine Dateien." },
|
||||||
|
{ "id": "d", "text": "Den Inhalt, wobei jedes `#` durch `d` ersetzt wird", "correct": false, "explanation": "Ersetzen wäre `s/#/d/`." },
|
||||||
|
{ "id": "e", "text": "Nur die erste Zeile", "correct": false, "explanation": "Das wäre `sed -n 1p` bzw. `sed q`." }
|
||||||
|
],
|
||||||
|
"explanation": "Mit Leerzeilen zusammen: `sed -e '/^#/d' -e '/^$/d' app.conf`.",
|
||||||
|
"references": ["man 1 sed"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "103.7-010",
|
||||||
|
"objective": "103.7",
|
||||||
|
"type": "multi",
|
||||||
|
"difficulty": 2,
|
||||||
|
"question": "Welche Aussagen zu grep und seinen Varianten treffen zu?",
|
||||||
|
"options": [
|
||||||
|
{ "id": "a", "text": "`grep -c muster datei` gibt die Anzahl passender Zeilen aus.", "correct": true, "explanation": "Pro Datei eine Zahl." },
|
||||||
|
{ "id": "b", "text": "`grep -l muster *.conf` gibt nur die Namen der Dateien mit Treffern aus.", "correct": true, "explanation": "`-L` gibt umgekehrt die Dateien ohne Treffer aus." },
|
||||||
|
{ "id": "c", "text": "`egrep` entspricht `grep -F`.", "correct": false, "explanation": "`egrep` entspricht `grep -E`; `fgrep` entspricht `grep -F`." },
|
||||||
|
{ "id": "d", "text": "`fgrep` wertet reguläre Ausdrücke aus.", "correct": false, "explanation": "`fgrep` sucht feste Zeichenketten ohne Sonderbedeutung." },
|
||||||
|
{ "id": "e", "text": "`grep -o` gibt immer die ganze passende Zeile aus.", "correct": false, "explanation": "`-o` gibt nur den passenden Teil aus." }
|
||||||
|
],
|
||||||
|
"explanation": "`egrep` und `fgrep` gelten als veraltet; besser `grep -E` und `grep -F`.",
|
||||||
|
"references": ["man 1 grep"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "103.8-005",
|
||||||
|
"objective": "103.8",
|
||||||
|
"type": "single",
|
||||||
|
"difficulty": 1,
|
||||||
|
"question": "Welche Taste macht in vi im Befehlsmodus die letzte Änderung **rückgängig**?",
|
||||||
|
"options": [
|
||||||
|
{ "id": "a", "text": "`u`", "correct": true, "explanation": "undo; in vim wiederholt Strg+R das Rückgängiggemachte." },
|
||||||
|
{ "id": "b", "text": "`x`", "correct": false, "explanation": "Löscht das Zeichen unter dem Cursor." },
|
||||||
|
{ "id": "c", "text": "`p`", "correct": false, "explanation": "Fügt den Pufferinhalt ein." },
|
||||||
|
{ "id": "d", "text": "`r`", "correct": false, "explanation": "Ersetzt ein einzelnes Zeichen." },
|
||||||
|
{ "id": "e", "text": "`.`", "correct": false, "explanation": "Wiederholt die letzte Änderung." }
|
||||||
|
],
|
||||||
|
"explanation": "`U` macht alle Änderungen in der aktuellen Zeile rückgängig.",
|
||||||
|
"references": [":help undo"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "103.8-006",
|
||||||
|
"objective": "103.8",
|
||||||
|
"type": "fill",
|
||||||
|
"difficulty": 1,
|
||||||
|
"question": "Welche Tastenfolge kopiert in vi im Befehlsmodus die **aktuelle Zeile** in den Puffer (yank)?",
|
||||||
|
"answers": ["yy", "Y"],
|
||||||
|
"explanation": "Mit `p` fügt man sie unterhalb, mit `P` oberhalb ein. `3yy` kopiert drei Zeilen.",
|
||||||
|
"references": [":help yy"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "103.8-007",
|
||||||
|
"objective": "103.8",
|
||||||
|
"type": "single",
|
||||||
|
"difficulty": 2,
|
||||||
|
"question": "Welcher Ex-Befehl ersetzt in vi **in der ganzen Datei** jedes Vorkommen von `alt` durch `neu`?",
|
||||||
|
"options": [
|
||||||
|
{ "id": "a", "text": "`:%s/alt/neu/g`", "correct": true, "explanation": "`%` = alle Zeilen, `g` = alle Vorkommen je Zeile." },
|
||||||
|
{ "id": "b", "text": "`:s/alt/neu/`", "correct": false, "explanation": "Nur das erste Vorkommen in der aktuellen Zeile." },
|
||||||
|
{ "id": "c", "text": "`:%s/alt/neu/`", "correct": false, "explanation": "Ohne `g` nur das erste Vorkommen je Zeile." },
|
||||||
|
{ "id": "d", "text": "`/alt/neu`", "correct": false, "explanation": "Eine Suche nach dem Muster `alt/neu`." },
|
||||||
|
{ "id": "e", "text": "`:g/alt/`", "correct": false, "explanation": "Führt einen Befehl (Standard: ausgeben) für alle passenden Zeilen aus, ersetzt nichts." }
|
||||||
|
],
|
||||||
|
"explanation": "Mit Rückfrage je Treffer: `:%s/alt/neu/gc`.",
|
||||||
|
"references": [":help :substitute"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "103.8-008",
|
||||||
|
"objective": "103.8",
|
||||||
|
"type": "single",
|
||||||
|
"difficulty": 1,
|
||||||
|
"question": "Wie springt man in vi zur Zeile 42?",
|
||||||
|
"options": [
|
||||||
|
{ "id": "a", "text": "`:42`", "correct": true, "explanation": "Ex-Befehl mit Zeilennummer; gleichwertig im Befehlsmodus `42G`." },
|
||||||
|
{ "id": "b", "text": "`42dd`", "correct": false, "explanation": "Löscht 42 Zeilen ab der aktuellen." },
|
||||||
|
{ "id": "c", "text": "`/42`", "correct": false, "explanation": "Sucht nach dem Text „42“." },
|
||||||
|
{ "id": "d", "text": "`42yy`", "correct": false, "explanation": "Kopiert 42 Zeilen." },
|
||||||
|
{ "id": "e", "text": "`G42`", "correct": false, "explanation": "`G` springt ans Dateiende; `42` wäre dann der Beginn eines neuen Befehls." }
|
||||||
|
],
|
||||||
|
"explanation": "`gg` springt an den Anfang, `G` ans Ende. Zeilennummern anzeigen: `:set number`.",
|
||||||
|
"references": [":help G"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "103.8-009",
|
||||||
|
"objective": "103.8",
|
||||||
|
"type": "multi",
|
||||||
|
"difficulty": 1,
|
||||||
|
"question": "Welche Aussagen zu Texteditoren unter Linux treffen zu?",
|
||||||
|
"options": [
|
||||||
|
{ "id": "a", "text": "Die Variablen `EDITOR` bzw. `VISUAL` bestimmen den Editor für Programme wie `crontab -e` oder `visudo`.", "correct": true, "explanation": "z. B. `export EDITOR=vim` in `~/.bashrc`." },
|
||||||
|
{ "id": "b", "text": "In vi wechselt man mit der Esc-Taste in den Befehlsmodus.", "correct": true, "explanation": "Aus dem Einfüge- oder Ersetzungsmodus." },
|
||||||
|
{ "id": "c", "text": "`:q` beendet vi auch dann, wenn ungesicherte Änderungen vorliegen.", "correct": false, "explanation": "vi verweigert das; erzwingen mit `:q!`." },
|
||||||
|
{ "id": "d", "text": "`ZZ` verwirft alle Änderungen.", "correct": false, "explanation": "`ZZ` speichert (falls geändert) und beendet." },
|
||||||
|
{ "id": "e", "text": "`vi -R datei` öffnet die Datei mit Root-Rechten.", "correct": false, "explanation": "`-R` öffnet schreibgeschützt (read-only)." }
|
||||||
|
],
|
||||||
|
"explanation": "Im Objective genannt: vi mit `/`, `?`, `h j k l`, `i o a`, `d p y dd yy`, `ZZ :w! :q!`, sowie nano und emacs als Alternativen.",
|
||||||
|
"references": [":help ZZ"]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -0,0 +1,379 @@
|
|||||||
|
{
|
||||||
|
"$schema": "../schema/questions.schema.json",
|
||||||
|
"format": "lpic-sim-questions",
|
||||||
|
"meta": {
|
||||||
|
"file": "questions_104_set2.json",
|
||||||
|
"brief": "Zweiter Fragensatz zu Topic 104 Geräte, Linux-Dateisysteme, FHS (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 (30.10.2026)"
|
||||||
|
},
|
||||||
|
"exam": "lpic1-101",
|
||||||
|
"questions": [
|
||||||
|
{
|
||||||
|
"id": "104.1-004",
|
||||||
|
"objective": "104.1",
|
||||||
|
"type": "single",
|
||||||
|
"difficulty": 2,
|
||||||
|
"question": "Auf `/dev/sdb2` soll ein XFS-Dateisystem mit der Bezeichnung (Label) `daten` angelegt werden. Welcher Befehl ist korrekt?",
|
||||||
|
"options": [
|
||||||
|
{ "id": "a", "text": "`mkfs.xfs -L daten /dev/sdb2`", "correct": true, "explanation": "`-L` setzt das Label beim Anlegen (max. 12 Zeichen bei XFS)." },
|
||||||
|
{ "id": "b", "text": "`mke2fs -t xfs -L daten /dev/sdb2`", "correct": false, "explanation": "`mke2fs` legt nur ext2/3/4 an." },
|
||||||
|
{ "id": "c", "text": "`xfs_admin -L daten /dev/sdb2`", "correct": false, "explanation": "Ändert das Label eines **bestehenden** XFS; angelegt wird nichts." },
|
||||||
|
{ "id": "d", "text": "`mkfs -t xfs -l daten /dev/sdb2`", "correct": false, "explanation": "Kleines `-l` steht bei mkfs.xfs für Log-Optionen." },
|
||||||
|
{ "id": "e", "text": "`mount -t xfs -L daten /dev/sdb2`", "correct": false, "explanation": "`mount` legt keine Dateisysteme an." }
|
||||||
|
],
|
||||||
|
"explanation": "Labels lassen sich in fstab mit `LABEL=daten` nutzen. ext4: `e2label` bzw. `tune2fs -L`.",
|
||||||
|
"references": ["man 8 mkfs.xfs"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "104.1-005",
|
||||||
|
"objective": "104.1",
|
||||||
|
"type": "fill",
|
||||||
|
"difficulty": 1,
|
||||||
|
"question": "Mit welchem Befehl (mit Argument) aktiviert man den bereits initialisierten Swap-Bereich `/dev/sdc2`?",
|
||||||
|
"answers": ["swapon /dev/sdc2"],
|
||||||
|
"explanation": "Deaktivieren: `swapoff /dev/sdc2`; aktive Bereiche: `swapon --show`.",
|
||||||
|
"references": ["man 8 swapon"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "104.1-006",
|
||||||
|
"objective": "104.1",
|
||||||
|
"type": "single",
|
||||||
|
"difficulty": 2,
|
||||||
|
"question": "Ein USB-Stick soll unter Windows, macOS und Linux nutzbar sein und Dateien **größer als 4 GiB** speichern. Welches Dateisystem passt?",
|
||||||
|
"options": [
|
||||||
|
{ "id": "a", "text": "exFAT", "correct": true, "explanation": "Breit unterstützt und ohne 4-GiB-Grenze je Datei." },
|
||||||
|
{ "id": "b", "text": "VFAT (FAT32)", "correct": false, "explanation": "Breit unterstützt, aber Dateien sind auf knapp 4 GiB begrenzt." },
|
||||||
|
{ "id": "c", "text": "ext4", "correct": false, "explanation": "Windows und macOS lesen ext4 ohne Zusatzsoftware nicht." },
|
||||||
|
{ "id": "d", "text": "XFS", "correct": false, "explanation": "Nur unter Linux nativ nutzbar." },
|
||||||
|
{ "id": "e", "text": "Btrfs", "correct": false, "explanation": "Nur unter Linux nativ nutzbar." }
|
||||||
|
],
|
||||||
|
"explanation": "Anlegen: `mkfs.exfat` bzw. `mkfs.vfat`. Im Objective genannt: ext2/3/4, XFS, VFAT, exFAT, Btrfs (Grundlagen).",
|
||||||
|
"references": ["man 8 mkfs.exfat"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "104.1-007",
|
||||||
|
"objective": "104.1",
|
||||||
|
"type": "multi",
|
||||||
|
"difficulty": 2,
|
||||||
|
"question": "Welche Merkmale bietet **Btrfs**?",
|
||||||
|
"options": [
|
||||||
|
{ "id": "a", "text": "Subvolumes", "correct": true, "explanation": "Eigenständig einhängbare Teilbäume innerhalb eines Dateisystems." },
|
||||||
|
{ "id": "b", "text": "Snapshots", "correct": true, "explanation": "Platzsparende Momentaufnahmen per Copy-on-Write." },
|
||||||
|
{ "id": "c", "text": "Es ist ausschließlich als Swap verwendbar.", "correct": false, "explanation": "Btrfs ist ein vollwertiges Dateisystem." },
|
||||||
|
{ "id": "d", "text": "Es hat keine Prüfsummen für Daten.", "correct": false, "explanation": "Btrfs prüft Daten und Metadaten mit Prüfsummen." },
|
||||||
|
{ "id": "e", "text": "Es ist auf 2 TB Größe begrenzt.", "correct": false, "explanation": "Btrfs unterstützt sehr große Dateisysteme." }
|
||||||
|
],
|
||||||
|
"explanation": "Weitere Merkmale: integrierte RAID-Funktionen, Kompression, Online-Vergrößerung.",
|
||||||
|
"references": ["man 5 btrfs"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "104.2-004",
|
||||||
|
"objective": "104.2",
|
||||||
|
"type": "single",
|
||||||
|
"difficulty": 2,
|
||||||
|
"question": "Ein ext4 auf `/dev/sdb1` soll nach spätestens 30 Einhängevorgängen beim Start automatisch geprüft werden. Welcher Befehl stellt das ein?",
|
||||||
|
"options": [
|
||||||
|
{ "id": "a", "text": "`tune2fs -c 30 /dev/sdb1`", "correct": true, "explanation": "`-c` setzt die maximale Mount-Anzahl bis zur Prüfung." },
|
||||||
|
{ "id": "b", "text": "`tune2fs -i 30 /dev/sdb1`", "correct": false, "explanation": "`-i` setzt ein Zeitintervall (z. B. `30d`)." },
|
||||||
|
{ "id": "c", "text": "`e2fsck -c 30 /dev/sdb1`", "correct": false, "explanation": "`e2fsck -c` sucht fehlerhafte Blöcke mit `badblocks`." },
|
||||||
|
{ "id": "d", "text": "`dumpe2fs -c 30 /dev/sdb1`", "correct": false, "explanation": "`dumpe2fs` zeigt nur Informationen an." },
|
||||||
|
{ "id": "e", "text": "`mkfs.ext4 -c 30 /dev/sdb1`", "correct": false, "explanation": "Würde ein neues Dateisystem anlegen und alle Daten löschen." }
|
||||||
|
],
|
||||||
|
"explanation": "Aktuelle Werte: `tune2fs -l /dev/sdb1 | grep -i mount`.",
|
||||||
|
"references": ["man 8 tune2fs"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "104.2-005",
|
||||||
|
"objective": "104.2",
|
||||||
|
"type": "fill",
|
||||||
|
"difficulty": 1,
|
||||||
|
"question": "Welche `df`-Option (nur die Option) zeigt statt des Speicherplatzes die Belegung der **Inodes**?",
|
||||||
|
"answers": ["-i", "--inodes"],
|
||||||
|
"explanation": "Viele kleine Dateien können die Inodes erschöpfen, obwohl noch Platz frei ist.",
|
||||||
|
"references": ["man 1 df"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "104.2-006",
|
||||||
|
"objective": "104.2",
|
||||||
|
"type": "single",
|
||||||
|
"difficulty": 2,
|
||||||
|
"question": "Welcher Befehl zeigt die Superblock-Informationen eines ext4-Dateisystems an (z. B. Blockgröße, Mount-Zähler, Zustand)?",
|
||||||
|
"options": [
|
||||||
|
{ "id": "a", "text": "`dumpe2fs -h /dev/sdb1`", "correct": true, "explanation": "`-h` beschränkt die Ausgabe auf den Superblock; gleichwertig `tune2fs -l`." },
|
||||||
|
{ "id": "b", "text": "`xfs_info /dev/sdb1`", "correct": false, "explanation": "Für XFS-Dateisysteme." },
|
||||||
|
{ "id": "c", "text": "`blkid /dev/sdb1`", "correct": false, "explanation": "Zeigt nur UUID, Typ und Label." },
|
||||||
|
{ "id": "d", "text": "`fsck -N /dev/sdb1`", "correct": false, "explanation": "Zeigt nur, welcher Prüfbefehl ausgeführt würde." },
|
||||||
|
{ "id": "e", "text": "`du -s /dev/sdb1`", "correct": false, "explanation": "Zeigt die Größe der Gerätedatei, nicht des Dateisystems." }
|
||||||
|
],
|
||||||
|
"explanation": "`debugfs` erlaubt interaktive Untersuchung und Reparatur von ext-Dateisystemen – nur für Experten.",
|
||||||
|
"references": ["man 8 dumpe2fs"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "104.2-007",
|
||||||
|
"objective": "104.2",
|
||||||
|
"type": "multi",
|
||||||
|
"difficulty": 2,
|
||||||
|
"question": "Welche Aussagen zu `e2fsck` und `fsck` treffen zu?",
|
||||||
|
"options": [
|
||||||
|
{ "id": "a", "text": "`e2fsck -f` erzwingt eine Prüfung, auch wenn das Dateisystem als sauber markiert ist.", "correct": true, "explanation": "Ohne `-f` überspringt e2fsck saubere Dateisysteme." },
|
||||||
|
{ "id": "b", "text": "`e2fsck -n` prüft nur und beantwortet alle Fragen mit „nein“, ändert also nichts.", "correct": true, "explanation": "Sicherer Prüflauf; damit auch an lesend eingehängten Dateisystemen nutzbar." },
|
||||||
|
{ "id": "c", "text": "`fsck -A` prüft nur das Root-Dateisystem.", "correct": false, "explanation": "`-A` prüft alle Dateisysteme aus `/etc/fstab` (in der Reihenfolge des sechsten Felds)." },
|
||||||
|
{ "id": "d", "text": "`xfs_repair` darf auf einem eingehängten XFS laufen.", "correct": false, "explanation": "XFS muss ausgehängt sein; nur `-n` (Prüfung) geht eingeschränkt." },
|
||||||
|
{ "id": "e", "text": "`e2fsck -y` beantwortet alle Fragen mit „nein“.", "correct": false, "explanation": "`-y` beantwortet alle Fragen mit „ja“ und repariert automatisch." }
|
||||||
|
],
|
||||||
|
"explanation": "`-p` (preen) repariert automatisch nur gefahrlose Fehler – so laufen Prüfungen beim Start.",
|
||||||
|
"references": ["man 8 e2fsck", "man 8 fsck"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "104.3-005",
|
||||||
|
"objective": "104.3",
|
||||||
|
"type": "single",
|
||||||
|
"difficulty": 1,
|
||||||
|
"question": "Was bewirkt die Mount-Option `noexec`?",
|
||||||
|
"options": [
|
||||||
|
{ "id": "a", "text": "Programme auf diesem Dateisystem können nicht direkt ausgeführt werden.", "correct": true, "explanation": "Das Ausführungsrecht wird ignoriert – nützlich z. B. für `/tmp` oder Wechselmedien." },
|
||||||
|
{ "id": "b", "text": "Das Dateisystem wird nur lesend eingehängt.", "correct": false, "explanation": "Das ist `ro`." },
|
||||||
|
{ "id": "c", "text": "SUID-Bits werden ignoriert.", "correct": false, "explanation": "Das ist `nosuid`." },
|
||||||
|
{ "id": "d", "text": "Gerätedateien werden nicht ausgewertet.", "correct": false, "explanation": "Das ist `nodev`." },
|
||||||
|
{ "id": "e", "text": "Das Dateisystem wird beim Start nicht eingehängt.", "correct": false, "explanation": "Das ist `noauto`." }
|
||||||
|
],
|
||||||
|
"explanation": "`defaults` steht für `rw,suid,dev,exec,auto,nouser,async`.",
|
||||||
|
"references": ["man 8 mount"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "104.3-006",
|
||||||
|
"objective": "104.3",
|
||||||
|
"type": "fill",
|
||||||
|
"difficulty": 1,
|
||||||
|
"question": "Welche Option im vierten Feld von `/etc/fstab` verhindert, dass ein Dateisystem beim Start bzw. mit `mount -a` automatisch eingehängt wird?",
|
||||||
|
"answers": ["noauto"],
|
||||||
|
"explanation": "Typisch für Wechselmedien; manuell mit `mount /mnt/usb` einhängen, da der Eintrag bekannt ist.",
|
||||||
|
"references": ["man 5 fstab"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "104.3-007",
|
||||||
|
"objective": "104.3",
|
||||||
|
"type": "single",
|
||||||
|
"difficulty": 2,
|
||||||
|
"question": "Wie hängt man das Root-Dateisystem im laufenden Betrieb **nur lesend** neu ein?",
|
||||||
|
"options": [
|
||||||
|
{ "id": "a", "text": "`mount -o remount,ro /`", "correct": true, "explanation": "`remount` ändert Optionen, ohne auszuhängen." },
|
||||||
|
{ "id": "b", "text": "`umount / && mount -r /`", "correct": false, "explanation": "Das Root-Dateisystem lässt sich im Betrieb nicht aushängen." },
|
||||||
|
{ "id": "c", "text": "`mount -a -o ro`", "correct": false, "explanation": "Hängt die noch nicht eingehängten fstab-Einträge ein." },
|
||||||
|
{ "id": "d", "text": "`chmod -R a-w /`", "correct": false, "explanation": "Ändert Rechte aller Dateien – schwerwiegend und nicht gemeint." },
|
||||||
|
{ "id": "e", "text": "`fsck -r /`", "correct": false, "explanation": "`fsck` hängt nichts ein." }
|
||||||
|
],
|
||||||
|
"explanation": "Umgekehrt im Rettungsmodus: `mount -o remount,rw /`, um Konfigurationen zu reparieren.",
|
||||||
|
"references": ["man 8 mount"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "104.3-008",
|
||||||
|
"objective": "104.3",
|
||||||
|
"type": "single",
|
||||||
|
"difficulty": 2,
|
||||||
|
"question": "Wie muss eine systemd-Mount-Unit heißen, die `/srv/backup` einhängt?",
|
||||||
|
"options": [
|
||||||
|
{ "id": "a", "text": "`srv-backup.mount`", "correct": true, "explanation": "Der Name leitet sich vom Pfad ab: führenden `/` weglassen, weitere `/` durch `-` ersetzen." },
|
||||||
|
{ "id": "b", "text": "`backup.mount`", "correct": false, "explanation": "Der Name muss dem vollständigen Pfad entsprechen." },
|
||||||
|
{ "id": "c", "text": "`srv/backup.mount`", "correct": false, "explanation": "Schrägstriche sind im Unit-Namen nicht erlaubt." },
|
||||||
|
{ "id": "d", "text": "`srv-backup.service`", "correct": false, "explanation": "Mount-Units haben die Endung `.mount`." },
|
||||||
|
{ "id": "e", "text": "`mount-srv-backup.target`", "correct": false, "explanation": "Targets gruppieren Units; einhängen tun sie nicht." }
|
||||||
|
],
|
||||||
|
"explanation": "Hilfe: `systemd-escape -p --suffix=mount /srv/backup`. Für Einträge in `/etc/fstab` erzeugt systemd solche Units automatisch.",
|
||||||
|
"references": ["man 5 systemd.mount"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "104.3-009",
|
||||||
|
"objective": "104.3",
|
||||||
|
"type": "multi",
|
||||||
|
"difficulty": 1,
|
||||||
|
"question": "Welche Aussagen zum Einhängen von Dateisystemen treffen zu?",
|
||||||
|
"options": [
|
||||||
|
{ "id": "a", "text": "Die fstab-Option `user` erlaubt normalen Benutzern, das Dateisystem einzuhängen.", "correct": true, "explanation": "Nur derselbe Benutzer darf es wieder aushängen (`users`: alle)." },
|
||||||
|
{ "id": "b", "text": "`findmnt` zeigt die eingehängten Dateisysteme als Baum.", "correct": true, "explanation": "Mit Quelle, Ziel, Typ und Optionen." },
|
||||||
|
{ "id": "c", "text": "`umount` akzeptiert nur den Gerätenamen, nicht den Einhängepunkt.", "correct": false, "explanation": "Beides funktioniert: `umount /dev/sdb1` oder `umount /mnt/daten`." },
|
||||||
|
{ "id": "d", "text": "`defaults` enthält die Option `noexec`.", "correct": false, "explanation": "`defaults` enthält `exec`." },
|
||||||
|
{ "id": "e", "text": "`mount` ohne Argumente hängt alle Dateisysteme aus.", "correct": false, "explanation": "Es listet die eingehängten Dateisysteme." }
|
||||||
|
],
|
||||||
|
"explanation": "Aktuell eingehängte Dateisysteme stehen auch in `/proc/mounts` (bzw. `/proc/self/mounts`).",
|
||||||
|
"references": ["man 8 findmnt", "man 5 fstab"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "104.5-006",
|
||||||
|
"objective": "104.5",
|
||||||
|
"type": "single",
|
||||||
|
"difficulty": 1,
|
||||||
|
"question": "Was bedeutet das `t` am Ende von `drwxrwxrwt` beim Verzeichnis `/tmp`?",
|
||||||
|
"options": [
|
||||||
|
{ "id": "a", "text": "Sticky-Bit: Dateien darf nur ihr Eigentümer (bzw. der Verzeichniseigentümer oder root) löschen oder umbenennen.", "correct": true, "explanation": "Obwohl alle Schreibrecht haben, können sie fremde Dateien nicht löschen." },
|
||||||
|
{ "id": "b", "text": "Das Verzeichnis ist temporär und wird beim Neustart gelöscht.", "correct": false, "explanation": "Ob `/tmp` geleert wird, regelt die Distribution, nicht das `t`." },
|
||||||
|
{ "id": "c", "text": "Dateien im Verzeichnis erben die Gruppe des Verzeichnisses.", "correct": false, "explanation": "Das ist SGID auf Verzeichnissen." },
|
||||||
|
{ "id": "d", "text": "Programme im Verzeichnis laufen mit den Rechten des Eigentümers.", "correct": false, "explanation": "Das ist SUID bei Dateien." },
|
||||||
|
{ "id": "e", "text": "Das Verzeichnis ist ein symbolischer Link.", "correct": false, "explanation": "Links erkennt man am `l` am **Anfang**." }
|
||||||
|
],
|
||||||
|
"explanation": "Setzen: `chmod +t verzeichnis` bzw. oktal `1777`. Großes `T` heißt: Sticky gesetzt, aber kein x für andere.",
|
||||||
|
"references": ["man 1 chmod"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "104.5-007",
|
||||||
|
"objective": "104.5",
|
||||||
|
"type": "fill",
|
||||||
|
"difficulty": 1,
|
||||||
|
"question": "Geben Sie den `chmod`-Befehl in **symbolischer** Schreibweise ein, der „anderen“ (others) alle Rechte an `bericht.txt` entzieht.",
|
||||||
|
"answers": ["chmod o-rwx bericht.txt", "chmod o= bericht.txt", "chmod o-rxw bericht.txt", "chmod o-wrx bericht.txt", "chmod o-wxr bericht.txt", "chmod o-xrw bericht.txt", "chmod o-xwr bericht.txt"],
|
||||||
|
"explanation": "`u` Eigentümer, `g` Gruppe, `o` andere, `a` alle; `+` hinzufügen, `-` entfernen, `=` genau setzen.",
|
||||||
|
"references": ["man 1 chmod"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "104.5-008",
|
||||||
|
"objective": "104.5",
|
||||||
|
"type": "single",
|
||||||
|
"difficulty": 2,
|
||||||
|
"question": "Welche Wirkung hat das **SGID-Bit** auf einem Verzeichnis?",
|
||||||
|
"options": [
|
||||||
|
{ "id": "a", "text": "Neu angelegte Dateien und Unterverzeichnisse erhalten die Gruppe des Verzeichnisses.", "correct": true, "explanation": "Praktisch für gemeinsame Projektverzeichnisse." },
|
||||||
|
{ "id": "b", "text": "Nur der Eigentümer darf Dateien löschen.", "correct": false, "explanation": "Das ist das Sticky-Bit." },
|
||||||
|
{ "id": "c", "text": "Programme laufen mit den Rechten der Gruppe des Aufrufers.", "correct": false, "explanation": "Programme laufen normal ohnehin mit der Gruppe des Aufrufers; SGID auf Dateien setzt die Gruppe der **Datei**." },
|
||||||
|
{ "id": "d", "text": "Das Verzeichnis kann nicht gelöscht werden.", "correct": false, "explanation": "Dafür gibt es kein Rechtebit (nur das Attribut `chattr +i`)." },
|
||||||
|
{ "id": "e", "text": "Alle Benutzer werden Mitglied der Gruppe.", "correct": false, "explanation": "Rechtebits ändern keine Gruppenmitgliedschaften." }
|
||||||
|
],
|
||||||
|
"explanation": "Setzen: `chmod g+s verzeichnis`; in `ls -l` steht dann `s` an der x-Stelle der Gruppe.",
|
||||||
|
"references": ["man 1 chmod"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "104.5-009",
|
||||||
|
"objective": "104.5",
|
||||||
|
"type": "single",
|
||||||
|
"difficulty": 2,
|
||||||
|
"question": "Welche Rechte hat ein Verzeichnis nach `chmod 2770 projekt`?",
|
||||||
|
"options": [
|
||||||
|
{ "id": "a", "text": "`drwxrws---`", "correct": true, "explanation": "2 = SGID, 7 = rwx (Eigentümer), 7 = rwx (Gruppe, mit `s` für SGID), 0 = keine (andere)." },
|
||||||
|
{ "id": "b", "text": "`drwsrwx---`", "correct": false, "explanation": "`s` beim Eigentümer wäre SUID (4xxx)." },
|
||||||
|
{ "id": "c", "text": "`drwxrwx--T`", "correct": false, "explanation": "`T` wäre das Sticky-Bit (1xxx)." },
|
||||||
|
{ "id": "d", "text": "`d-w-rwxrwx`", "correct": false, "explanation": "Die führende 2 ist kein Rechtewert für den Eigentümer." },
|
||||||
|
{ "id": "e", "text": "`drwxr-x---`", "correct": false, "explanation": "Das wäre 750 ohne Sonderbit." }
|
||||||
|
],
|
||||||
|
"explanation": "Sonderbits als vierte Ziffer vorne: 4 SUID, 2 SGID, 1 Sticky, auch kombiniert (z. B. 3770).",
|
||||||
|
"references": ["man 1 chmod"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "104.5-010",
|
||||||
|
"objective": "104.5",
|
||||||
|
"type": "single",
|
||||||
|
"difficulty": 1,
|
||||||
|
"question": "Wie setzt man für `/srv/projekt` und **alles darin** den Eigentümer `anna` und die Gruppe `team`?",
|
||||||
|
"options": [
|
||||||
|
{ "id": "a", "text": "`chown -R anna:team /srv/projekt`", "correct": true, "explanation": "`-R` arbeitet rekursiv, `benutzer:gruppe` setzt beides." },
|
||||||
|
{ "id": "b", "text": "`chown anna:team /srv/projekt`", "correct": false, "explanation": "Ändert nur das Verzeichnis selbst, nicht den Inhalt." },
|
||||||
|
{ "id": "c", "text": "`chmod -R anna:team /srv/projekt`", "correct": false, "explanation": "`chmod` ändert Rechte, keine Eigentümer." },
|
||||||
|
{ "id": "d", "text": "`chgrp -R anna:team /srv/projekt`", "correct": false, "explanation": "`chgrp` setzt nur die Gruppe und erwartet nur einen Gruppennamen." },
|
||||||
|
{ "id": "e", "text": "`usermod -R team anna /srv/projekt`", "correct": false, "explanation": "`usermod` ändert Benutzerkonten." }
|
||||||
|
],
|
||||||
|
"explanation": "Den Eigentümer ändern darf nur root.",
|
||||||
|
"references": ["man 1 chown"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "104.5-011",
|
||||||
|
"objective": "104.5",
|
||||||
|
"type": "multi",
|
||||||
|
"difficulty": 2,
|
||||||
|
"question": "Welche Aussagen zu Rechten an **Verzeichnissen** treffen zu?",
|
||||||
|
"options": [
|
||||||
|
{ "id": "a", "text": "Das x-Recht erlaubt, das Verzeichnis zu betreten und auf Einträge darin zuzugreifen.", "correct": true, "explanation": "Ohne x kein `cd` und kein Zugriff auf Dateien darin, auch wenn ihr Name bekannt ist." },
|
||||||
|
{ "id": "b", "text": "Das w-Recht (zusammen mit x) erlaubt, Dateien darin anzulegen, umzubenennen und zu löschen.", "correct": true, "explanation": "Löschen ist eine Änderung des Verzeichnisses." },
|
||||||
|
{ "id": "c", "text": "Das r-Recht allein erlaubt, den Inhalt der Dateien zu lesen.", "correct": false, "explanation": "r am Verzeichnis erlaubt nur, die Namen aufzulisten; Dateiinhalt hängt von den Dateirechten (und x am Verzeichnis) ab." },
|
||||||
|
{ "id": "d", "text": "Zum Löschen einer Datei braucht man Schreibrecht an der Datei selbst.", "correct": false, "explanation": "Entscheidend ist das Schreibrecht am Verzeichnis (Ausnahme: Sticky-Bit)." },
|
||||||
|
{ "id": "e", "text": "Die umask ändert auch die Rechte bereits bestehender Dateien.", "correct": false, "explanation": "Die umask wirkt nur beim Anlegen neuer Dateien." }
|
||||||
|
],
|
||||||
|
"explanation": "Üblich: Verzeichnisse 755 bzw. 750, Dateien 644 bzw. 640.",
|
||||||
|
"references": ["man 7 inode", "man 1 chmod"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "104.6-004",
|
||||||
|
"objective": "104.6",
|
||||||
|
"type": "single",
|
||||||
|
"difficulty": 1,
|
||||||
|
"question": "Was passiert mit einem symbolischen Link, wenn seine Zieldatei gelöscht wird?",
|
||||||
|
"options": [
|
||||||
|
{ "id": "a", "text": "Der Link bleibt bestehen, zeigt aber ins Leere (verwaister Link).", "correct": true, "explanation": "Ein Symlink speichert nur den Pfad; Zugriffe melden „No such file or directory“." },
|
||||||
|
{ "id": "b", "text": "Der Link wird automatisch mitgelöscht.", "correct": false, "explanation": "Linux entfernt Symlinks nicht automatisch." },
|
||||||
|
{ "id": "c", "text": "Der Link enthält weiterhin den Dateiinhalt.", "correct": false, "explanation": "So verhält sich ein Hardlink, kein Symlink." },
|
||||||
|
{ "id": "d", "text": "Der Link wird zu einem Hardlink.", "correct": false, "explanation": "Der Link-Typ ändert sich nie." },
|
||||||
|
{ "id": "e", "text": "Das Löschen schlägt fehl, solange ein Link existiert.", "correct": false, "explanation": "Symlinks verhindern das Löschen nicht." }
|
||||||
|
],
|
||||||
|
"explanation": "Verwaiste Links finden: `find /pfad -xtype l`.",
|
||||||
|
"references": ["man 7 symlink"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "104.6-005",
|
||||||
|
"objective": "104.6",
|
||||||
|
"type": "fill",
|
||||||
|
"difficulty": 1,
|
||||||
|
"question": "Welcher Befehl (nur der Name) gibt das Ziel eines symbolischen Links aus?",
|
||||||
|
"answers": ["readlink"],
|
||||||
|
"explanation": "`readlink -f` löst die ganze Kette auf und gibt den absoluten Pfad aus. Auch `ls -l` zeigt `link -> ziel`.",
|
||||||
|
"references": ["man 1 readlink"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "104.6-006",
|
||||||
|
"objective": "104.6",
|
||||||
|
"type": "multi",
|
||||||
|
"difficulty": 2,
|
||||||
|
"question": "Welche Aussagen über **symbolische** Links treffen zu?",
|
||||||
|
"options": [
|
||||||
|
{ "id": "a", "text": "Symbolische Links können auf Dateien in anderen Dateisystemen zeigen.", "correct": true, "explanation": "Sie speichern nur einen Pfad." },
|
||||||
|
{ "id": "b", "text": "`ls -l` zeigt bei einem Symlink ein `l` als erstes Zeichen.", "correct": true, "explanation": "z. B. `lrwxrwxrwx … aktuell -> release-2.4`." },
|
||||||
|
{ "id": "c", "text": "Ein Symlink teilt sich den Inode mit seinem Ziel.", "correct": false, "explanation": "Das gilt für Hardlinks; ein Symlink hat einen eigenen Inode." },
|
||||||
|
{ "id": "d", "text": "Löscht man den Symlink, wird auch das Ziel gelöscht.", "correct": false, "explanation": "`rm link` entfernt nur den Link." },
|
||||||
|
{ "id": "e", "text": "Symlinks können nicht auf Verzeichnisse zeigen.", "correct": false, "explanation": "Symlinks auf Verzeichnisse sind üblich (z. B. `/bin -> usr/bin`)." }
|
||||||
|
],
|
||||||
|
"explanation": "Relative Symlinks (`ln -s ../ziel link`) gelten relativ zum Ort des Links, nicht zum aktuellen Verzeichnis.",
|
||||||
|
"references": ["man 7 symlink"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "104.7-004",
|
||||||
|
"objective": "104.7",
|
||||||
|
"type": "single",
|
||||||
|
"difficulty": 1,
|
||||||
|
"question": "Wohin gehört laut FHS ein eigenständiges **Zusatz-Softwarepaket** eines Drittanbieters?",
|
||||||
|
"options": [
|
||||||
|
{ "id": "a", "text": "`/opt`", "correct": true, "explanation": "Je Paket ein Unterverzeichnis, z. B. `/opt/<anbieter>/`." },
|
||||||
|
{ "id": "b", "text": "`/srv`", "correct": false, "explanation": "Für Daten, die der Rechner als Dienst ausliefert." },
|
||||||
|
{ "id": "c", "text": "`/var/lib`", "correct": false, "explanation": "Für Zustandsdaten von Programmen." },
|
||||||
|
{ "id": "d", "text": "`/etc`", "correct": false, "explanation": "Nur für Konfiguration." },
|
||||||
|
{ "id": "e", "text": "`/boot`", "correct": false, "explanation": "Nur für Bootloader, Kernel und initramfs." }
|
||||||
|
],
|
||||||
|
"explanation": "Selbst kompilierte Software installiert man üblicherweise unter `/usr/local` (bin, lib, share).",
|
||||||
|
"references": ["man 7 hier"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "104.7-005",
|
||||||
|
"objective": "104.7",
|
||||||
|
"type": "fill",
|
||||||
|
"difficulty": 2,
|
||||||
|
"question": "In welchem Verzeichnis liegen laut FHS temporäre Dateien, die einen **Neustart überdauern** sollen? (Pfad)",
|
||||||
|
"answers": ["/var/tmp"],
|
||||||
|
"explanation": "`/tmp` darf beim Start geleert werden (oft tmpfs im RAM), `/var/tmp` bleibt erhalten.",
|
||||||
|
"references": ["man 7 hier"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "104.7-006",
|
||||||
|
"objective": "104.7",
|
||||||
|
"type": "multi",
|
||||||
|
"difficulty": 1,
|
||||||
|
"question": "Welche Aussagen zum Filesystem Hierarchy Standard treffen zu?",
|
||||||
|
"options": [
|
||||||
|
{ "id": "a", "text": "`/usr` enthält weitgehend statische Daten und kann schreibgeschützt eingehängt werden.", "correct": true, "explanation": "Programme, Bibliotheken, Dokumentation – nicht hostspezifisch." },
|
||||||
|
{ "id": "b", "text": "`/home` enthält die Home-Verzeichnisse der Benutzer.", "correct": true, "explanation": "Das Home von root liegt dagegen in `/root`." },
|
||||||
|
{ "id": "c", "text": "`/proc` enthält die Konfigurationsdateien der Dienste.", "correct": false, "explanation": "`/proc` ist ein virtuelles Dateisystem mit Prozess- und Kernelinformationen." },
|
||||||
|
{ "id": "d", "text": "`/sbin` ist für Programme normaler Benutzer gedacht.", "correct": false, "explanation": "`/sbin` enthält Systemprogramme für die Administration." },
|
||||||
|
{ "id": "e", "text": "`/dev` enthält den Quellcode der Gerätetreiber.", "correct": false, "explanation": "`/dev` enthält Gerätedateien." }
|
||||||
|
],
|
||||||
|
"explanation": "Kurzüberblick: `man 7 hier` bzw. `man 7 file-hierarchy` (systemd).",
|
||||||
|
"references": ["man 7 hier"]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -0,0 +1,221 @@
|
|||||||
|
{
|
||||||
|
"$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"]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -0,0 +1,137 @@
|
|||||||
|
{
|
||||||
|
"$schema": "../schema/questions.schema.json",
|
||||||
|
"format": "lpic-sim-questions",
|
||||||
|
"meta": {
|
||||||
|
"file": "questions_106_set2.json",
|
||||||
|
"brief": "Zweiter Fragensatz zu Topic 106 Benutzerschnittstellen und Desktops (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": "106.1-004",
|
||||||
|
"objective": "106.1",
|
||||||
|
"type": "single",
|
||||||
|
"difficulty": 2,
|
||||||
|
"question": "Mit welchem Befehl erlaubt man einem bestimmten entfernten Rechner **hostbasiert** den Zugriff auf den lokalen X-Server?",
|
||||||
|
"options": [
|
||||||
|
{ "id": "a", "text": "`xhost +192.0.2.20`", "correct": true, "explanation": "`xhost +<host>` fügt den Host der Zugriffsliste hinzu; `xhost -<host>` entfernt ihn." },
|
||||||
|
{ "id": "b", "text": "`xauth add 192.0.2.20`", "correct": false, "explanation": "`xauth` verwaltet Cookies (MIT-MAGIC-COOKIE), nicht hostbasierte Freigaben." },
|
||||||
|
{ "id": "c", "text": "`xdpyinfo 192.0.2.20`", "correct": false, "explanation": "`xdpyinfo` zeigt Informationen über einen X-Server an." },
|
||||||
|
{ "id": "d", "text": "`xrandr --allow 192.0.2.20`", "correct": false, "explanation": "`xrandr` stellt Bildschirmauflösung und -anordnung ein." },
|
||||||
|
{ "id": "e", "text": "`startx 192.0.2.20`", "correct": false, "explanation": "`startx` startet einen X-Server mit Sitzung." }
|
||||||
|
],
|
||||||
|
"explanation": "`xhost +` ohne Host schaltet die Zugriffskontrolle ganz ab – unsicher. Besser: X-Weiterleitung über SSH (`ssh -X`).",
|
||||||
|
"references": ["man 1 xhost"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "106.1-005",
|
||||||
|
"objective": "106.1",
|
||||||
|
"type": "fill",
|
||||||
|
"difficulty": 2,
|
||||||
|
"question": "In welcher Datei (vollständiger Pfad, klassischer Ablageort) protokolliert der erste Xorg-Server (Display `:0`) seinen Start und erkannte Hardware?",
|
||||||
|
"answers": ["/var/log/Xorg.0.log"],
|
||||||
|
"explanation": "Fehlerzeilen sind mit `(EE)`, Warnungen mit `(WW)` markiert. Läuft Xorg ohne Root-Rechte, liegt das Log oft unter `~/.local/share/xorg/Xorg.0.log`.",
|
||||||
|
"references": ["man 1 Xorg"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "106.1-006",
|
||||||
|
"objective": "106.1",
|
||||||
|
"type": "single",
|
||||||
|
"difficulty": 1,
|
||||||
|
"question": "Welches Programm zeigt Informationen über den laufenden X-Server an, z. B. Auflösung, Farbtiefe und unterstützte Erweiterungen?",
|
||||||
|
"options": [
|
||||||
|
{ "id": "a", "text": "`xdpyinfo`", "correct": true, "explanation": "display info: Server-Version, Bildschirme, Erweiterungen." },
|
||||||
|
{ "id": "b", "text": "`xwininfo`", "correct": false, "explanation": "`xwininfo` zeigt Informationen zu einem einzelnen Fenster." },
|
||||||
|
{ "id": "c", "text": "`xhost`", "correct": false, "explanation": "`xhost` verwaltet die hostbasierte Zugriffskontrolle." },
|
||||||
|
{ "id": "d", "text": "`xinit`", "correct": false, "explanation": "`xinit` startet einen X-Server und erste Clients." },
|
||||||
|
{ "id": "e", "text": "`xauth`", "correct": false, "explanation": "`xauth` verwaltet Zugriffs-Cookies." }
|
||||||
|
],
|
||||||
|
"explanation": "Weitere X-Werkzeuge aus 106.1: `xwininfo`, `xdpyinfo`, `xhost`, `xauth`, `xrandr`.",
|
||||||
|
"references": ["man 1 xdpyinfo"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "106.1-007",
|
||||||
|
"objective": "106.1",
|
||||||
|
"type": "multi",
|
||||||
|
"difficulty": 2,
|
||||||
|
"question": "Welche Aussagen zur X11-Weiterleitung über SSH treffen zu?",
|
||||||
|
"options": [
|
||||||
|
{ "id": "a", "text": "Mit `ssh -X benutzer@server` erscheinen dort gestartete X-Programme auf dem lokalen Bildschirm.", "correct": true, "explanation": "ssh setzt auf dem Server `DISPLAY` (z. B. `localhost:10.0`) und tunnelt die Verbindung." },
|
||||||
|
{ "id": "b", "text": "Der SSH-Server muss `X11Forwarding yes` in `sshd_config` erlauben.", "correct": true, "explanation": "Ohne diese Einstellung lehnt sshd die Weiterleitung ab." },
|
||||||
|
{ "id": "c", "text": "Auf dem Client muss vorher `xhost +` ausgeführt werden.", "correct": false, "explanation": "Nicht nötig – ssh regelt die Authentifizierung per Cookie; `xhost +` wäre unsicher." },
|
||||||
|
{ "id": "d", "text": "Man muss auf dem Server `DISPLAY=:0` setzen.", "correct": false, "explanation": "`:0` wäre der lokale Bildschirm des Servers; ssh setzt `DISPLAY` selbst." },
|
||||||
|
{ "id": "e", "text": "X11-Weiterleitung funktioniert nur über unverschlüsselte Verbindungen.", "correct": false, "explanation": "Gerade der Vorteil: Der X-Verkehr läuft verschlüsselt im SSH-Tunnel." }
|
||||||
|
],
|
||||||
|
"explanation": "`ssh -Y` ist „trusted“ X11-Forwarding mit weniger Einschränkungen durch die X-Security-Extension.",
|
||||||
|
"references": ["man 1 ssh", "man 5 sshd_config"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "106.2-003",
|
||||||
|
"objective": "106.2",
|
||||||
|
"type": "single",
|
||||||
|
"difficulty": 1,
|
||||||
|
"question": "Welche Komponente zeigt die grafische Anmeldemaske an und startet nach erfolgreicher Anmeldung die Desktop-Sitzung?",
|
||||||
|
"options": [
|
||||||
|
{ "id": "a", "text": "Der Display-Manager (z. B. GDM, SDDM, LightDM)", "correct": true, "explanation": "Display-Manager übernehmen Anmeldung und Sitzungsstart." },
|
||||||
|
{ "id": "b", "text": "Der Fenstermanager", "correct": false, "explanation": "Er platziert und dekoriert Fenster innerhalb einer laufenden Sitzung." },
|
||||||
|
{ "id": "c", "text": "Der Terminal-Emulator", "correct": false, "explanation": "Er stellt eine Shell in einem Fenster bereit." },
|
||||||
|
{ "id": "d", "text": "Der Dateimanager", "correct": false, "explanation": "Er verwaltet Dateien innerhalb der Sitzung." },
|
||||||
|
{ "id": "e", "text": "Der Druckdienst CUPS", "correct": false, "explanation": "CUPS verwaltet Drucker." }
|
||||||
|
],
|
||||||
|
"explanation": "Ohne Display-Manager startet man X z. B. nach Textanmeldung mit `startx`.",
|
||||||
|
"references": ["LPI 102-500 Objective 106.2"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "106.2-004",
|
||||||
|
"objective": "106.2",
|
||||||
|
"type": "single",
|
||||||
|
"difficulty": 2,
|
||||||
|
"question": "Welche Aussage zu XDMCP trifft zu?",
|
||||||
|
"options": [
|
||||||
|
{ "id": "a", "text": "Die Verbindung ist unverschlüsselt; XDMCP sollte nur in vertrauenswürdigen Netzen oder über einen Tunnel genutzt werden.", "correct": true, "explanation": "XDMCP und das anschließende X-Protokoll übertragen alles im Klartext." },
|
||||||
|
{ "id": "b", "text": "XDMCP verschlüsselt per TLS.", "correct": false, "explanation": "XDMCP bietet keine Verschlüsselung." },
|
||||||
|
{ "id": "c", "text": "XDMCP verwendet TCP-Port 3389.", "correct": false, "explanation": "3389 ist RDP; XDMCP nutzt UDP-Port 177." },
|
||||||
|
{ "id": "d", "text": "XDMCP ist das Protokoll von VNC.", "correct": false, "explanation": "VNC nutzt RFB." },
|
||||||
|
{ "id": "e", "text": "XDMCP funktioniert nur mit Wayland.", "correct": false, "explanation": "XDMCP gehört zum X Window System." }
|
||||||
|
],
|
||||||
|
"explanation": "XDMCP vermittelt eine Anmeldung am Display-Manager eines entfernten Rechners; die Sitzung läuft dann dort, die Anzeige lokal.",
|
||||||
|
"references": ["LPI 102-500 Objective 106.2"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "106.3-003",
|
||||||
|
"objective": "106.3",
|
||||||
|
"type": "single",
|
||||||
|
"difficulty": 1,
|
||||||
|
"question": "Welche Hilfsfunktion vergrößert einen Ausschnitt des Bildschirms für Menschen mit eingeschränktem Sehvermögen?",
|
||||||
|
"options": [
|
||||||
|
{ "id": "a", "text": "Bildschirmlupe", "correct": true, "explanation": "Vergrößert den Bereich um Mauszeiger oder Fokus." },
|
||||||
|
{ "id": "b", "text": "Bildschirmleser", "correct": false, "explanation": "Liest Inhalte vor bzw. gibt sie auf einer Braillezeile aus, vergrößert aber nicht." },
|
||||||
|
{ "id": "c", "text": "Langsame Tasten", "correct": false, "explanation": "Eine Tastaturhilfe gegen versehentliche Anschläge." },
|
||||||
|
{ "id": "d", "text": "Springende Tasten", "correct": false, "explanation": "Ignoriert schnell wiederholte Anschläge." },
|
||||||
|
{ "id": "e", "text": "Maustasten", "correct": false, "explanation": "Steuert den Mauszeiger über den Ziffernblock." }
|
||||||
|
],
|
||||||
|
"explanation": "Für eingeschränktes Sehen: Lupe, große Schriften, Hochkontrast. Für Blinde: Bildschirmleser, Braillezeile.",
|
||||||
|
"references": ["LPI 102-500 Objective 106.3"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "106.3-004",
|
||||||
|
"objective": "106.3",
|
||||||
|
"type": "multi",
|
||||||
|
"difficulty": 1,
|
||||||
|
"question": "Welche Hilfstechnologien richten sich vor allem an **blinde** Nutzer?",
|
||||||
|
"options": [
|
||||||
|
{ "id": "a", "text": "Braillezeile", "correct": true, "explanation": "Gibt Text als ertastbare Punktschrift aus." },
|
||||||
|
{ "id": "b", "text": "Bildschirmleser (z. B. Orca)", "correct": true, "explanation": "Liest Inhalte per Sprachsynthese vor." },
|
||||||
|
{ "id": "c", "text": "Hochkontrast-Theme", "correct": false, "explanation": "Hilft bei eingeschränktem Sehvermögen, nicht bei Blindheit." },
|
||||||
|
{ "id": "d", "text": "Bildschirmtastatur", "correct": false, "explanation": "Hilft bei motorischen Einschränkungen." },
|
||||||
|
{ "id": "e", "text": "Maustasten", "correct": false, "explanation": "Hilft bei motorischen Einschränkungen." }
|
||||||
|
],
|
||||||
|
"explanation": "Barrierefreiheit unterscheidet Seh-, Hör- und motorische Einschränkungen; die Hilfen sind entsprechend verschieden.",
|
||||||
|
"references": ["LPI 102-500 Objective 106.3"]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -0,0 +1,337 @@
|
|||||||
|
{
|
||||||
|
"$schema": "../schema/questions.schema.json",
|
||||||
|
"format": "lpic-sim-questions",
|
||||||
|
"meta": {
|
||||||
|
"file": "questions_107_set2.json",
|
||||||
|
"brief": "Zweiter Fragensatz zu Topic 107 Administrative Aufgaben (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": "107.1-009",
|
||||||
|
"objective": "107.1",
|
||||||
|
"type": "single",
|
||||||
|
"difficulty": 1,
|
||||||
|
"question": "Welcher Eintrag in `/etc/group` ist korrekt aufgebaut?",
|
||||||
|
"options": [
|
||||||
|
{ "id": "a", "text": "`docker:x:998:anna,bob`", "correct": true, "explanation": "Name, Passwortplatzhalter, GID, Mitglieder durch Komma getrennt." },
|
||||||
|
{ "id": "b", "text": "`docker:998:anna,bob`", "correct": false, "explanation": "Es fehlt das Passwortfeld; die Datei hat vier Felder." },
|
||||||
|
{ "id": "c", "text": "`docker:x:998:anna bob`", "correct": false, "explanation": "Mitglieder werden durch Kommas getrennt, nicht durch Leerzeichen." },
|
||||||
|
{ "id": "d", "text": "`998:docker:x:anna,bob`", "correct": false, "explanation": "Der Gruppenname steht im ersten Feld, die GID im dritten." },
|
||||||
|
{ "id": "e", "text": "`docker:x:anna,bob:998`", "correct": false, "explanation": "Die GID steht vor der Mitgliederliste." }
|
||||||
|
],
|
||||||
|
"explanation": "In der Mitgliederliste stehen nur Zusatzmitglieder; wer die Gruppe als primäre Gruppe hat, steht über die GID in `/etc/passwd`.",
|
||||||
|
"references": ["man 5 group"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "107.1-010",
|
||||||
|
"objective": "107.1",
|
||||||
|
"type": "fill",
|
||||||
|
"difficulty": 1,
|
||||||
|
"question": "Welcher Befehl (mit Argument) zeigt UID, primäre GID und alle Gruppen des Benutzers `anna`?",
|
||||||
|
"answers": ["id anna"],
|
||||||
|
"explanation": "Ausgabe z. B. `uid=1001(anna) gid=1001(anna) groups=1001(anna),998(docker)`. `groups anna` zeigt nur die Gruppennamen.",
|
||||||
|
"references": ["man 1 id"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "107.1-011",
|
||||||
|
"objective": "107.1",
|
||||||
|
"type": "single",
|
||||||
|
"difficulty": 1,
|
||||||
|
"question": "Wie legt man die Gruppe `projekt` mit der GID 1500 an?",
|
||||||
|
"options": [
|
||||||
|
{ "id": "a", "text": "`groupadd -g 1500 projekt`", "correct": true, "explanation": "`-g` legt die GID fest." },
|
||||||
|
{ "id": "b", "text": "`groupadd projekt 1500`", "correct": false, "explanation": "`groupadd` erwartet nur den Gruppennamen als Argument." },
|
||||||
|
{ "id": "c", "text": "`groupmod -g 1500 projekt`", "correct": false, "explanation": "`groupmod` ändert eine **bestehende** Gruppe." },
|
||||||
|
{ "id": "d", "text": "`newgrp -g 1500 projekt`", "correct": false, "explanation": "`newgrp` wechselt die aktive Gruppe der Shell." },
|
||||||
|
{ "id": "e", "text": "`useradd -g 1500 projekt`", "correct": false, "explanation": "Legt einen **Benutzer** `projekt` mit primärer Gruppe 1500 an." }
|
||||||
|
],
|
||||||
|
"explanation": "Systemgruppen: `groupadd -r`. Umbenennen: `groupmod -n neu alt`.",
|
||||||
|
"references": ["man 8 groupadd"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "107.1-012",
|
||||||
|
"objective": "107.1",
|
||||||
|
"type": "single",
|
||||||
|
"difficulty": 2,
|
||||||
|
"question": "Das Konto `backup` soll für Dienste und Dateibesitz erhalten bleiben, aber **keine interaktive Anmeldung** mehr erlauben. Was ist geeignet?",
|
||||||
|
"options": [
|
||||||
|
{ "id": "a", "text": "`usermod -s /usr/sbin/nologin backup`", "correct": true, "explanation": "Bei der Anmeldung startet `nologin`, gibt eine Meldung aus und beendet sich." },
|
||||||
|
{ "id": "b", "text": "`userdel backup`", "correct": false, "explanation": "Löscht das Konto; Dateien gehören danach einer „verwaisten“ UID." },
|
||||||
|
{ "id": "c", "text": "`passwd -d backup`", "correct": false, "explanation": "Löscht das Passwort – je nach Konfiguration wird die Anmeldung damit sogar einfacher." },
|
||||||
|
{ "id": "d", "text": "`usermod -G nologin backup`", "correct": false, "explanation": "Setzt die Zusatzgruppe `nologin`, die es normalerweise nicht gibt." },
|
||||||
|
{ "id": "e", "text": "`chage -M 0 backup`", "correct": false, "explanation": "Erzwingt nur eine sofortige Passwortänderung." }
|
||||||
|
],
|
||||||
|
"explanation": "Systemkonten erhalten typischerweise `/usr/sbin/nologin` oder `/bin/false` als Shell.",
|
||||||
|
"references": ["man 8 nologin", "man 8 usermod"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "107.1-013",
|
||||||
|
"objective": "107.1",
|
||||||
|
"type": "multi",
|
||||||
|
"difficulty": 1,
|
||||||
|
"question": "Mit welchen Befehlen ändert man die Login-Shell eines Benutzers?",
|
||||||
|
"options": [
|
||||||
|
{ "id": "a", "text": "`chsh -s /bin/zsh anna`", "correct": true, "explanation": "`chsh` ändert die Shell; normale Benutzer dürfen ihre eigene ändern (auf Shells aus `/etc/shells`)." },
|
||||||
|
{ "id": "b", "text": "`usermod -s /bin/zsh anna`", "correct": true, "explanation": "`usermod -s` setzt das siebte Feld in `/etc/passwd` (nur root)." },
|
||||||
|
{ "id": "c", "text": "`chfn -s /bin/zsh anna`", "correct": false, "explanation": "`chfn` ändert die GECOS-Angaben (Name, Telefon)." },
|
||||||
|
{ "id": "d", "text": "`usermod -c /bin/zsh anna`", "correct": false, "explanation": "`-c` setzt den Kommentar (GECOS)." },
|
||||||
|
{ "id": "e", "text": "`chage -s /bin/zsh anna`", "correct": false, "explanation": "`chage` verwaltet die Passwort-Alterung." }
|
||||||
|
],
|
||||||
|
"explanation": "`/etc/shells` listet die gültigen Login-Shells.",
|
||||||
|
"references": ["man 1 chsh"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "107.1-014",
|
||||||
|
"objective": "107.1",
|
||||||
|
"type": "single",
|
||||||
|
"difficulty": 2,
|
||||||
|
"question": "In welcher Datei stehen u. a. die UID-Bereiche für normale Benutzer (`UID_MIN`, `UID_MAX`) und Standardwerte der Passwort-Alterung (`PASS_MAX_DAYS`)?",
|
||||||
|
"options": [
|
||||||
|
{ "id": "a", "text": "`/etc/login.defs`", "correct": true, "explanation": "Sie gilt für `useradd`, `groupadd`, `passwd` und weitere Shadow-Werkzeuge." },
|
||||||
|
{ "id": "b", "text": "`/etc/default/useradd`", "correct": false, "explanation": "Enthält Vorgaben wie `SHELL`, `HOME`, `SKEL`, aber keine UID-Bereiche." },
|
||||||
|
{ "id": "c", "text": "`/etc/security/limits.conf`", "correct": false, "explanation": "Legt Ressourcenlimits pro Benutzer fest." },
|
||||||
|
{ "id": "d", "text": "`/etc/shells`", "correct": false, "explanation": "Listet erlaubte Login-Shells." },
|
||||||
|
{ "id": "e", "text": "`/etc/pam.d/passwd`", "correct": false, "explanation": "PAM-Konfiguration für das Programm `passwd`." }
|
||||||
|
],
|
||||||
|
"explanation": "Die Alterungswerte aus `login.defs` gelten nur für neu angelegte Konten; bestehende ändert man mit `chage`.",
|
||||||
|
"references": ["man 5 login.defs"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "107.1-015",
|
||||||
|
"objective": "107.1",
|
||||||
|
"type": "fill",
|
||||||
|
"difficulty": 1,
|
||||||
|
"question": "Welcher Befehl (mit Option und Benutzername) zeigt die Passwort-Alterungsdaten des Benutzers `anna` an?",
|
||||||
|
"answers": ["chage -l anna", "chage --list anna"],
|
||||||
|
"explanation": "Zeigt letzte Änderung, Ablauf von Passwort und Konto sowie Mindest-/Höchstdauer und Warnzeit.",
|
||||||
|
"references": ["man 1 chage"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "107.1-016",
|
||||||
|
"objective": "107.1",
|
||||||
|
"type": "single",
|
||||||
|
"difficulty": 1,
|
||||||
|
"question": "Welche Datei enthält Gruppenpasswörter und die Gruppenadministratoren?",
|
||||||
|
"options": [
|
||||||
|
{ "id": "a", "text": "`/etc/gshadow`", "correct": true, "explanation": "Felder: Name, Passwort, Administratoren, Mitglieder; nur für root lesbar." },
|
||||||
|
{ "id": "b", "text": "`/etc/group`", "correct": false, "explanation": "Enthält GID und Mitglieder, im Passwortfeld nur `x`." },
|
||||||
|
{ "id": "c", "text": "`/etc/shadow`", "correct": false, "explanation": "Enthält die Passwörter der **Benutzer**." },
|
||||||
|
{ "id": "d", "text": "`/etc/sudoers`", "correct": false, "explanation": "Regelt sudo-Berechtigungen." },
|
||||||
|
{ "id": "e", "text": "`/etc/groups`", "correct": false, "explanation": "Diese Datei gibt es nicht." }
|
||||||
|
],
|
||||||
|
"explanation": "Gruppenadministratoren verwalten Mitglieder mit `gpasswd -a/-d`. Gruppenpasswörter werden kaum noch genutzt.",
|
||||||
|
"references": ["man 5 gshadow", "man 1 gpasswd"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "107.1-017",
|
||||||
|
"objective": "107.1",
|
||||||
|
"type": "multi",
|
||||||
|
"difficulty": 2,
|
||||||
|
"question": "Was geschieht bei `userdel anna` **ohne** weitere Optionen?",
|
||||||
|
"options": [
|
||||||
|
{ "id": "a", "text": "Die Einträge von `anna` in `/etc/passwd` und `/etc/shadow` werden entfernt.", "correct": true, "explanation": "Das Konto selbst wird gelöscht." },
|
||||||
|
{ "id": "b", "text": "Das Home-Verzeichnis `/home/anna` bleibt erhalten.", "correct": true, "explanation": "Erst `-r` entfernt Home-Verzeichnis und Mail-Spool." },
|
||||||
|
{ "id": "c", "text": "Alle Dateien von `anna` im gesamten System werden gelöscht.", "correct": false, "explanation": "Dateien außerhalb des Homes bleiben immer erhalten – mit `find / -nouser` findet man sie." },
|
||||||
|
{ "id": "d", "text": "Laufende Prozesse von `anna` werden automatisch beendet.", "correct": false, "explanation": "`userdel` verweigert das Löschen, solange der Benutzer angemeldet ist (`-f` erzwingt)." },
|
||||||
|
{ "id": "e", "text": "Die gleichnamige private Gruppe bleibt in jedem Fall bestehen.", "correct": false, "explanation": "Mit `USERGROUPS_ENAB yes` wird sie mitgelöscht, sofern sie nicht anderweitig genutzt wird." }
|
||||||
|
],
|
||||||
|
"explanation": "Vor dem Löschen eines Kontos Dateien sichern oder neu zuordnen; verwaiste Dateien zeigen `find / -nouser -o -nogroup`.",
|
||||||
|
"references": ["man 8 userdel"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "107.2-007",
|
||||||
|
"objective": "107.2",
|
||||||
|
"type": "single",
|
||||||
|
"difficulty": 1,
|
||||||
|
"question": "Welche crontab-Kurzschreibweise führt einen Befehl einmal nach **jedem Systemstart** aus?",
|
||||||
|
"options": [
|
||||||
|
{ "id": "a", "text": "`@reboot`", "correct": true, "explanation": "Läuft einmal, wenn der cron-Daemon startet." },
|
||||||
|
{ "id": "b", "text": "`@daily`", "correct": false, "explanation": "Entspricht `0 0 * * *` (täglich um Mitternacht)." },
|
||||||
|
{ "id": "c", "text": "`@boot`", "correct": false, "explanation": "Diese Kurzschreibweise gibt es nicht." },
|
||||||
|
{ "id": "d", "text": "`@startup`", "correct": false, "explanation": "Diese Kurzschreibweise gibt es nicht." },
|
||||||
|
{ "id": "e", "text": "`0 0 * * 0`", "correct": false, "explanation": "Sonntags um Mitternacht (`@weekly`)." }
|
||||||
|
],
|
||||||
|
"explanation": "Kurzschreibweisen: `@reboot`, `@yearly`, `@monthly`, `@weekly`, `@daily`, `@hourly`.",
|
||||||
|
"references": ["man 5 crontab"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "107.2-008",
|
||||||
|
"objective": "107.2",
|
||||||
|
"type": "fill",
|
||||||
|
"difficulty": 2,
|
||||||
|
"question": "Geben Sie die fünf crontab-Zeitfelder ein, mit denen ein Job **alle 15 Minuten** läuft.",
|
||||||
|
"answers": ["*/15 * * * *", "0,15,30,45 * * * *", "0-59/15 * * * *"],
|
||||||
|
"explanation": "`*/15` im Minutenfeld bedeutet „jede 15. Minute“ (0, 15, 30, 45).",
|
||||||
|
"references": ["man 5 crontab"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "107.2-009",
|
||||||
|
"objective": "107.2",
|
||||||
|
"type": "single",
|
||||||
|
"difficulty": 1,
|
||||||
|
"question": "Wie löscht man den anstehenden at-Auftrag mit der Nummer 7?",
|
||||||
|
"options": [
|
||||||
|
{ "id": "a", "text": "`atrm 7`", "correct": true, "explanation": "`atrm` entfernt at-Aufträge anhand der Nummer aus `atq`." },
|
||||||
|
{ "id": "b", "text": "`atq 7`", "correct": false, "explanation": "`atq` listet nur die Warteschlange." },
|
||||||
|
{ "id": "c", "text": "`crontab -r 7`", "correct": false, "explanation": "`crontab -r` löscht die **gesamte** crontab des Benutzers – Vorsicht!" },
|
||||||
|
{ "id": "d", "text": "`kill 7`", "correct": false, "explanation": "Sendet ein Signal an den Prozess mit PID 7." },
|
||||||
|
{ "id": "e", "text": "`at -l 7`", "correct": false, "explanation": "`at -l` entspricht `atq` und listet Aufträge." }
|
||||||
|
],
|
||||||
|
"explanation": "`at -c 7` zeigt den Inhalt des Auftrags. `at -d 7` ist gleichbedeutend mit `atrm 7`.",
|
||||||
|
"references": ["man 1 at"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "107.2-010",
|
||||||
|
"objective": "107.2",
|
||||||
|
"type": "single",
|
||||||
|
"difficulty": 2,
|
||||||
|
"question": "Ein systemd-Timer soll eine Ausführung **nachholen**, die verpasst wurde, weil der Rechner ausgeschaltet war. Welche Einstellung im `[Timer]`-Abschnitt sorgt dafür?",
|
||||||
|
"options": [
|
||||||
|
{ "id": "a", "text": "`Persistent=true`", "correct": true, "explanation": "Der Zeitpunkt der letzten Ausführung wird gespeichert; Verpasstes läuft nach dem Start." },
|
||||||
|
{ "id": "b", "text": "`OnBootSec=0`", "correct": false, "explanation": "Startet nach jedem Boot, unabhängig vom Kalender." },
|
||||||
|
{ "id": "c", "text": "`AccuracySec=1s`", "correct": false, "explanation": "Legt nur die Genauigkeit des Auslösezeitpunkts fest." },
|
||||||
|
{ "id": "d", "text": "`WakeSystem=true`", "correct": false, "explanation": "Weckt das System aus dem Ruhezustand; ein ausgeschaltetes System hilft das nicht." },
|
||||||
|
{ "id": "e", "text": "`RemainAfterElapse=true`", "correct": false, "explanation": "Lässt den Timer nach Ablauf geladen; mit Nachholen hat das nichts zu tun." }
|
||||||
|
],
|
||||||
|
"explanation": "Klassisch erfüllt `anacron` diese Aufgabe für tägliche/wöchentliche cron-Jobs.",
|
||||||
|
"references": ["man 5 systemd.timer"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "107.2-011",
|
||||||
|
"objective": "107.2",
|
||||||
|
"type": "single",
|
||||||
|
"difficulty": 2,
|
||||||
|
"question": "Welcher Befehl führt `/usr/local/bin/sync.sh` **einmalig in 30 Minuten** als transiente systemd-Unit aus?",
|
||||||
|
"options": [
|
||||||
|
{ "id": "a", "text": "`systemd-run --on-active=30m /usr/local/bin/sync.sh`", "correct": true, "explanation": "`systemd-run` erzeugt Timer und Service vorübergehend; `--on-active` zählt ab jetzt." },
|
||||||
|
{ "id": "b", "text": "`systemd-run --on-calendar=30m /usr/local/bin/sync.sh`", "correct": false, "explanation": "`--on-calendar` erwartet einen Kalenderausdruck wie `*-*-* 02:00`, keine Zeitspanne." },
|
||||||
|
{ "id": "c", "text": "`systemctl start --in 30m /usr/local/bin/sync.sh`", "correct": false, "explanation": "`systemctl start` kennt keine Verzögerung und startet nur Units." },
|
||||||
|
{ "id": "d", "text": "`at --systemd 30m /usr/local/bin/sync.sh`", "correct": false, "explanation": "`at` hat keine solche Option; richtig wäre `echo /usr/local/bin/sync.sh | at now + 30 minutes`." },
|
||||||
|
{ "id": "e", "text": "`timedatectl run 30m /usr/local/bin/sync.sh`", "correct": false, "explanation": "`timedatectl` verwaltet Uhrzeit und Zeitzone." }
|
||||||
|
],
|
||||||
|
"explanation": "Transiente Timer erscheinen in `systemctl list-timers` und verschwinden nach Ausführung.",
|
||||||
|
"references": ["man 1 systemd-run"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "107.2-012",
|
||||||
|
"objective": "107.2",
|
||||||
|
"type": "multi",
|
||||||
|
"difficulty": 2,
|
||||||
|
"question": "Welche Werte sind gültige `OnCalendar=`-Angaben in einer systemd-Timer-Unit?",
|
||||||
|
"options": [
|
||||||
|
{ "id": "a", "text": "`daily`", "correct": true, "explanation": "Kurzform für `*-*-* 00:00:00`." },
|
||||||
|
{ "id": "b", "text": "`Mon *-*-* 02:30:00`", "correct": true, "explanation": "Wochentag, Datum (Jahr-Monat-Tag), Uhrzeit." },
|
||||||
|
{ "id": "c", "text": "`*/15 * * * *`", "correct": false, "explanation": "Das ist crontab-Syntax; systemd schreibt z. B. `*:0/15`." },
|
||||||
|
{ "id": "d", "text": "`every 5 minutes`", "correct": false, "explanation": "Freitext versteht systemd nicht." },
|
||||||
|
{ "id": "e", "text": "`30 2 * * 1`", "correct": false, "explanation": "crontab-Syntax, nicht systemd." }
|
||||||
|
],
|
||||||
|
"explanation": "Prüfen und Vorschau: `systemd-analyze calendar \"Mon *-*-* 02:30:00\"`.",
|
||||||
|
"references": ["man 7 systemd.time"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "107.2-013",
|
||||||
|
"objective": "107.2",
|
||||||
|
"type": "fill",
|
||||||
|
"difficulty": 2,
|
||||||
|
"question": "Mit welchem `crontab`-Aufruf zeigt root die crontab des Benutzers `bob` an?",
|
||||||
|
"answers": ["crontab -l -u bob", "crontab -u bob -l"],
|
||||||
|
"explanation": "`-u` wählt den Benutzer; mit `-e` bearbeitet root fremde crontabs.",
|
||||||
|
"references": ["man 1 crontab"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "107.3-005",
|
||||||
|
"objective": "107.3",
|
||||||
|
"type": "single",
|
||||||
|
"difficulty": 1,
|
||||||
|
"question": "Welcher Befehl listet alle auf dem System verfügbaren (erzeugten) Locales auf?",
|
||||||
|
"options": [
|
||||||
|
{ "id": "a", "text": "`locale -a`", "correct": true, "explanation": "`-a` (all) listet z. B. `C.UTF-8`, `de_DE.utf8`, `en_US.utf8`." },
|
||||||
|
{ "id": "b", "text": "`locale`", "correct": false, "explanation": "Zeigt nur die aktuell wirksamen Einstellungen." },
|
||||||
|
{ "id": "c", "text": "`localectl list-keymaps`", "correct": false, "explanation": "Listet Tastaturbelegungen." },
|
||||||
|
{ "id": "d", "text": "`iconv -l`", "correct": false, "explanation": "Listet Zeichenkodierungen, keine Locales." },
|
||||||
|
{ "id": "e", "text": "`ls /etc/locale`", "correct": false, "explanation": "Kein Standardort für Locales." }
|
||||||
|
],
|
||||||
|
"explanation": "Fehlende Locales erzeugt man unter Debian mit `locale-gen` bzw. `dpkg-reconfigure locales`. Systemweite Vorgabe: `localectl set-locale LANG=de_DE.UTF-8`.",
|
||||||
|
"references": ["man 1 locale"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "107.3-006",
|
||||||
|
"objective": "107.3",
|
||||||
|
"type": "fill",
|
||||||
|
"difficulty": 1,
|
||||||
|
"question": "Welcher Befehl (nur der Name) zeigt die aktuell wirksamen Locale-Einstellungen (`LANG`, `LC_*`) an?",
|
||||||
|
"answers": ["locale"],
|
||||||
|
"explanation": "Werte in Anführungszeichen sind abgeleitet (aus `LANG` bzw. `LC_ALL`), nicht ausdrücklich gesetzt.",
|
||||||
|
"references": ["man 1 locale"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "107.3-007",
|
||||||
|
"objective": "107.3",
|
||||||
|
"type": "single",
|
||||||
|
"difficulty": 2,
|
||||||
|
"question": "Was ist `/etc/localtime` auf den meisten aktuellen Linux-Systemen?",
|
||||||
|
"options": [
|
||||||
|
{ "id": "a", "text": "Ein symbolischer Link auf eine Zeitzonendatei unter `/usr/share/zoneinfo/`", "correct": true, "explanation": "z. B. `/etc/localtime -> /usr/share/zoneinfo/Europe/Berlin`." },
|
||||||
|
{ "id": "b", "text": "Eine Textdatei mit dem Namen der Zeitzone", "correct": false, "explanation": "Das ist `/etc/timezone` (Debian)." },
|
||||||
|
{ "id": "c", "text": "Die Konfiguration der Hardware-Uhr (UTC oder Ortszeit)", "correct": false, "explanation": "Das steht in `/etc/adjtime`." },
|
||||||
|
{ "id": "d", "text": "Eine Protokolldatei der Zeitsynchronisation", "correct": false, "explanation": "Keine Protokolldatei." },
|
||||||
|
{ "id": "e", "text": "Ein Kernelparameter unter `/proc`", "correct": false, "explanation": "`/etc` liegt auf der Festplatte, nicht im procfs." }
|
||||||
|
],
|
||||||
|
"explanation": "Die Zeitzonendaten (tzdata) liegen binär unter `/usr/share/zoneinfo/`.",
|
||||||
|
"references": ["man 5 localtime"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "107.3-008",
|
||||||
|
"objective": "107.3",
|
||||||
|
"type": "single",
|
||||||
|
"difficulty": 1,
|
||||||
|
"question": "Wie zeigt man **einmalig** die aktuelle Uhrzeit in New York an, ohne die Zeitzone des Systems zu ändern?",
|
||||||
|
"options": [
|
||||||
|
{ "id": "a", "text": "`TZ=America/New_York date`", "correct": true, "explanation": "`TZ` gilt hier nur für diesen einen Aufruf von `date`." },
|
||||||
|
{ "id": "b", "text": "`timedatectl set-timezone America/New_York`", "correct": false, "explanation": "Ändert die Zeitzone des Systems dauerhaft." },
|
||||||
|
{ "id": "c", "text": "`LC_TIME=America/New_York date`", "correct": false, "explanation": "`LC_TIME` steuert nur das Format, nicht die Zeitzone." },
|
||||||
|
{ "id": "d", "text": "`date -u`", "correct": false, "explanation": "Zeigt UTC an." },
|
||||||
|
{ "id": "e", "text": "`hwclock --localtime`", "correct": false, "explanation": "Betrifft die Interpretation der Hardware-Uhr." }
|
||||||
|
],
|
||||||
|
"explanation": "Gültige Namen liefert `timedatectl list-timezones` oder `tzselect`.",
|
||||||
|
"references": ["man 1 date", "man 3 tzset"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "107.3-009",
|
||||||
|
"objective": "107.3",
|
||||||
|
"type": "single",
|
||||||
|
"difficulty": 1,
|
||||||
|
"question": "Welche Locale-Kategorie bestimmt das **Format von Datum und Uhrzeit**?",
|
||||||
|
"options": [
|
||||||
|
{ "id": "a", "text": "`LC_TIME`", "correct": true, "explanation": "z. B. `30.10.2026` bei `de_DE` statt `10/30/2026` bei `en_US`." },
|
||||||
|
{ "id": "b", "text": "`LC_NUMERIC`", "correct": false, "explanation": "Dezimal- und Tausendertrennzeichen." },
|
||||||
|
{ "id": "c", "text": "`LC_COLLATE`", "correct": false, "explanation": "Sortierreihenfolge." },
|
||||||
|
{ "id": "d", "text": "`LC_MESSAGES`", "correct": false, "explanation": "Sprache der Programmmeldungen." },
|
||||||
|
{ "id": "e", "text": "`LC_CTYPE`", "correct": false, "explanation": "Zeichenklassen und Zeichensatz." }
|
||||||
|
],
|
||||||
|
"explanation": "Weitere: `LC_MONETARY` (Währung), `LC_PAPER`, `LC_MEASUREMENT`.",
|
||||||
|
"references": ["man 7 locale"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "107.3-010",
|
||||||
|
"objective": "107.3",
|
||||||
|
"type": "multi",
|
||||||
|
"difficulty": 2,
|
||||||
|
"question": "Welche Werkzeuge helfen, die **Zeitzone** auszuwählen bzw. einzustellen?",
|
||||||
|
"options": [
|
||||||
|
{ "id": "a", "text": "`tzselect`", "correct": true, "explanation": "Interaktive Auswahl; gibt den passenden `TZ`-Wert aus." },
|
||||||
|
{ "id": "b", "text": "`dpkg-reconfigure tzdata`", "correct": true, "explanation": "Debian: setzt `/etc/timezone` und `/etc/localtime`." },
|
||||||
|
{ "id": "c", "text": "`locale-gen`", "correct": false, "explanation": "Erzeugt Locales." },
|
||||||
|
{ "id": "d", "text": "`iconv`", "correct": false, "explanation": "Konvertiert Zeichenkodierungen." },
|
||||||
|
{ "id": "e", "text": "`localectl set-locale`", "correct": false, "explanation": "Setzt die systemweite Locale, nicht die Zeitzone." }
|
||||||
|
],
|
||||||
|
"explanation": "Mit systemd: `timedatectl set-timezone <Zone>`.",
|
||||||
|
"references": ["man 8 tzselect"]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -0,0 +1,321 @@
|
|||||||
|
{
|
||||||
|
"$schema": "../schema/questions.schema.json",
|
||||||
|
"format": "lpic-sim-questions",
|
||||||
|
"meta": {
|
||||||
|
"file": "questions_108_set2.json",
|
||||||
|
"brief": "Zweiter Fragensatz zu Topic 108 Grundlegende Systemdienste (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": "108.1-005",
|
||||||
|
"objective": "108.1",
|
||||||
|
"type": "fill",
|
||||||
|
"difficulty": 2,
|
||||||
|
"question": "Welche Option von `hwclock` überträgt die Zeit der Hardware-Uhr in die Systemzeit? (nur die Option)",
|
||||||
|
"answers": ["--hctosys", "-s"],
|
||||||
|
"explanation": "hardware clock to system: wird typischerweise beim Start ausgeführt. Gegenrichtung: `--systohc` (`-w`).",
|
||||||
|
"references": ["man 8 hwclock"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "108.1-006",
|
||||||
|
"objective": "108.1",
|
||||||
|
"type": "single",
|
||||||
|
"difficulty": 1,
|
||||||
|
"question": "Welcher Befehl gibt das heutige Datum im Format `2026-10-30` aus?",
|
||||||
|
"options": [
|
||||||
|
{ "id": "a", "text": "`date +%F`", "correct": true, "explanation": "`%F` entspricht `%Y-%m-%d`." },
|
||||||
|
{ "id": "b", "text": "`date +%D`", "correct": false, "explanation": "`%D` ergibt `10/30/26`." },
|
||||||
|
{ "id": "c", "text": "`date +%T`", "correct": false, "explanation": "`%T` ist die Uhrzeit `%H:%M:%S`." },
|
||||||
|
{ "id": "d", "text": "`date +%d.%m.%Y`", "correct": false, "explanation": "Ergibt `30.10.2026`." },
|
||||||
|
{ "id": "e", "text": "`date -u`", "correct": false, "explanation": "Zeigt Datum und Uhrzeit in UTC im Standardformat." }
|
||||||
|
],
|
||||||
|
"explanation": "Typisch für Dateinamen: `backup_$(date +%F).tar.gz`. Uhrzeit stellen: `date -s` bzw. `timedatectl set-time`.",
|
||||||
|
"references": ["man 1 date"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "108.1-007",
|
||||||
|
"objective": "108.1",
|
||||||
|
"type": "single",
|
||||||
|
"difficulty": 2,
|
||||||
|
"question": "Mit welcher Zeile trägt man in der chrony-Konfiguration einen NTP-**Pool** als Zeitquelle ein?",
|
||||||
|
"options": [
|
||||||
|
{ "id": "a", "text": "`pool 2.debian.pool.ntp.org iburst`", "correct": true, "explanation": "`pool` löst den Namen in mehrere Server auf; `iburst` beschleunigt die erste Synchronisation." },
|
||||||
|
{ "id": "b", "text": "`NTP=2.debian.pool.ntp.org`", "correct": false, "explanation": "Das ist die Syntax von `/etc/systemd/timesyncd.conf`." },
|
||||||
|
{ "id": "c", "text": "`ntpserver = 2.debian.pool.ntp.org`", "correct": false, "explanation": "Keine gültige chrony-Direktive." },
|
||||||
|
{ "id": "d", "text": "`nameserver 2.debian.pool.ntp.org`", "correct": false, "explanation": "Syntax von `/etc/resolv.conf`." },
|
||||||
|
{ "id": "e", "text": "`server: 2.debian.pool.ntp.org`", "correct": false, "explanation": "chrony nutzt keinen Doppelpunkt; einzelne Server: `server <name> iburst`." }
|
||||||
|
],
|
||||||
|
"explanation": "Dieselbe Syntax (`server`, `pool`) verwendet auch der klassische ntpd in `/etc/ntp.conf`.",
|
||||||
|
"references": ["man 5 chrony.conf"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "108.1-008",
|
||||||
|
"objective": "108.1",
|
||||||
|
"type": "single",
|
||||||
|
"difficulty": 2,
|
||||||
|
"question": "In welcher Datei konfiguriert man die NTP-Server für **systemd-timesyncd**?",
|
||||||
|
"options": [
|
||||||
|
{ "id": "a", "text": "`/etc/systemd/timesyncd.conf`", "correct": true, "explanation": "Abschnitt `[Time]`, z. B. `NTP=` und `FallbackNTP=`." },
|
||||||
|
{ "id": "b", "text": "`/etc/chrony/chrony.conf`", "correct": false, "explanation": "Konfiguration von chrony." },
|
||||||
|
{ "id": "c", "text": "`/etc/ntp.conf`", "correct": false, "explanation": "Konfiguration des klassischen ntpd." },
|
||||||
|
{ "id": "d", "text": "`/etc/adjtime`", "correct": false, "explanation": "Hält Drift und Modus (UTC/Ortszeit) der Hardware-Uhr." },
|
||||||
|
{ "id": "e", "text": "`/etc/systemd/journald.conf`", "correct": false, "explanation": "Konfiguration des Journals." }
|
||||||
|
],
|
||||||
|
"explanation": "systemd-timesyncd ist ein reiner SNTP-Client; als Server für andere Rechner taugt er nicht.",
|
||||||
|
"references": ["man 5 timesyncd.conf"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "108.1-009",
|
||||||
|
"objective": "108.1",
|
||||||
|
"type": "multi",
|
||||||
|
"difficulty": 2,
|
||||||
|
"question": "Mit welchen Befehlen prüft man, ob die Systemuhr synchronisiert ist bzw. wie groß die Abweichung ist?",
|
||||||
|
"options": [
|
||||||
|
{ "id": "a", "text": "`timedatectl`", "correct": true, "explanation": "Zeigt u. a. `System clock synchronized: yes/no` und `NTP service`." },
|
||||||
|
{ "id": "b", "text": "`chronyc tracking`", "correct": true, "explanation": "Zeigt Referenzquelle, Stratum und aktuelle Abweichung (System time offset)." },
|
||||||
|
{ "id": "c", "text": "`hwclock --systohc`", "correct": false, "explanation": "Schreibt die Systemzeit in die Hardware-Uhr, prüft nichts." },
|
||||||
|
{ "id": "d", "text": "`date -s \"12:00\"`", "correct": false, "explanation": "Stellt die Uhr manuell." },
|
||||||
|
{ "id": "e", "text": "`ntpdate pool.ntp.org`", "correct": false, "explanation": "Stellt die Uhr einmalig (veraltet); `ntpdate -q` würde nur abfragen." }
|
||||||
|
],
|
||||||
|
"explanation": "Beim klassischen ntpd zeigt `ntpq -p` die Peers mit Offset und Jitter.",
|
||||||
|
"references": ["man 1 timedatectl", "man 1 chronyc"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "108.2-007",
|
||||||
|
"objective": "108.2",
|
||||||
|
"type": "single",
|
||||||
|
"difficulty": 1,
|
||||||
|
"question": "Wie zeigt `journalctl` nur Meldungen mit Priorität **err und höher** an?",
|
||||||
|
"options": [
|
||||||
|
{ "id": "a", "text": "`journalctl -p err`", "correct": true, "explanation": "`-p` filtert nach Priorität; ein einzelner Wert schließt alle schwerwiegenderen ein." },
|
||||||
|
{ "id": "b", "text": "`journalctl -u err`", "correct": false, "explanation": "`-u` filtert nach Unit." },
|
||||||
|
{ "id": "c", "text": "`journalctl -t err`", "correct": false, "explanation": "`-t` filtert nach Syslog-Kennung (Identifier)." },
|
||||||
|
{ "id": "d", "text": "`journalctl -k err`", "correct": false, "explanation": "`-k` zeigt Kernel-Meldungen." },
|
||||||
|
{ "id": "e", "text": "`journalctl --grep err`", "correct": false, "explanation": "Durchsucht den Meldungstext nach „err“, unabhängig von der Priorität." }
|
||||||
|
],
|
||||||
|
"explanation": "Prioritäten als Namen oder Zahlen 0 (emerg) bis 7 (debug); Bereich z. B. `-p warning..err`.",
|
||||||
|
"references": ["man 1 journalctl"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "108.2-008",
|
||||||
|
"objective": "108.2",
|
||||||
|
"type": "fill",
|
||||||
|
"difficulty": 1,
|
||||||
|
"question": "Welche `journalctl`-Option zeigt nur Meldungen des **aktuellen Systemstarts**? (nur die Option)",
|
||||||
|
"answers": ["-b", "--boot", "-b 0"],
|
||||||
|
"explanation": "`-b -1` zeigt den vorherigen Start (persistentes Journal nötig); `--list-boots` listet alle.",
|
||||||
|
"references": ["man 1 journalctl"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "108.2-009",
|
||||||
|
"objective": "108.2",
|
||||||
|
"type": "single",
|
||||||
|
"difficulty": 2,
|
||||||
|
"question": "Welcher Aufruf zeigt Journal-Meldungen vom 30.10.2026 zwischen 08:00 und 09:00 Uhr?",
|
||||||
|
"options": [
|
||||||
|
{ "id": "a", "text": "`journalctl --since \"2026-10-30 08:00\" --until \"2026-10-30 09:00\"`", "correct": true, "explanation": "`--since`/`--until` (`-S`/`-U`) begrenzen den Zeitraum." },
|
||||||
|
{ "id": "b", "text": "`journalctl --from 08:00 --to 09:00`", "correct": false, "explanation": "Diese Optionen gibt es nicht." },
|
||||||
|
{ "id": "c", "text": "`journalctl -b 2026-10-30 08:00-09:00`", "correct": false, "explanation": "`-b` erwartet eine Boot-ID oder einen Index." },
|
||||||
|
{ "id": "d", "text": "`journalctl -p 08:00..09:00`", "correct": false, "explanation": "`-p` filtert nach Priorität." },
|
||||||
|
{ "id": "e", "text": "`journalctl --date 30.10.2026`", "correct": false, "explanation": "Diese Option gibt es nicht." }
|
||||||
|
],
|
||||||
|
"explanation": "Auch relative Angaben sind möglich: `--since \"1 hour ago\"`, `--since yesterday`.",
|
||||||
|
"references": ["man 1 journalctl"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "108.2-010",
|
||||||
|
"objective": "108.2",
|
||||||
|
"type": "single",
|
||||||
|
"difficulty": 2,
|
||||||
|
"question": "Was bewirkt die rsyslog-Regel `*.* @@log.example.org:514`?",
|
||||||
|
"options": [
|
||||||
|
{ "id": "a", "text": "Alle Meldungen werden per **TCP** an `log.example.org` weitergeleitet.", "correct": true, "explanation": "`@@` steht für TCP." },
|
||||||
|
{ "id": "b", "text": "Alle Meldungen werden per UDP an `log.example.org` weitergeleitet.", "correct": false, "explanation": "UDP wäre ein einzelnes `@`." },
|
||||||
|
{ "id": "c", "text": "rsyslog empfängt Meldungen von `log.example.org`.", "correct": false, "explanation": "Empfang wird über Eingabemodule (`imtcp`/`imudp`) konfiguriert." },
|
||||||
|
{ "id": "d", "text": "Nur Fehler werden weitergeleitet.", "correct": false, "explanation": "`*.*` bedeutet alle Facilities und Prioritäten." },
|
||||||
|
{ "id": "e", "text": "Die Meldungen werden in eine Datei namens `log.example.org` geschrieben.", "correct": false, "explanation": "Dateiziele beginnen mit `/`." }
|
||||||
|
],
|
||||||
|
"explanation": "Port 514 ist der Standard für syslog. Zentrale Protokollierung erschwert Angreifern das Verwischen von Spuren.",
|
||||||
|
"references": ["man 5 rsyslog.conf"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "108.2-011",
|
||||||
|
"objective": "108.2",
|
||||||
|
"type": "single",
|
||||||
|
"difficulty": 1,
|
||||||
|
"question": "Welche syslog-Facilities sind für **eigene Anwendungen** frei verwendbar?",
|
||||||
|
"options": [
|
||||||
|
{ "id": "a", "text": "`local0` bis `local7`", "correct": true, "explanation": "Reserviert für lokale bzw. eigene Zwecke." },
|
||||||
|
{ "id": "b", "text": "`kern`", "correct": false, "explanation": "Für Kernel-Meldungen reserviert." },
|
||||||
|
{ "id": "c", "text": "`authpriv`", "correct": false, "explanation": "Für vertrauliche Authentifizierungsmeldungen." },
|
||||||
|
{ "id": "d", "text": "`mail`", "correct": false, "explanation": "Für das Mailsystem." },
|
||||||
|
{ "id": "e", "text": "`cron`", "correct": false, "explanation": "Für den cron-Daemon." }
|
||||||
|
],
|
||||||
|
"explanation": "Beispiel: `logger -p local3.info \"Backup ok\"` und in rsyslog `local3.* /var/log/backup.log`.",
|
||||||
|
"references": ["man 3 syslog"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "108.2-012",
|
||||||
|
"objective": "108.2",
|
||||||
|
"type": "multi",
|
||||||
|
"difficulty": 2,
|
||||||
|
"question": "Welche Aussagen zur Verwaltung des systemd-Journals treffen zu?",
|
||||||
|
"options": [
|
||||||
|
{ "id": "a", "text": "`journalctl --vacuum-time=2weeks` löscht archivierte Journal-Dateien, die älter als zwei Wochen sind.", "correct": true, "explanation": "Ebenso `--vacuum-size=` und `--vacuum-files=`." },
|
||||||
|
{ "id": "b", "text": "`journalctl --disk-usage` zeigt, wie viel Platz das Journal belegt.", "correct": true, "explanation": "Summe aus aktiven und archivierten Dateien." },
|
||||||
|
{ "id": "c", "text": "`journalctl --rotate` löscht alle Meldungen.", "correct": false, "explanation": "Rotiert nur: Die aktiven Dateien werden archiviert, neue begonnen." },
|
||||||
|
{ "id": "d", "text": "`journalctl -r` zeigt das Journal eines entfernten Rechners.", "correct": false, "explanation": "`-r` (reverse) zeigt die neuesten Meldungen zuerst." },
|
||||||
|
{ "id": "e", "text": "`systemd-cat` liest das Journal und gibt es aus.", "correct": false, "explanation": "`systemd-cat` schreibt die Ausgabe eines Befehls **ins** Journal." }
|
||||||
|
],
|
||||||
|
"explanation": "Dauerhafte Grenzen: `SystemMaxUse=` und `MaxRetentionSec=` in `journald.conf`.",
|
||||||
|
"references": ["man 1 journalctl", "man 1 systemd-cat"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "108.2-013",
|
||||||
|
"objective": "108.2",
|
||||||
|
"type": "fill",
|
||||||
|
"difficulty": 1,
|
||||||
|
"question": "Mit welchem `journalctl`-Aufruf (Befehl und Option) zeigt man nur die **Kernel-Meldungen** aus dem Journal?",
|
||||||
|
"answers": ["journalctl -k", "journalctl --dmesg"],
|
||||||
|
"explanation": "Entspricht inhaltlich `dmesg`, aber mit Zeitstempeln und Filtern des Journals; impliziert den aktuellen Boot.",
|
||||||
|
"references": ["man 1 journalctl"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "108.3-005",
|
||||||
|
"objective": "108.3",
|
||||||
|
"type": "single",
|
||||||
|
"difficulty": 1,
|
||||||
|
"question": "Über welchen Port liefern MTAs E-Mails per SMTP **untereinander** aus?",
|
||||||
|
"options": [
|
||||||
|
{ "id": "a", "text": "25", "correct": true, "explanation": "Port 25/tcp: SMTP zwischen Mailservern." },
|
||||||
|
{ "id": "b", "text": "587", "correct": false, "explanation": "Submission: Einlieferung durch Mailprogramme (MUA) mit Authentifizierung." },
|
||||||
|
{ "id": "c", "text": "110", "correct": false, "explanation": "POP3 zum Abholen von Mails." },
|
||||||
|
{ "id": "d", "text": "143", "correct": false, "explanation": "IMAP zum Abholen bzw. Verwalten von Mails." },
|
||||||
|
{ "id": "e", "text": "993", "correct": false, "explanation": "IMAP über TLS." }
|
||||||
|
],
|
||||||
|
"explanation": "Zusätzlich 465 (SMTPS, Submission über TLS). Viele Provider sperren ausgehenden Port 25 für Endkunden.",
|
||||||
|
"references": ["man 5 services"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "108.3-006",
|
||||||
|
"objective": "108.3",
|
||||||
|
"type": "single",
|
||||||
|
"difficulty": 1,
|
||||||
|
"question": "Wie verschickt man auf der Befehlszeile den Inhalt von `bericht.txt` mit dem Betreff „Bericht“ an `anna@example.org`?",
|
||||||
|
"options": [
|
||||||
|
{ "id": "a", "text": "`mail -s \"Bericht\" anna@example.org < bericht.txt`", "correct": true, "explanation": "`mail` liest den Text von stdin; `-s` setzt den Betreff." },
|
||||||
|
{ "id": "b", "text": "`mailq -s \"Bericht\" anna@example.org < bericht.txt`", "correct": false, "explanation": "`mailq` zeigt nur die Warteschlange." },
|
||||||
|
{ "id": "c", "text": "`newaliases -s \"Bericht\" anna@example.org`", "correct": false, "explanation": "`newaliases` baut die Alias-Datenbank neu." },
|
||||||
|
{ "id": "d", "text": "`smtp anna@example.org bericht.txt`", "correct": false, "explanation": "Einen solchen Befehl gibt es standardmäßig nicht." },
|
||||||
|
{ "id": "e", "text": "`cat bericht.txt > anna@example.org`", "correct": false, "explanation": "Schreibt in eine **Datei** namens `anna@example.org`." }
|
||||||
|
],
|
||||||
|
"explanation": "`mail` übergibt die Nachricht an den lokalen MTA (über dessen `sendmail`-Schnittstelle).",
|
||||||
|
"references": ["man 1 mail"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "108.3-007",
|
||||||
|
"objective": "108.3",
|
||||||
|
"type": "fill",
|
||||||
|
"difficulty": 1,
|
||||||
|
"question": "In welcher Datei (vollständiger Pfad) stehen die systemweiten E-Mail-Aliase, z. B. `postmaster: root`?",
|
||||||
|
"answers": ["/etc/aliases"],
|
||||||
|
"explanation": "Nach Änderungen `newaliases` ausführen. Bei manchen Systemen liegt sie unter `/etc/mail/aliases`.",
|
||||||
|
"references": ["man 5 aliases"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "108.3-008",
|
||||||
|
"objective": "108.3",
|
||||||
|
"type": "single",
|
||||||
|
"difficulty": 2,
|
||||||
|
"question": "Warum bringen Postfix und Exim einen Befehl `sendmail` mit, obwohl sie nicht Sendmail sind?",
|
||||||
|
"options": [
|
||||||
|
{ "id": "a", "text": "Aus Kompatibilität: Viele Programme übergeben Mails an `/usr/sbin/sendmail`.", "correct": true, "explanation": "Die Schnittstelle ist ein De-facto-Standard; cron, mail und Skripte nutzen sie." },
|
||||||
|
{ "id": "b", "text": "Weil Postfix intern den Sendmail-Daemon startet.", "correct": false, "explanation": "Postfix ist eine eigenständige Implementierung." },
|
||||||
|
{ "id": "c", "text": "Damit sie Mails per IMAP abholen können.", "correct": false, "explanation": "Abholen ist Aufgabe von IMAP-/POP3-Servern und Clients." },
|
||||||
|
{ "id": "d", "text": "Weil `sendmail` die Konfigurationsdatei `/etc/aliases` ersetzt.", "correct": false, "explanation": "`/etc/aliases` bleibt in Gebrauch." },
|
||||||
|
{ "id": "e", "text": "Es ist nur ein Symlink auf `mailq` ohne eigene Funktion.", "correct": false, "explanation": "Umgekehrt: `mailq` und `newaliases` sind oft Links auf `sendmail`." }
|
||||||
|
],
|
||||||
|
"explanation": "`sendmail -bp` = `mailq`, `sendmail -bi` = `newaliases`, `sendmail -q` arbeitet die Warteschlange ab.",
|
||||||
|
"references": ["man 1 sendmail"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "108.3-009",
|
||||||
|
"objective": "108.3",
|
||||||
|
"type": "multi",
|
||||||
|
"difficulty": 1,
|
||||||
|
"question": "Welche Aussagen zu MTA, MDA und MUA treffen zu?",
|
||||||
|
"options": [
|
||||||
|
{ "id": "a", "text": "Thunderbird ist ein Mail User Agent (MUA).", "correct": true, "explanation": "Programm zum Lesen und Schreiben von Mails." },
|
||||||
|
{ "id": "b", "text": "Ein MTA überträgt Mails per SMTP zwischen Servern.", "correct": true, "explanation": "z. B. Postfix, Exim, Sendmail." },
|
||||||
|
{ "id": "c", "text": "Dovecot ist ein MTA.", "correct": false, "explanation": "Dovecot ist ein IMAP-/POP3-Server (mit eigenem LDA)." },
|
||||||
|
{ "id": "d", "text": "Ein MUA stellt Mails standardmäßig direkt an fremde Mailserver zu.", "correct": false, "explanation": "Ein MUA übergibt an einen MTA (Submission), der zustellt." },
|
||||||
|
{ "id": "e", "text": "`mailq` verschickt Mails sofort.", "correct": false, "explanation": "`mailq` zeigt nur die Warteschlange." }
|
||||||
|
],
|
||||||
|
"explanation": "Kette: MUA → MTA (Absender) → MTA (Empfänger) → MDA (lokale Zustellung) → Postfach → MUA.",
|
||||||
|
"references": ["LPI 102-500 Objective 108.3"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "108.4-004",
|
||||||
|
"objective": "108.4",
|
||||||
|
"type": "single",
|
||||||
|
"difficulty": 2,
|
||||||
|
"question": "Wie legt ein Benutzer den Drucker `buero` als seinen **Standarddrucker** fest?",
|
||||||
|
"options": [
|
||||||
|
{ "id": "a", "text": "`lpoptions -d buero`", "correct": true, "explanation": "Schreibt den Standarddrucker in `~/.cups/lpoptions` (als root systemweit)." },
|
||||||
|
{ "id": "b", "text": "`lp -d buero`", "correct": false, "explanation": "Druckt stdin einmalig auf `buero`, ändert den Standard nicht." },
|
||||||
|
{ "id": "c", "text": "`lpq -d buero`", "correct": false, "explanation": "`lpq` zeigt die Warteschlange." },
|
||||||
|
{ "id": "d", "text": "`cupsenable -d buero`", "correct": false, "explanation": "`cupsenable` aktiviert einen Drucker." },
|
||||||
|
{ "id": "e", "text": "`lprm -d buero`", "correct": false, "explanation": "`lprm` entfernt Aufträge." }
|
||||||
|
],
|
||||||
|
"explanation": "Systemweit als Administrator auch `lpadmin -d buero`. Die Variable `PRINTER` überschreibt den Standard für eine Sitzung.",
|
||||||
|
"references": ["man 1 lpoptions"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "108.4-005",
|
||||||
|
"objective": "108.4",
|
||||||
|
"type": "fill",
|
||||||
|
"difficulty": 2,
|
||||||
|
"question": "Welcher System-V-Druckbefehl (nur der Name) entfernt Druckaufträge – das Gegenstück zu `lprm`?",
|
||||||
|
"answers": ["cancel"],
|
||||||
|
"explanation": "`cancel <auftrag>` bzw. `cancel -a <drucker>` für alle Aufträge eines Druckers.",
|
||||||
|
"references": ["man 1 cancel"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "108.4-006",
|
||||||
|
"objective": "108.4",
|
||||||
|
"type": "single",
|
||||||
|
"difficulty": 1,
|
||||||
|
"question": "Welcher Befehl zeigt alle Drucker mit ihrem Status und den Standarddrucker an?",
|
||||||
|
"options": [
|
||||||
|
{ "id": "a", "text": "`lpstat -p -d`", "correct": true, "explanation": "`-p` Druckerstatus, `-d` Standarddrucker; `lpstat -t` zeigt alles." },
|
||||||
|
{ "id": "b", "text": "`lpq -a`", "correct": false, "explanation": "Zeigt die Aufträge aller Warteschlangen." },
|
||||||
|
{ "id": "c", "text": "`lpinfo -v`", "correct": false, "explanation": "Listet verfügbare Geräte bzw. Backends für neue Drucker." },
|
||||||
|
{ "id": "d", "text": "`cupsctl`", "correct": false, "explanation": "Zeigt bzw. ändert Einstellungen des CUPS-Servers." },
|
||||||
|
{ "id": "e", "text": "`lpadmin -l`", "correct": false, "explanation": "`lpadmin` richtet Drucker ein; `-l` listet nichts." }
|
||||||
|
],
|
||||||
|
"explanation": "Die Weboberfläche unter `http://localhost:631` zeigt dieselben Informationen.",
|
||||||
|
"references": ["man 1 lpstat"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "108.4-007",
|
||||||
|
"objective": "108.4",
|
||||||
|
"type": "multi",
|
||||||
|
"difficulty": 2,
|
||||||
|
"question": "Druckaufträge für `buero` landen in der Warteschlange, werden aber nicht gedruckt. Welche Befehle helfen bei Diagnose bzw. Behebung?",
|
||||||
|
"options": [
|
||||||
|
{ "id": "a", "text": "`lpstat -t`", "correct": true, "explanation": "Zeigt Status aller Drucker (z. B. „disabled“) und Aufträge." },
|
||||||
|
{ "id": "b", "text": "`cupsenable buero`", "correct": true, "explanation": "Aktiviert einen angehaltenen Drucker wieder; danach wird gedruckt." },
|
||||||
|
{ "id": "c", "text": "`cupsreject buero`", "correct": false, "explanation": "Lässt den Drucker keine **neuen** Aufträge mehr annehmen." },
|
||||||
|
{ "id": "d", "text": "`lpadmin -x buero`", "correct": false, "explanation": "Löscht den Drucker." },
|
||||||
|
{ "id": "e", "text": "`lprm -`", "correct": false, "explanation": "Löscht alle eigenen Aufträge – behebt die Ursache nicht." }
|
||||||
|
],
|
||||||
|
"explanation": "CUPS deaktiviert einen Drucker oft selbst nach Fehlern. Details stehen in `/var/log/cups/error_log`.",
|
||||||
|
"references": ["man 8 cupsenable", "man 1 lpstat"]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -0,0 +1,391 @@
|
|||||||
|
{
|
||||||
|
"$schema": "../schema/questions.schema.json",
|
||||||
|
"format": "lpic-sim-questions",
|
||||||
|
"meta": {
|
||||||
|
"file": "questions_109_set2.json",
|
||||||
|
"brief": "Zweiter Fragensatz zu Topic 109 Netzwerkgrundlagen (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": "109.1-007",
|
||||||
|
"objective": "109.1",
|
||||||
|
"type": "single",
|
||||||
|
"difficulty": 2,
|
||||||
|
"question": "Wie lautet die Broadcast-Adresse des Netzes `192.0.2.64/26`?",
|
||||||
|
"options": [
|
||||||
|
{ "id": "a", "text": "`192.0.2.127`", "correct": true, "explanation": "/26 = Blöcke zu 64 Adressen: .64 bis .127; die letzte ist Broadcast." },
|
||||||
|
{ "id": "b", "text": "`192.0.2.63`", "correct": false, "explanation": "Broadcast des vorherigen Netzes `192.0.2.0/26`." },
|
||||||
|
{ "id": "c", "text": "`192.0.2.128`", "correct": false, "explanation": "Netzadresse des nächsten Blocks `192.0.2.128/26`." },
|
||||||
|
{ "id": "d", "text": "`192.0.2.255`", "correct": false, "explanation": "Broadcast eines `/24`." },
|
||||||
|
{ "id": "e", "text": "`192.0.2.64`", "correct": false, "explanation": "Das ist die Netzadresse." }
|
||||||
|
],
|
||||||
|
"explanation": "Rechenweg: Blockgröße = 256 − 192 = 64. Netz = Vielfaches von 64, Broadcast = Netz + 63.",
|
||||||
|
"references": ["RFC 950"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "109.1-008",
|
||||||
|
"objective": "109.1",
|
||||||
|
"type": "fill",
|
||||||
|
"difficulty": 1,
|
||||||
|
"question": "Welchen Port verwenden DNS-Anfragen standardmäßig? (nur die Zahl)",
|
||||||
|
"answers": ["53"],
|
||||||
|
"explanation": "Normale Anfragen über UDP 53; große Antworten und Zonentransfers über TCP 53.",
|
||||||
|
"references": ["man 5 services"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "109.1-009",
|
||||||
|
"objective": "109.1",
|
||||||
|
"type": "single",
|
||||||
|
"difficulty": 1,
|
||||||
|
"question": "Welche Aussage über UDP trifft zu?",
|
||||||
|
"options": [
|
||||||
|
{ "id": "a", "text": "UDP ist verbindungslos und garantiert weder Zustellung noch Reihenfolge.", "correct": true, "explanation": "Geringer Overhead; Zuverlässigkeit muss die Anwendung selbst regeln." },
|
||||||
|
{ "id": "b", "text": "UDP baut Verbindungen mit einem Drei-Wege-Handshake auf.", "correct": false, "explanation": "Das ist TCP (SYN, SYN-ACK, ACK)." },
|
||||||
|
{ "id": "c", "text": "UDP sorgt für die richtige Reihenfolge der Pakete.", "correct": false, "explanation": "Das leistet TCP über Sequenznummern." },
|
||||||
|
{ "id": "d", "text": "UDP funktioniert nur mit IPv6.", "correct": false, "explanation": "UDP läuft über IPv4 und IPv6." },
|
||||||
|
{ "id": "e", "text": "`ping` verwendet UDP.", "correct": false, "explanation": "`ping` verwendet ICMP." }
|
||||||
|
],
|
||||||
|
"explanation": "Typische UDP-Dienste: DNS, NTP, DHCP, syslog, SNMP.",
|
||||||
|
"references": ["RFC 768"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "109.1-010",
|
||||||
|
"objective": "109.1",
|
||||||
|
"type": "single",
|
||||||
|
"difficulty": 2,
|
||||||
|
"question": "Welche Schreibweise ist die korrekte Kurzform von `2001:0db8:0000:0000:0000:0000:0000:0001`?",
|
||||||
|
"options": [
|
||||||
|
{ "id": "a", "text": "`2001:db8::1`", "correct": true, "explanation": "Führende Nullen je Gruppe entfallen, die längste Nullfolge wird einmal durch `::` ersetzt." },
|
||||||
|
{ "id": "b", "text": "`2001:db8:1`", "correct": false, "explanation": "Ohne `::` fehlen fünf Gruppen – die Adresse wäre unvollständig." },
|
||||||
|
{ "id": "c", "text": "`2001::db8::1`", "correct": false, "explanation": "`::` darf nur einmal vorkommen." },
|
||||||
|
{ "id": "d", "text": "`2001:db8:0:1`", "correct": false, "explanation": "Nur vier Gruppen, ohne `::` – ungültig." },
|
||||||
|
{ "id": "e", "text": "`21:db8::1`", "correct": false, "explanation": "Nur **führende** Nullen dürfen entfallen; in `2001` sind keine." }
|
||||||
|
],
|
||||||
|
"explanation": "`2001:db8::/32` ist für Dokumentation reserviert – wie `192.0.2.0/24` bei IPv4.",
|
||||||
|
"references": ["RFC 5952"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "109.1-011",
|
||||||
|
"objective": "109.1",
|
||||||
|
"type": "single",
|
||||||
|
"difficulty": 2,
|
||||||
|
"question": "Welches IPv6-Präfix ist für **Unique Local Addresses** reserviert (vergleichbar mit privaten IPv4-Netzen)?",
|
||||||
|
"options": [
|
||||||
|
{ "id": "a", "text": "`fc00::/7`", "correct": true, "explanation": "In der Praxis `fd00::/8` mit zufälliger 40-Bit-Global-ID." },
|
||||||
|
{ "id": "b", "text": "`fe80::/10`", "correct": false, "explanation": "Link-Local – nur auf dem eigenen Segment gültig." },
|
||||||
|
{ "id": "c", "text": "`2000::/3`", "correct": false, "explanation": "Global Unicast (öffentlich routbar)." },
|
||||||
|
{ "id": "d", "text": "`ff00::/8`", "correct": false, "explanation": "Multicast." },
|
||||||
|
{ "id": "e", "text": "`::1/128`", "correct": false, "explanation": "Loopback." }
|
||||||
|
],
|
||||||
|
"explanation": "ULA werden im Internet nicht geroutet, eignen sich aber für interne Netze.",
|
||||||
|
"references": ["RFC 4193"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "109.1-012",
|
||||||
|
"objective": "109.1",
|
||||||
|
"type": "multi",
|
||||||
|
"difficulty": 1,
|
||||||
|
"question": "Welche Protokolle arbeiten auf der **Transportschicht**?",
|
||||||
|
"options": [
|
||||||
|
{ "id": "a", "text": "TCP", "correct": true, "explanation": "Verbindungsorientiert, zuverlässig." },
|
||||||
|
{ "id": "b", "text": "UDP", "correct": true, "explanation": "Verbindungslos." },
|
||||||
|
{ "id": "c", "text": "ICMP", "correct": false, "explanation": "Gehört zur Vermittlungsschicht (IP)." },
|
||||||
|
{ "id": "d", "text": "IP", "correct": false, "explanation": "Vermittlungsschicht." },
|
||||||
|
{ "id": "e", "text": "ARP", "correct": false, "explanation": "Verbindet Sicherungs- und Vermittlungsschicht (IP → MAC)." }
|
||||||
|
],
|
||||||
|
"explanation": "Ports gibt es nur auf der Transportschicht – deshalb haben ICMP-Nachrichten keine Portnummer.",
|
||||||
|
"references": ["RFC 1122"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "109.1-013",
|
||||||
|
"objective": "109.1",
|
||||||
|
"type": "single",
|
||||||
|
"difficulty": 2,
|
||||||
|
"question": "Liegen die Adressen `192.0.2.10/26` und `192.0.2.70/26` im selben Subnetz?",
|
||||||
|
"options": [
|
||||||
|
{ "id": "a", "text": "Nein – `192.0.2.10` liegt in `192.0.2.0/26`, `192.0.2.70` in `192.0.2.64/26`.", "correct": true, "explanation": "/26 teilt das /24 in Blöcke .0–.63, .64–.127, .128–.191, .192–.255." },
|
||||||
|
{ "id": "b", "text": "Ja – beide liegen in `192.0.2.0/26`.", "correct": false, "explanation": "`192.0.2.0/26` reicht nur bis .63." },
|
||||||
|
{ "id": "c", "text": "Ja – ein /26 umfasst .0 bis .127.", "correct": false, "explanation": "Das wäre ein /25." },
|
||||||
|
{ "id": "d", "text": "Nein – weil `192.0.2.70` eine Broadcast-Adresse ist.", "correct": false, "explanation": "Broadcast des Blocks ist .127; .70 ist eine normale Host-Adresse." },
|
||||||
|
{ "id": "e", "text": "Das lässt sich ohne Angabe des Gateways nicht bestimmen.", "correct": false, "explanation": "Adresse und Präfix genügen." }
|
||||||
|
],
|
||||||
|
"explanation": "Hosts in verschiedenen Subnetzen erreichen sich nur über einen Router.",
|
||||||
|
"references": ["RFC 950"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "109.2-007",
|
||||||
|
"objective": "109.2",
|
||||||
|
"type": "single",
|
||||||
|
"difficulty": 1,
|
||||||
|
"question": "Welcher Befehl zeigt den Status aller Netzwerkgeräte, die NetworkManager verwaltet?",
|
||||||
|
"options": [
|
||||||
|
{ "id": "a", "text": "`nmcli device status`", "correct": true, "explanation": "Listet Gerät, Typ, Zustand (connected, disconnected, unmanaged) und Verbindung." },
|
||||||
|
{ "id": "b", "text": "`nmcli general hostname`", "correct": false, "explanation": "Zeigt bzw. setzt den Hostnamen." },
|
||||||
|
{ "id": "c", "text": "`nmcli connection reload`", "correct": false, "explanation": "Liest Verbindungsdateien neu ein." },
|
||||||
|
{ "id": "d", "text": "`ip route`", "correct": false, "explanation": "Zeigt die Routingtabelle des Kernels, nicht den NetworkManager-Status." },
|
||||||
|
{ "id": "e", "text": "`networkctl reload`", "correct": false, "explanation": "Gehört zu systemd-networkd." }
|
||||||
|
],
|
||||||
|
"explanation": "Verbindungen (Profile): `nmcli connection show`; aktivieren mit `nmcli connection up <name>`.",
|
||||||
|
"references": ["man 1 nmcli"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "109.2-008",
|
||||||
|
"objective": "109.2",
|
||||||
|
"type": "fill",
|
||||||
|
"difficulty": 1,
|
||||||
|
"question": "Mit welchem Befehl (mit Argument) aktiviert man unter ifupdown die Schnittstelle `eth0` gemäß `/etc/network/interfaces`?",
|
||||||
|
"answers": ["ifup eth0"],
|
||||||
|
"explanation": "Gegenstück: `ifdown eth0`. Hinweis: ifupdown soll laut LPI künftig aus den Objectives entfallen.",
|
||||||
|
"references": ["man 8 ifup"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "109.2-009",
|
||||||
|
"objective": "109.2",
|
||||||
|
"type": "single",
|
||||||
|
"difficulty": 2,
|
||||||
|
"question": "Wo und mit welcher Dateiendung legt man eine Schnittstellenkonfiguration für **systemd-networkd** ab?",
|
||||||
|
"options": [
|
||||||
|
{ "id": "a", "text": "`/etc/systemd/network/10-eth0.network`", "correct": true, "explanation": "Abschnitte `[Match]` (z. B. `Name=eth0`) und `[Network]` (`Address=`, `Gateway=`, `DNS=` oder `DHCP=yes`)." },
|
||||||
|
{ "id": "b", "text": "`/etc/network/interfaces.d/eth0.conf`", "correct": false, "explanation": "Gehört zu ifupdown." },
|
||||||
|
{ "id": "c", "text": "`/etc/NetworkManager/system-connections/eth0.nmconnection`", "correct": false, "explanation": "Verbindungsprofil von NetworkManager." },
|
||||||
|
{ "id": "d", "text": "`/etc/sysconfig/network-scripts/ifcfg-eth0`", "correct": false, "explanation": "Klassischer Ort der Red-Hat-Familie." },
|
||||||
|
{ "id": "e", "text": "`/etc/systemd/networkd.conf.d/eth0.service`", "correct": false, "explanation": "`.service`-Dateien sind Dienst-Units." }
|
||||||
|
],
|
||||||
|
"explanation": "Status bei networkd: `networkctl list`, `networkctl status eth0`.",
|
||||||
|
"references": ["man 5 systemd.network"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "109.2-010",
|
||||||
|
"objective": "109.2",
|
||||||
|
"type": "single",
|
||||||
|
"difficulty": 1,
|
||||||
|
"question": "Wie schaltet man die Schnittstelle `eth0` mit dem `ip`-Werkzeug ab?",
|
||||||
|
"options": [
|
||||||
|
{ "id": "a", "text": "`ip link set eth0 down`", "correct": true, "explanation": "`ip link set <dev> up|down` setzt den administrativen Zustand." },
|
||||||
|
{ "id": "b", "text": "`ip addr del eth0`", "correct": false, "explanation": "`ip addr del` erwartet eine Adresse und entfernt nur diese." },
|
||||||
|
{ "id": "c", "text": "`ip link eth0 off`", "correct": false, "explanation": "Falsche Syntax (fehlendes `set`, `off` statt `down`)." },
|
||||||
|
{ "id": "d", "text": "`ip route del eth0`", "correct": false, "explanation": "Entfernt Routen, nicht die Schnittstelle." },
|
||||||
|
{ "id": "e", "text": "`ifconfig eth0 off`", "correct": false, "explanation": "Bei ifconfig hieße es `ifconfig eth0 down`." }
|
||||||
|
],
|
||||||
|
"explanation": "Die Änderung ist nicht dauerhaft; Netzwerkdienste können die Schnittstelle wieder aktivieren.",
|
||||||
|
"references": ["man 8 ip-link"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "109.2-011",
|
||||||
|
"objective": "109.2",
|
||||||
|
"type": "multi",
|
||||||
|
"difficulty": 2,
|
||||||
|
"question": "Welche Aussagen zu Hostnamen treffen zu?",
|
||||||
|
"options": [
|
||||||
|
{ "id": "a", "text": "`hostname -f` zeigt den vollqualifizierten Namen (FQDN).", "correct": true, "explanation": "Ermittelt über die Namensauflösung, z. B. `web01.example.org`." },
|
||||||
|
{ "id": "b", "text": "`hostnamectl` ohne Argumente zeigt u. a. den statischen Hostnamen, Betriebssystem und Kernel.", "correct": true, "explanation": "Entspricht `hostnamectl status`." },
|
||||||
|
{ "id": "c", "text": "`/etc/hostname` enthält die IP-Adresse des Rechners.", "correct": false, "explanation": "Sie enthält nur den Namen." },
|
||||||
|
{ "id": "d", "text": "Ein mit `hostname web02` gesetzter Name bleibt nach dem Neustart erhalten.", "correct": false, "explanation": "Nur bis zum Neustart; dauerhaft mit `hostnamectl set-hostname`." },
|
||||||
|
{ "id": "e", "text": "Ein Eintrag in `/etc/hosts` schaltet DNS für alle Namen ab.", "correct": false, "explanation": "`/etc/hosts` ergänzt nur einzelne Namen; die Reihenfolge regelt `nsswitch.conf`." }
|
||||||
|
],
|
||||||
|
"explanation": "systemd unterscheidet statischen, transienten (z. B. per DHCP) und „pretty“ Hostnamen.",
|
||||||
|
"references": ["man 1 hostname", "man 1 hostnamectl"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "109.2-012",
|
||||||
|
"objective": "109.2",
|
||||||
|
"type": "single",
|
||||||
|
"difficulty": 1,
|
||||||
|
"question": "Welches Programm ist ein **DHCP-Client**?",
|
||||||
|
"options": [
|
||||||
|
{ "id": "a", "text": "`dhclient`", "correct": true, "explanation": "Fordert Adresse, Gateway und DNS-Server beim DHCP-Server an." },
|
||||||
|
{ "id": "b", "text": "`dhcpd`", "correct": false, "explanation": "Der ISC-DHCP-**Server**." },
|
||||||
|
{ "id": "c", "text": "`named`", "correct": false, "explanation": "DNS-Server (BIND)." },
|
||||||
|
{ "id": "d", "text": "`ntpd`", "correct": false, "explanation": "NTP-Daemon." },
|
||||||
|
{ "id": "e", "text": "`sshd`", "correct": false, "explanation": "SSH-Server." }
|
||||||
|
],
|
||||||
|
"explanation": "NetworkManager und systemd-networkd bringen eigene DHCP-Clients mit.",
|
||||||
|
"references": ["man 8 dhclient"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "109.2-013",
|
||||||
|
"objective": "109.2",
|
||||||
|
"type": "single",
|
||||||
|
"difficulty": 2,
|
||||||
|
"question": "Wie verbindet man sich mit NetworkManager auf der Befehlszeile mit dem WLAN `Labor`?",
|
||||||
|
"options": [
|
||||||
|
{ "id": "a", "text": "`nmcli device wifi connect Labor password \"<passphrase>\"`", "correct": true, "explanation": "Legt ein Verbindungsprofil an und aktiviert es; `nmcli device wifi list` zeigt verfügbare Netze." },
|
||||||
|
{ "id": "b", "text": "`nmcli wifi join Labor`", "correct": false, "explanation": "Einen Unterbefehl `wifi join` gibt es nicht." },
|
||||||
|
{ "id": "c", "text": "`ip link set wlan0 ssid Labor`", "correct": false, "explanation": "`ip` konfiguriert keine WLAN-Verbindungen." },
|
||||||
|
{ "id": "d", "text": "`iwconfig connect Labor`", "correct": false, "explanation": "Falsche Syntax; `iwconfig` ist zudem veraltet und kann kein WPA." },
|
||||||
|
{ "id": "e", "text": "`hostnamectl wifi Labor`", "correct": false, "explanation": "`hostnamectl` verwaltet den Hostnamen." }
|
||||||
|
],
|
||||||
|
"explanation": "Interaktiv geht es mit `nmtui`. Passwörter nicht in der Shell-History stehen lassen (`--ask`).",
|
||||||
|
"references": ["man 1 nmcli"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "109.3-007",
|
||||||
|
"objective": "109.3",
|
||||||
|
"type": "single",
|
||||||
|
"difficulty": 1,
|
||||||
|
"question": "Welcher Aufruf sendet genau vier Echo Requests und beendet sich dann?",
|
||||||
|
"options": [
|
||||||
|
{ "id": "a", "text": "`ping -c 4 host01`", "correct": true, "explanation": "`-c` (count) begrenzt die Anzahl." },
|
||||||
|
{ "id": "b", "text": "`ping -n 4 host01`", "correct": false, "explanation": "`-n` ist bei Linux „numerische Ausgabe“; die Windows-Syntax hat hier keine Wirkung auf die Anzahl." },
|
||||||
|
{ "id": "c", "text": "`ping -i 4 host01`", "correct": false, "explanation": "`-i` setzt den Abstand zwischen Paketen in Sekunden." },
|
||||||
|
{ "id": "d", "text": "`ping -s 4 host01`", "correct": false, "explanation": "`-s` setzt die Nutzdatengröße." },
|
||||||
|
{ "id": "e", "text": "`ping -w 4 host01`", "correct": false, "explanation": "`-w` ist eine Gesamtzeitgrenze in Sekunden." }
|
||||||
|
],
|
||||||
|
"explanation": "Ohne `-c` läuft ping unter Linux bis Strg+C. IPv6: `ping -6` bzw. `ping6`.",
|
||||||
|
"references": ["man 8 ping"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "109.3-008",
|
||||||
|
"objective": "109.3",
|
||||||
|
"type": "fill",
|
||||||
|
"difficulty": 1,
|
||||||
|
"question": "Mit welchem `ip`-Aufruf (Befehl und Objekt) zeigt man die Neighbor-/ARP-Tabelle an?",
|
||||||
|
"answers": ["ip neigh", "ip neighbor", "ip neighbour", "ip n", "ip neigh show"],
|
||||||
|
"explanation": "Zeigt IP → MAC-Zuordnungen mit Zustand (REACHABLE, STALE, FAILED). Alt: `arp -n`.",
|
||||||
|
"references": ["man 8 ip-neighbour"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "109.3-009",
|
||||||
|
"objective": "109.3",
|
||||||
|
"type": "single",
|
||||||
|
"difficulty": 2,
|
||||||
|
"question": "Welcher Befehl zeigt, über welche Route, welches Gateway und welche Schnittstelle Pakete zu `198.51.100.7` gesendet würden?",
|
||||||
|
"options": [
|
||||||
|
{ "id": "a", "text": "`ip route get 198.51.100.7`", "correct": true, "explanation": "Fragt die Routing-Entscheidung des Kernels für genau dieses Ziel ab." },
|
||||||
|
{ "id": "b", "text": "`ip route show 198.51.100.7`", "correct": false, "explanation": "Zeigt nur Routen, die exakt diesem Präfix entsprechen – meist keine." },
|
||||||
|
{ "id": "c", "text": "`ip addr get 198.51.100.7`", "correct": false, "explanation": "`ip addr` kennt kein `get`." },
|
||||||
|
{ "id": "d", "text": "`ping -r 198.51.100.7`", "correct": false, "explanation": "`-r` umgeht die Routingtabelle." },
|
||||||
|
{ "id": "e", "text": "`dig 198.51.100.7`", "correct": false, "explanation": "`dig` stellt DNS-Anfragen." }
|
||||||
|
],
|
||||||
|
"explanation": "Hilfreich bei mehreren Schnittstellen oder VPNs, um die gewählte Quelladresse zu sehen.",
|
||||||
|
"references": ["man 8 ip-route"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "109.3-010",
|
||||||
|
"objective": "109.3",
|
||||||
|
"type": "single",
|
||||||
|
"difficulty": 2,
|
||||||
|
"question": "Mit welchem Befehl lässt man netcat (OpenBSD-Variante) zu Testzwecken auf TCP-Port 4444 lauschen?",
|
||||||
|
"options": [
|
||||||
|
{ "id": "a", "text": "`nc -l 4444`", "correct": true, "explanation": "`-l` (listen); die traditionelle Variante erwartet `nc -l -p 4444`." },
|
||||||
|
{ "id": "b", "text": "`nc -z 4444`", "correct": false, "explanation": "`-z` prüft nur Verbindungen zu einem Ziel ohne Daten." },
|
||||||
|
{ "id": "c", "text": "`nc -u 4444`", "correct": false, "explanation": "`-u` wählt UDP; es fehlt das Lauschen und ein Ziel." },
|
||||||
|
{ "id": "d", "text": "`nc 4444`", "correct": false, "explanation": "`4444` würde als Hostname interpretiert." },
|
||||||
|
{ "id": "e", "text": "`nc -v 4444`", "correct": false, "explanation": "`-v` macht nur die Ausgabe ausführlicher." }
|
||||||
|
],
|
||||||
|
"explanation": "Test zwischen zwei Rechnern: auf A `nc -l 4444`, auf B `nc A 4444` – getippter Text erscheint auf der Gegenseite.",
|
||||||
|
"references": ["man 1 nc"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "109.3-011",
|
||||||
|
"objective": "109.3",
|
||||||
|
"type": "multi",
|
||||||
|
"difficulty": 2,
|
||||||
|
"question": "Welche Aussagen zu `traceroute` und `tracepath` treffen zu?",
|
||||||
|
"options": [
|
||||||
|
{ "id": "a", "text": "`traceroute` sendet Pakete mit schrittweise steigender TTL.", "correct": true, "explanation": "Jeder Router, bei dem die TTL 0 erreicht, antwortet mit ICMP Time Exceeded und verrät sich so." },
|
||||||
|
{ "id": "b", "text": "`tracepath` benötigt keine Root-Rechte und ermittelt zusätzlich die Path-MTU.", "correct": true, "explanation": "Es nutzt UDP und wertet ICMP-Fehlermeldungen aus." },
|
||||||
|
{ "id": "c", "text": "`traceroute` funktioniert nur, wenn auf dem Ziel TCP-Port 80 offen ist.", "correct": false, "explanation": "Standardmäßig nutzt traceroute UDP auf hohe Ports; TCP ist nur eine Option (`-T`)." },
|
||||||
|
{ "id": "d", "text": "`traceroute` zeigt nur das Ziel, nicht die Zwischenstationen.", "correct": false, "explanation": "Genau die Zwischenstationen (Hops) sind der Zweck." },
|
||||||
|
{ "id": "e", "text": "Ein `* * *` bedeutet immer, dass das Ziel nicht erreichbar ist.", "correct": false, "explanation": "Nur, dass dieser Hop nicht antwortet (oft gefiltert); spätere Hops können trotzdem erscheinen." }
|
||||||
|
],
|
||||||
|
"explanation": "`mtr` kombiniert traceroute und ping fortlaufend.",
|
||||||
|
"references": ["man 8 traceroute", "man 8 tracepath"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "109.3-012",
|
||||||
|
"objective": "109.3",
|
||||||
|
"type": "single",
|
||||||
|
"difficulty": 1,
|
||||||
|
"question": "Welcher Befehl zeigt alle **bestehenden** TCP-Verbindungen mit numerischen Adressen und Ports?",
|
||||||
|
"options": [
|
||||||
|
{ "id": "a", "text": "`ss -tn`", "correct": true, "explanation": "Ohne `-l` oder `-a` zeigt `ss` die verbundenen (nicht lauschenden) Sockets." },
|
||||||
|
{ "id": "b", "text": "`ss -tln`", "correct": false, "explanation": "`-l` zeigt nur lauschende Sockets." },
|
||||||
|
{ "id": "c", "text": "`ss -un`", "correct": false, "explanation": "`-u` zeigt UDP-Sockets." },
|
||||||
|
{ "id": "d", "text": "`ip -s link`", "correct": false, "explanation": "Zeigt Schnittstellenstatistiken." },
|
||||||
|
{ "id": "e", "text": "`netstat -i`", "correct": false, "explanation": "Zeigt die Schnittstellentabelle mit Zählern." }
|
||||||
|
],
|
||||||
|
"explanation": "Filter sind möglich: `ss -tn state established '( dport = :443 )'`.",
|
||||||
|
"references": ["man 8 ss"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "109.3-013",
|
||||||
|
"objective": "109.3",
|
||||||
|
"type": "single",
|
||||||
|
"difficulty": 1,
|
||||||
|
"question": "Welcher Befehl zeigt die Adressen aller Schnittstellen kompakt in **je einer Zeile**?",
|
||||||
|
"options": [
|
||||||
|
{ "id": "a", "text": "`ip -br addr`", "correct": true, "explanation": "`-br` (brief): Name, Zustand, Adressen." },
|
||||||
|
{ "id": "b", "text": "`ip -s link`", "correct": false, "explanation": "Zeigt Statistiken der Schnittstellen." },
|
||||||
|
{ "id": "c", "text": "`ip route`", "correct": false, "explanation": "Zeigt die Routingtabelle." },
|
||||||
|
{ "id": "d", "text": "`ip neigh`", "correct": false, "explanation": "Zeigt die Neighbor-/ARP-Tabelle." },
|
||||||
|
{ "id": "e", "text": "`ss -a`", "correct": false, "explanation": "Zeigt alle Sockets." }
|
||||||
|
],
|
||||||
|
"explanation": "Nur IPv4: `ip -4 -br addr`. Eigene Adressen schnell: `hostname -I`.",
|
||||||
|
"references": ["man 8 ip"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "109.4-004",
|
||||||
|
"objective": "109.4",
|
||||||
|
"type": "single",
|
||||||
|
"difficulty": 2,
|
||||||
|
"question": "`/etc/resolv.conf` enthält `search example.org`. Was bewirkt das?",
|
||||||
|
"options": [
|
||||||
|
{ "id": "a", "text": "Kurze Namen wie `web01` werden zusätzlich als `web01.example.org` aufgelöst.", "correct": true, "explanation": "Die Suchdomäne wird an Namen ohne (ausreichend viele) Punkte angehängt." },
|
||||||
|
{ "id": "b", "text": "Nur Namen unter `example.org` dürfen aufgelöst werden.", "correct": false, "explanation": "`search` beschränkt nichts." },
|
||||||
|
{ "id": "c", "text": "`example.org` wird als DNS-Server verwendet.", "correct": false, "explanation": "DNS-Server stehen in `nameserver`-Zeilen (als IP-Adresse)." },
|
||||||
|
{ "id": "d", "text": "Der Hostname des Rechners wird auf `example.org` gesetzt.", "correct": false, "explanation": "Der Hostname steht in `/etc/hostname`." },
|
||||||
|
{ "id": "e", "text": "Anfragen nach `example.org` werden aus `/etc/hosts` beantwortet.", "correct": false, "explanation": "Die Reihenfolge der Quellen regelt `nsswitch.conf`." }
|
||||||
|
],
|
||||||
|
"explanation": "Bis zu drei `nameserver`-Zeilen werden genutzt; `options timeout:2 attempts:2` steuert Wiederholungen.",
|
||||||
|
"references": ["man 5 resolv.conf"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "109.4-005",
|
||||||
|
"objective": "109.4",
|
||||||
|
"type": "fill",
|
||||||
|
"difficulty": 2,
|
||||||
|
"question": "Welcher Befehl (mit Unterbefehl) zeigt bei **systemd-resolved** die verwendeten DNS-Server je Schnittstelle?",
|
||||||
|
"answers": ["resolvectl status", "resolvectl dns", "systemd-resolve --status"],
|
||||||
|
"explanation": "Bei systemd-resolved zeigt `/etc/resolv.conf` meist nur den lokalen Stub `127.0.0.53`.",
|
||||||
|
"references": ["man 1 resolvectl"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "109.4-006",
|
||||||
|
"objective": "109.4",
|
||||||
|
"type": "single",
|
||||||
|
"difficulty": 1,
|
||||||
|
"question": "Welcher `dig`-Aufruf gibt für `example.org` **nur** die aufgelöste(n) Adresse(n) aus?",
|
||||||
|
"options": [
|
||||||
|
{ "id": "a", "text": "`dig +short example.org`", "correct": true, "explanation": "`+short` unterdrückt alle Abschnitte bis auf die Antwortdaten." },
|
||||||
|
{ "id": "b", "text": "`dig -x example.org`", "correct": false, "explanation": "`-x` macht eine Rückwärtsauflösung und erwartet eine IP-Adresse." },
|
||||||
|
{ "id": "c", "text": "`dig @short example.org`", "correct": false, "explanation": "`@` wählt den abzufragenden Server – hier einen namens `short`." },
|
||||||
|
{ "id": "d", "text": "`host -t short example.org`", "correct": false, "explanation": "`-t` erwartet einen Record-Typ wie `A`, `MX`, `AAAA`." },
|
||||||
|
{ "id": "e", "text": "`nslookup -short example.org`", "correct": false, "explanation": "`nslookup` kennt keine Option `-short`." }
|
||||||
|
],
|
||||||
|
"explanation": "Record-Typ angeben: `dig example.org MX`, `dig AAAA example.org`. Bestimmten Server fragen: `dig @192.0.2.53 example.org`.",
|
||||||
|
"references": ["man 1 dig"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "109.4-007",
|
||||||
|
"objective": "109.4",
|
||||||
|
"type": "multi",
|
||||||
|
"difficulty": 2,
|
||||||
|
"question": "Welche Aussagen zur clientseitigen Namensauflösung treffen zu?",
|
||||||
|
"options": [
|
||||||
|
{ "id": "a", "text": "`getent hosts web01` berücksichtigt die Reihenfolge aus `/etc/nsswitch.conf`, also auch `/etc/hosts`.", "correct": true, "explanation": "`getent` nutzt dieselbe Kette wie normale Programme." },
|
||||||
|
{ "id": "b", "text": "`dig -x 192.0.2.10` fragt den PTR-Eintrag (Rückwärtsauflösung) ab.", "correct": true, "explanation": "Abgefragt wird `10.2.0.192.in-addr.arpa`." },
|
||||||
|
{ "id": "c", "text": "`host -t MX example.org` liefert die A-Records von `example.org`.", "correct": false, "explanation": "Es liefert die **MX**-Records (Mailserver)." },
|
||||||
|
{ "id": "d", "text": "Mit `hosts: dns files` in `nsswitch.conf` wird `/etc/hosts` zuerst befragt.", "correct": false, "explanation": "Die Reihenfolge ist von links nach rechts: zuerst DNS." },
|
||||||
|
{ "id": "e", "text": "Beliebig viele `nameserver`-Zeilen in `/etc/resolv.conf` werden genutzt.", "correct": false, "explanation": "Die glibc nutzt höchstens drei." }
|
||||||
|
],
|
||||||
|
"explanation": "Fehlersuche: `dig` (nur DNS) mit `getent hosts` (NSS) vergleichen.",
|
||||||
|
"references": ["man 5 nsswitch.conf", "man 1 dig"]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -0,0 +1,311 @@
|
|||||||
|
{
|
||||||
|
"$schema": "../schema/questions.schema.json",
|
||||||
|
"format": "lpic-sim-questions",
|
||||||
|
"meta": {
|
||||||
|
"file": "questions_110_set2.json",
|
||||||
|
"brief": "Zweiter Fragensatz zu Topic 110 Sicherheit (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": "110.1-005",
|
||||||
|
"objective": "110.1",
|
||||||
|
"type": "multi",
|
||||||
|
"difficulty": 2,
|
||||||
|
"question": "`umount /mnt/usb` meldet „target is busy“. Mit welchen Befehlen findet man die Prozesse, die das Dateisystem noch verwenden?",
|
||||||
|
"options": [
|
||||||
|
{ "id": "a", "text": "`fuser -vm /mnt/usb`", "correct": true, "explanation": "`-m` betrachtet das ganze eingehängte Dateisystem, `-v` zeigt Benutzer, PID und Zugriffsart." },
|
||||||
|
{ "id": "b", "text": "`lsof /mnt/usb`", "correct": true, "explanation": "Für einen Einhängepunkt listet `lsof` alle offenen Dateien auf diesem Dateisystem." },
|
||||||
|
{ "id": "c", "text": "`df /mnt/usb`", "correct": false, "explanation": "Zeigt nur Belegung und Größe." },
|
||||||
|
{ "id": "d", "text": "`mount -l`", "correct": false, "explanation": "Listet eingehängte Dateisysteme mit Labels." },
|
||||||
|
{ "id": "e", "text": "`ps -m`", "correct": false, "explanation": "`-m` zeigt Threads, keine Dateibezüge." }
|
||||||
|
],
|
||||||
|
"explanation": "Häufige Ursache: Eine Shell steht mit ihrem aktuellen Verzeichnis im Einhängepunkt. `fuser -km` beendet die Prozesse (Vorsicht).",
|
||||||
|
"references": ["man 1 fuser", "man 8 lsof"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "110.1-006",
|
||||||
|
"objective": "110.1",
|
||||||
|
"type": "fill",
|
||||||
|
"difficulty": 2,
|
||||||
|
"question": "In welcher Datei (vollständiger Pfad) legt man über PAM dauerhafte Ressourcenlimits (wie bei `ulimit`) für Benutzer und Gruppen fest?",
|
||||||
|
"answers": ["/etc/security/limits.conf"],
|
||||||
|
"explanation": "Zeilen der Form `<domain> <soft|hard> <item> <wert>`, z. B. `@studenten hard nproc 100`. Ergänzungen in `/etc/security/limits.d/`.",
|
||||||
|
"references": ["man 5 limits.conf"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "110.1-007",
|
||||||
|
"objective": "110.1",
|
||||||
|
"type": "single",
|
||||||
|
"difficulty": 2,
|
||||||
|
"question": "Was erlaubt die sudoers-Zeile `bob ALL=(root) /usr/bin/systemctl restart nginx`?",
|
||||||
|
"options": [
|
||||||
|
{ "id": "a", "text": "`bob` darf auf allen Hosts genau diesen Befehl als root ausführen (mit seinem eigenen Passwort).", "correct": true, "explanation": "Aufbau: Benutzer Hosts=(Zielbenutzer) Befehle." },
|
||||||
|
{ "id": "b", "text": "`bob` darf alle Befehle als root ausführen.", "correct": false, "explanation": "Dafür stünde am Ende `ALL`." },
|
||||||
|
{ "id": "c", "text": "`bob` darf nginx ohne Passwort neu starten.", "correct": false, "explanation": "Ohne Passwortabfrage nur mit `NOPASSWD:` vor dem Befehl." },
|
||||||
|
{ "id": "d", "text": "root darf Befehle als `bob` ausführen.", "correct": false, "explanation": "Die Zeile berechtigt `bob`, nicht root." },
|
||||||
|
{ "id": "e", "text": "`bob` muss das root-Passwort eingeben.", "correct": false, "explanation": "sudo fragt standardmäßig das Passwort des **aufrufenden** Benutzers." }
|
||||||
|
],
|
||||||
|
"explanation": "Gruppen beginnen mit `%`, z. B. `%admin ALL=(ALL:ALL) ALL`. Erlaubte Befehle zeigt `sudo -l`.",
|
||||||
|
"references": ["man 5 sudoers"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "110.1-008",
|
||||||
|
"objective": "110.1",
|
||||||
|
"type": "single",
|
||||||
|
"difficulty": 1,
|
||||||
|
"question": "Was bewirkt `su - anna`?",
|
||||||
|
"options": [
|
||||||
|
{ "id": "a", "text": "Es startet eine Login-Shell als `anna` mit deren Umgebung und Home-Verzeichnis.", "correct": true, "explanation": "`-` (bzw. `-l`) simuliert eine vollständige Anmeldung." },
|
||||||
|
{ "id": "b", "text": "Es wechselt zu `anna`, behält aber Umgebung und Verzeichnis des Aufrufers.", "correct": false, "explanation": "Das macht `su anna` **ohne** Bindestrich." },
|
||||||
|
{ "id": "c", "text": "Es entfernt das Konto `anna`.", "correct": false, "explanation": "Konten löscht `userdel`." },
|
||||||
|
{ "id": "d", "text": "Es führt einen Befehl als root aus und fragt nach dem Passwort von `anna`.", "correct": false, "explanation": "`su` fragt nach dem Passwort des **Zielbenutzers** (hier anna), außer root ruft auf." },
|
||||||
|
{ "id": "e", "text": "Es sperrt `anna` für die Dauer der Sitzung.", "correct": false, "explanation": "`su` sperrt keine Konten." }
|
||||||
|
],
|
||||||
|
"explanation": "Einzelnen Befehl: `su - anna -c \"befehl\"`. Ohne Benutzername wechselt `su` zu root.",
|
||||||
|
"references": ["man 1 su"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "110.1-009",
|
||||||
|
"objective": "110.1",
|
||||||
|
"type": "single",
|
||||||
|
"difficulty": 1,
|
||||||
|
"question": "Welcher Befehl zeigt **fehlgeschlagene** Anmeldeversuche aus `/var/log/btmp`?",
|
||||||
|
"options": [
|
||||||
|
{ "id": "a", "text": "`lastb`", "correct": true, "explanation": "„last bad“; nur für root lesbar." },
|
||||||
|
{ "id": "b", "text": "`last`", "correct": false, "explanation": "Zeigt erfolgreiche Anmeldungen aus `wtmp`." },
|
||||||
|
{ "id": "c", "text": "`lastlog`", "correct": false, "explanation": "Zeigt je Benutzer die letzte Anmeldung." },
|
||||||
|
{ "id": "d", "text": "`who`", "correct": false, "explanation": "Zeigt aktuell angemeldete Benutzer." },
|
||||||
|
{ "id": "e", "text": "`w`", "correct": false, "explanation": "Zeigt angemeldete Benutzer und deren Aktivität." }
|
||||||
|
],
|
||||||
|
"explanation": "Viele fehlgeschlagene SSH-Anmeldungen sind ein Hinweis auf Brute-Force-Versuche (Abhilfe z. B. Schlüssel statt Passwort).",
|
||||||
|
"references": ["man 1 last"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "110.1-010",
|
||||||
|
"objective": "110.1",
|
||||||
|
"type": "multi",
|
||||||
|
"difficulty": 2,
|
||||||
|
"question": "Welche Aussagen zu `nmap` treffen zu?",
|
||||||
|
"options": [
|
||||||
|
{ "id": "a", "text": "`nmap -sT host01` führt einen TCP-Connect-Scan durch.", "correct": true, "explanation": "Baut vollständige TCP-Verbindungen auf; braucht keine Root-Rechte." },
|
||||||
|
{ "id": "b", "text": "Portscans sollten nur gegen eigene Systeme oder mit ausdrücklicher Erlaubnis laufen.", "correct": true, "explanation": "Fremde Systeme zu scannen kann rechtliche Folgen haben." },
|
||||||
|
{ "id": "c", "text": "`nmap` ändert die Firewall-Regeln des Ziels.", "correct": false, "explanation": "`nmap` beobachtet nur, es konfiguriert nichts." },
|
||||||
|
{ "id": "d", "text": "`nmap -p 22 host01` scannt alle Ports außer 22.", "correct": false, "explanation": "`-p 22` scannt **nur** Port 22." },
|
||||||
|
{ "id": "e", "text": "`nmap` kann nur den eigenen Rechner prüfen.", "correct": false, "explanation": "Es scannt beliebige erreichbare Hosts und Netze." }
|
||||||
|
],
|
||||||
|
"explanation": "Ohne Angabe prüft nmap die 1000 häufigsten Ports. `-sU` scannt UDP, `-sV` erkennt Dienstversionen.",
|
||||||
|
"references": ["man 1 nmap"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "110.2-006",
|
||||||
|
"objective": "110.2",
|
||||||
|
"type": "single",
|
||||||
|
"difficulty": 2,
|
||||||
|
"question": "Was bewirkt `systemctl mask cups.service`?",
|
||||||
|
"options": [
|
||||||
|
{ "id": "a", "text": "Die Unit wird auf `/dev/null` verlinkt und kann weder manuell noch als Abhängigkeit gestartet werden.", "correct": true, "explanation": "Stärker als `disable`; rückgängig mit `systemctl unmask`." },
|
||||||
|
{ "id": "b", "text": "Der Dienst wird nur beim nächsten Start nicht automatisch gestartet.", "correct": false, "explanation": "Das ist `disable`; manuell starten ginge weiterhin." },
|
||||||
|
{ "id": "c", "text": "Der Dienst wird versteckt, läuft aber weiter.", "correct": false, "explanation": "`mask` stoppt einen laufenden Dienst nicht automatisch – starten lässt er sich danach aber nicht mehr." },
|
||||||
|
{ "id": "d", "text": "Die Protokollausgabe des Dienstes wird unterdrückt.", "correct": false, "explanation": "`mask` hat mit Logging nichts zu tun." },
|
||||||
|
{ "id": "e", "text": "Der Dienst läuft danach nur noch für root.", "correct": false, "explanation": "`mask` kennt keine Benutzerbeschränkung." }
|
||||||
|
],
|
||||||
|
"explanation": "Zum sofortigen Stoppen zusätzlich `--now` angeben. Status `masked` zeigt `systemctl status` bzw. `list-unit-files`.",
|
||||||
|
"references": ["man 1 systemctl"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "110.2-007",
|
||||||
|
"objective": "110.2",
|
||||||
|
"type": "single",
|
||||||
|
"difficulty": 1,
|
||||||
|
"question": "Was passiert, wenn ein Benutzer mit der Login-Shell `/usr/sbin/nologin` sich per SSH anmelden will?",
|
||||||
|
"options": [
|
||||||
|
{ "id": "a", "text": "Eine Meldung wird ausgegeben und die Verbindung beendet; eine interaktive Sitzung entsteht nicht.", "correct": true, "explanation": "`nologin` gibt „This account is currently not available.“ (bzw. `/etc/nologin.txt`) aus und endet mit Fehler." },
|
||||||
|
{ "id": "b", "text": "Der Benutzer erhält eine eingeschränkte Bash.", "correct": false, "explanation": "Es wird gar keine Shell gestartet." },
|
||||||
|
{ "id": "c", "text": "Das Konto wird dauerhaft gelöscht.", "correct": false, "explanation": "`nologin` ändert keine Konten." },
|
||||||
|
{ "id": "d", "text": "Die Anmeldung gelingt nur mit SSH-Schlüssel.", "correct": false, "explanation": "Auch mit Schlüssel endet die Sitzung sofort." },
|
||||||
|
{ "id": "e", "text": "Es gilt nur für root, normale Benutzer sind nicht betroffen.", "correct": false, "explanation": "Es gilt für jedes Konto mit dieser Shell." }
|
||||||
|
],
|
||||||
|
"explanation": "Nicht verwechseln mit `/etc/nologin`: Diese Datei sperrt **alle** Nicht-root-Anmeldungen, solange sie existiert.",
|
||||||
|
"references": ["man 8 nologin"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "110.2-008",
|
||||||
|
"objective": "110.2",
|
||||||
|
"type": "fill",
|
||||||
|
"difficulty": 2,
|
||||||
|
"question": "Mit welchem `systemctl`-Aufruf (Befehl und Unterbefehl) listet man alle Socket-Units mit ihren lauschenden Adressen auf?",
|
||||||
|
"answers": ["systemctl list-sockets"],
|
||||||
|
"explanation": "Socket-Units (`*.socket`) lauschen stellvertretend und starten den Dienst bei Bedarf.",
|
||||||
|
"references": ["man 1 systemctl", "man 5 systemd.socket"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "110.2-009",
|
||||||
|
"objective": "110.2",
|
||||||
|
"type": "single",
|
||||||
|
"difficulty": 2,
|
||||||
|
"question": "Welche Aussage zu **xinetd** trifft zu?",
|
||||||
|
"options": [
|
||||||
|
{ "id": "a", "text": "Als Super-Server lauscht er für mehrere Dienste und startet sie erst bei einer Verbindung; Konfiguration in `/etc/xinetd.conf` und `/etc/xinetd.d/`.", "correct": true, "explanation": "In `/etc/xinetd.d/<dienst>` schaltet `disable = yes` einen Dienst ab." },
|
||||||
|
{ "id": "b", "text": "xinetd ist eine Firewall auf Paketebene.", "correct": false, "explanation": "Paketfilter sind z. B. nftables/iptables." },
|
||||||
|
{ "id": "c", "text": "xinetd ersetzt den Kernel-Scheduler.", "correct": false, "explanation": "Kein Zusammenhang." },
|
||||||
|
{ "id": "d", "text": "xinetd wird über `/etc/inittab` konfiguriert.", "correct": false, "explanation": "`/etc/inittab` gehört zu SysV-init." },
|
||||||
|
{ "id": "e", "text": "xinetd ist der Nachfolger von systemd.", "correct": false, "explanation": "Umgekehrt: systemd-Socket-Units übernehmen heute meist diese Aufgabe." }
|
||||||
|
],
|
||||||
|
"explanation": "Auf modernen Systemen selten; Prinzip „Dienste nur bei Bedarf starten“ lebt in systemd-Socket-Aktivierung weiter.",
|
||||||
|
"references": ["man 8 xinetd", "man 5 xinetd.conf"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "110.2-010",
|
||||||
|
"objective": "110.2",
|
||||||
|
"type": "multi",
|
||||||
|
"difficulty": 1,
|
||||||
|
"question": "Welche Maßnahmen verringern die **Angriffsfläche** eines Servers?",
|
||||||
|
"options": [
|
||||||
|
{ "id": "a", "text": "Nicht benötigte Dienste stoppen und deaktivieren", "correct": true, "explanation": "Jeder laufende Netzwerkdienst ist ein möglicher Angriffspunkt." },
|
||||||
|
{ "id": "b", "text": "Dienste, die nur lokal gebraucht werden, nur an `127.0.0.1` binden", "correct": true, "explanation": "Dann sind sie aus dem Netz nicht erreichbar." },
|
||||||
|
{ "id": "c", "text": "`/etc/shadow` für alle lesbar machen (644)", "correct": false, "explanation": "Damit könnten alle Benutzer die Hashes offline knacken." },
|
||||||
|
{ "id": "d", "text": "SSH-Anmeldung als root mit Passwort erlauben", "correct": false, "explanation": "Erhöht das Risiko durch Passwortraten auf das mächtigste Konto." },
|
||||||
|
{ "id": "e", "text": "Telnet für die Fernwartung verwenden", "correct": false, "explanation": "Telnet überträgt alles inklusive Passwort im Klartext." }
|
||||||
|
],
|
||||||
|
"explanation": "Vorgehen: lauschende Ports ermitteln (`ss -tulpn`), unnötige Dienste abschalten, Rest mit Firewall und Updates absichern.",
|
||||||
|
"references": ["LPI 102-500 Objective 110.2"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "110.2-011",
|
||||||
|
"objective": "110.2",
|
||||||
|
"type": "single",
|
||||||
|
"difficulty": 2,
|
||||||
|
"question": "Welche Aussage zur **Socket-Aktivierung** bei systemd trifft zu?",
|
||||||
|
"options": [
|
||||||
|
{ "id": "a", "text": "systemd lauscht selbst auf dem Socket und startet den zugehörigen Dienst erst bei der ersten Verbindung.", "correct": true, "explanation": "Die `.socket`-Unit hält den Port offen und übergibt ihn an den Dienst." },
|
||||||
|
{ "id": "b", "text": "Der Dienst muss vorher manuell gestartet sein, sonst gehen Verbindungen verloren.", "correct": false, "explanation": "Gerade das Gegenteil: Verbindungen werden gepuffert, bis der Dienst läuft." },
|
||||||
|
{ "id": "c", "text": "Socket-Units ersetzen die Firewall.", "correct": false, "explanation": "Sie regeln nicht, **wer** sich verbinden darf." },
|
||||||
|
{ "id": "d", "text": "Socket-Aktivierung funktioniert nur mit UDP.", "correct": false, "explanation": "TCP, UDP und Unix-Sockets werden unterstützt." },
|
||||||
|
{ "id": "e", "text": "Socket-Units werden in `/etc/xinetd.d/` konfiguriert.", "correct": false, "explanation": "Sie liegen wie andere Units z. B. unter `/etc/systemd/system/`." }
|
||||||
|
],
|
||||||
|
"explanation": "Beispiel: `ssh.socket` statt `ssh.service`. Auch eine deaktivierte Service-Unit kann so über ihre aktive Socket-Unit gestartet werden – beim Härten beide prüfen.",
|
||||||
|
"references": ["man 5 systemd.socket"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "110.3-007",
|
||||||
|
"objective": "110.3",
|
||||||
|
"type": "single",
|
||||||
|
"difficulty": 1,
|
||||||
|
"question": "Wie überträgt man den eigenen öffentlichen SSH-Schlüssel am einfachsten auf den Server `host01`?",
|
||||||
|
"options": [
|
||||||
|
{ "id": "a", "text": "`ssh-copy-id anna@host01`", "correct": true, "explanation": "Hängt den öffentlichen Schlüssel an `~/.ssh/authorized_keys` auf dem Server an und setzt passende Rechte." },
|
||||||
|
{ "id": "b", "text": "`scp ~/.ssh/id_ed25519 anna@host01:`", "correct": false, "explanation": "Kopiert den **privaten** Schlüssel – ein Sicherheitsproblem und wirkungslos für die Anmeldung." },
|
||||||
|
{ "id": "c", "text": "`ssh-add anna@host01`", "correct": false, "explanation": "`ssh-add` lädt Schlüssel in den lokalen ssh-agent." },
|
||||||
|
{ "id": "d", "text": "`ssh-keyscan host01`", "correct": false, "explanation": "Holt die **Host**-Schlüssel des Servers ab." },
|
||||||
|
{ "id": "e", "text": "`ssh-agent anna@host01`", "correct": false, "explanation": "`ssh-agent` hält Schlüssel im Speicher, überträgt nichts." }
|
||||||
|
],
|
||||||
|
"explanation": "Mit `-i ~/.ssh/datei.pub` wählt man einen bestimmten Schlüssel.",
|
||||||
|
"references": ["man 1 ssh-copy-id"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "110.3-008",
|
||||||
|
"objective": "110.3",
|
||||||
|
"type": "fill",
|
||||||
|
"difficulty": 1,
|
||||||
|
"question": "Wie heißt die Konfigurationsdatei des OpenSSH-**Servers**? (vollständiger Pfad)",
|
||||||
|
"answers": ["/etc/ssh/sshd_config"],
|
||||||
|
"explanation": "Die Client-Konfiguration ist `/etc/ssh/ssh_config` bzw. `~/.ssh/config`. Nach Änderungen `sshd -t` prüfen und den Dienst neu laden.",
|
||||||
|
"references": ["man 5 sshd_config"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "110.3-009",
|
||||||
|
"objective": "110.3",
|
||||||
|
"type": "single",
|
||||||
|
"difficulty": 1,
|
||||||
|
"question": "Welcher GnuPG-Befehl listet die öffentlichen Schlüssel im eigenen Schlüsselbund auf?",
|
||||||
|
"options": [
|
||||||
|
{ "id": "a", "text": "`gpg --list-keys`", "correct": true, "explanation": "Kurzform `gpg -k`." },
|
||||||
|
{ "id": "b", "text": "`gpg --list-secret-keys`", "correct": false, "explanation": "Listet die **privaten** Schlüssel (`-K`)." },
|
||||||
|
{ "id": "c", "text": "`gpg --export`", "correct": false, "explanation": "Gibt öffentliche Schlüssel zur Weitergabe aus (binär oder mit `--armor`)." },
|
||||||
|
{ "id": "d", "text": "`gpg --import`", "correct": false, "explanation": "Importiert Schlüssel aus einer Datei." },
|
||||||
|
{ "id": "e", "text": "`gpg --verify`", "correct": false, "explanation": "Prüft Signaturen." }
|
||||||
|
],
|
||||||
|
"explanation": "Schlüsselbund liegt in `~/.gnupg/`. Schlüssel verteilen: `gpg --export --armor anna@example.org > anna.asc`.",
|
||||||
|
"references": ["man 1 gpg"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "110.3-010",
|
||||||
|
"objective": "110.3",
|
||||||
|
"type": "single",
|
||||||
|
"difficulty": 2,
|
||||||
|
"question": "Zu `release.tar.gz` gibt es die abgetrennte Signatur `release.tar.gz.sig`. Wie prüft man sie?",
|
||||||
|
"options": [
|
||||||
|
{ "id": "a", "text": "`gpg --verify release.tar.gz.sig release.tar.gz`", "correct": true, "explanation": "Erst die Signatur, dann die signierte Datei; der öffentliche Schlüssel des Signierers muss importiert sein." },
|
||||||
|
{ "id": "b", "text": "`gpg --decrypt release.tar.gz`", "correct": false, "explanation": "Die Datei ist nicht verschlüsselt, nur signiert." },
|
||||||
|
{ "id": "c", "text": "`gpg --sign release.tar.gz.sig`", "correct": false, "explanation": "Würde selbst eine neue Signatur erstellen." },
|
||||||
|
{ "id": "d", "text": "`sha256sum release.tar.gz.sig`", "correct": false, "explanation": "Berechnet nur eine Prüfsumme der Signaturdatei." },
|
||||||
|
{ "id": "e", "text": "`gpg --list-keys release.tar.gz`", "correct": false, "explanation": "Listet Schlüssel, prüft nichts." }
|
||||||
|
],
|
||||||
|
"explanation": "„Good signature“ heißt nur: passt zum Schlüssel. Ob der Schlüssel vertrauenswürdig ist, zeigt der Fingerabdruck-Abgleich über einen sicheren Kanal.",
|
||||||
|
"references": ["man 1 gpg"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "110.3-011",
|
||||||
|
"objective": "110.3",
|
||||||
|
"type": "single",
|
||||||
|
"difficulty": 1,
|
||||||
|
"question": "Wie lädt man den privaten Schlüssel `~/.ssh/id_ed25519` in einen laufenden **ssh-agent**?",
|
||||||
|
"options": [
|
||||||
|
{ "id": "a", "text": "`ssh-add ~/.ssh/id_ed25519`", "correct": true, "explanation": "Fragt einmal nach der Passphrase; danach nutzt ssh den Schlüssel aus dem Agent. `ssh-add -l` listet geladene Schlüssel." },
|
||||||
|
{ "id": "b", "text": "`ssh -A ~/.ssh/id_ed25519`", "correct": false, "explanation": "`-A` aktiviert Agent-Weiterleitung für eine Verbindung." },
|
||||||
|
{ "id": "c", "text": "`ssh-keygen -a ~/.ssh/id_ed25519`", "correct": false, "explanation": "`-a` legt die Anzahl der KDF-Runden beim Erzeugen fest." },
|
||||||
|
{ "id": "d", "text": "`ssh-copy-id ~/.ssh/id_ed25519`", "correct": false, "explanation": "Überträgt einen öffentlichen Schlüssel auf einen Server." },
|
||||||
|
{ "id": "e", "text": "`ssh-agent -k`", "correct": false, "explanation": "`-k` beendet den laufenden Agent." }
|
||||||
|
],
|
||||||
|
"explanation": "Agent starten (falls nicht durch die Desktop-Sitzung geschehen): `eval \"$(ssh-agent)\"`.",
|
||||||
|
"references": ["man 1 ssh-add", "man 1 ssh-agent"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "110.3-012",
|
||||||
|
"objective": "110.3",
|
||||||
|
"type": "multi",
|
||||||
|
"difficulty": 2,
|
||||||
|
"question": "Welche Aussagen zu GnuPG treffen zu?",
|
||||||
|
"options": [
|
||||||
|
{ "id": "a", "text": "Man verschlüsselt mit dem **öffentlichen** Schlüssel des Empfängers.", "correct": true, "explanation": "Nur der Inhaber des passenden privaten Schlüssels kann entschlüsseln." },
|
||||||
|
{ "id": "b", "text": "Man signiert mit dem eigenen **privaten** Schlüssel.", "correct": true, "explanation": "Jeder mit dem öffentlichen Schlüssel kann die Signatur prüfen." },
|
||||||
|
{ "id": "c", "text": "Der Empfänger entschlüsselt mit dem öffentlichen Schlüssel des Absenders.", "correct": false, "explanation": "Entschlüsselt wird mit dem eigenen privaten Schlüssel." },
|
||||||
|
{ "id": "d", "text": "Ein Widerrufszertifikat dient zum Verschlüsseln von Dateien.", "correct": false, "explanation": "Es erklärt einen Schlüssel für ungültig, z. B. nach Verlust." },
|
||||||
|
{ "id": "e", "text": "`~/.gnupg` sollte für alle lesbar sein, damit andere die Schlüssel finden.", "correct": false, "explanation": "Das Verzeichnis enthält private Schlüssel und muss privat bleiben (700); öffentliche Schlüssel verteilt man per Export." }
|
||||||
|
],
|
||||||
|
"explanation": "Hintergrund-Daemon: `gpg-agent` verwaltet Passphrasen; Widerrufszertifikat erzeugen mit `gpg --gen-revoke`.",
|
||||||
|
"references": ["man 1 gpg"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "110.3-013",
|
||||||
|
"objective": "110.3",
|
||||||
|
"type": "fill",
|
||||||
|
"difficulty": 1,
|
||||||
|
"question": "Mit welcher `ssh`-Option gibt man eine bestimmte Datei mit dem privaten Schlüssel für die Anmeldung an? (nur die Option)",
|
||||||
|
"answers": ["-i"],
|
||||||
|
"explanation": "Beispiel: `ssh -i ~/.ssh/labor_ed25519 anna@host01`. Dauerhaft in `~/.ssh/config` mit `IdentityFile`.",
|
||||||
|
"references": ["man 1 ssh"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "110.3-014",
|
||||||
|
"objective": "110.3",
|
||||||
|
"type": "single",
|
||||||
|
"difficulty": 2,
|
||||||
|
"question": "Welche Einstellung in `/etc/ssh/sshd_config` verbietet die Anmeldung per **Passwort** für alle Benutzer?",
|
||||||
|
"options": [
|
||||||
|
{ "id": "a", "text": "`PasswordAuthentication no`", "correct": true, "explanation": "Danach sind nur noch Schlüssel bzw. andere Verfahren möglich – vorher Schlüssel-Anmeldung testen!" },
|
||||||
|
{ "id": "b", "text": "`PermitRootLogin no`", "correct": false, "explanation": "Verbietet nur die Anmeldung als root." },
|
||||||
|
{ "id": "c", "text": "`PubkeyAuthentication no`", "correct": false, "explanation": "Verbietet die Schlüssel-Anmeldung – das Gegenteil." },
|
||||||
|
{ "id": "d", "text": "`AllowUsers none`", "correct": false, "explanation": "Erlaubt nur einem Benutzer namens `none` die Anmeldung." },
|
||||||
|
{ "id": "e", "text": "`X11Forwarding no`", "correct": false, "explanation": "Betrifft nur die X11-Weiterleitung." }
|
||||||
|
],
|
||||||
|
"explanation": "Abhängig von PAM sollte zusätzlich `KbdInteractiveAuthentication no` gesetzt sein, sonst ist eine Passwortabfrage über PAM noch möglich.",
|
||||||
|
"references": ["man 5 sshd_config"]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -24,5 +24,5 @@
|
|||||||
1. Richtwert 65 % für „bestanden“ – anpassen?
|
1. Richtwert 65 % für „bestanden“ – anpassen?
|
||||||
2. Teilpunkte bei Mehrfachauswahl: von LPI nicht dokumentiert; derzeit alles-oder-nichts.
|
2. Teilpunkte bei Mehrfachauswahl: von LPI nicht dokumentiert; derzeit alles-oder-nichts.
|
||||||
3. Sitzungs-Export und `localStorage` enthalten die Fragen einer Sitzung im Klartext.
|
3. Sitzungs-Export und `localStorage` enthalten die Fragen einer Sitzung im Klartext.
|
||||||
4. Alle 180 Fragen sind KI-erstellt (Claude Opus 5.5) und **noch nicht fachlich geprüft** – Aufgabe der Prüfer ([REVIEW.md](REVIEW.md)).
|
4. Alle 400 Fragen (je 200 für 101 und 102; zweiter Satz in `questions_*_set2.json`, 30.10.2026) sind KI-erstellt (Claude Opus 5.5) und **noch nicht fachlich geprüft** – Aufgabe der Prüfer ([REVIEW.md](REVIEW.md)).
|
||||||
5. Nicht getestet: Safari, echte Mobilgeräte.
|
5. Nicht getestet: Safari, echte Mobilgeräte.
|
||||||
@@ -3,11 +3,11 @@
|
|||||||
* @brief Fragenbank (verschlüsselt) – ERZEUGT von tools/build_bank.py, nicht von Hand bearbeiten
|
* @brief Fragenbank (verschlüsselt) – ERZEUGT von tools/build_bank.py, nicht von Hand bearbeiten
|
||||||
* @author Björn Runden <br@runden.de>
|
* @author Björn Runden <br@runden.de>
|
||||||
* @owner Björn Runden <br@runden.de>
|
* @owner Björn Runden <br@runden.de>
|
||||||
* @version 2026-10-29T22:40:55Z
|
* @version 2026-10-30T10:57:52Z
|
||||||
*/
|
*/
|
||||||
window.LPIC_BANK = {
|
window.LPIC_BANK = {
|
||||||
"generated": "2026-10-29T22:40:55Z",
|
"generated": "2026-10-30T10:57:52Z",
|
||||||
"build": "179de2341e47860b1d8ad91f2d6dad734ec7915808c0fd02d276c13a6b2ed86a",
|
"build": "179de2341e47860b1d8ad91f2d6dad734ec7915808c0fd02d276c13a6b2ed86a",
|
||||||
"rev": "1ae157f0c162c0674a00e01c",
|
"rev": "2caf2bb88d32f29371052f6c",
|
||||||
"payload": "teKT1gUgtOV6NRIL1VW9Jr+HID9gbX2p1wMdJFLJIwDPdzP2sKUZB7RQjQDr17hweZf8jAGfie8P0yyoXihOLYh3VplFV/xeCdO+4na9D7Qy8RQX5bcY2eBptZJMAnEW/Bytj3EQ73JOR5lC+XIXhuJTBP9C8QEW8GR9YkmNVQVXV4fEu1Zpd3cs02SqjyKG7yKx29nB+Cs2Md1TwoG7QZROEtQdzoGLWJ9/apgjJVs2ak9HcpAmo2IYbjQ2XcbYeU+k8teRObPkjFHy7kjDn09pR7xDz4HhHBCMdd9kKVaNd748gNodxCcB1JMoz/2cXcWdf3WINCR831WDl+RqOMsrRFfsN2Hg3YVVq8YA0L77EgEkyaN1d23vI8AjZFso0IkyweW/bdW12So+mwjAzMhZXvTahZVNaqhg4uuvb+Px7lDv3bDp13vH3LejKf0/+VMHKtVEoCDIu/fzgf+FfCP5tJEYw/gG/+g2hBcXegu8yTbU/0nxaEnP7sDulXzAiSrnGdRzK47/AV+vqDrCzA26gN2luHVxw61a4v4JIPpR+WiEQA9jBW+gLXw717GbVgnRupxlLAc8sn2z01VfbYHONqn3UCeHXhoBn9ANuBIRiXTHfZwPNeH0Isvx797ESOkwSvYb23/BIXJiIjGUqeEwtAihb06ZNpszHJV1SLhuqFlYPo8lpf/cmghGvD9k3EK+dFmakXTYqtl7gQjkR8RGBrBcZqBKcyrJxXY6Dr/Q3zxR43OJYIMoe/Mckl7c3uIxfYfbvYUyUIj3szhKFbmW6O4DeAWjVgvqFYc01/hr9U9xjRXJcsE4agTJK1iYMASXjYOY6RZ6aBBwoIevb4f+eP4RSifO514PxcyiKz/UfGAMsczmVEaHbiHOPNdSht4SneY9ZiDmhcJ8oyvwz6gXX3Q+x5WuLzWn1nhC8xxOG/hLKZz/7WEA179fU3Y3CNHu0okimhKbMTFe6XWoHNPBcNDdMVYn83lTJGDGvZ7iP6cSnKOKGBaMyG77JNwdrw2VKV9pzdEgGhNE4t6bi3uIssssa8dX86j7yIVpukLjqBTM2StxJaIDugQSv75UEge/REgCFMfEhZNbLvZLEPrpND+6eKEy3+AfEjmZhMDuMy18oxeC4CjbK5FSS6gkKvM9Xqu3me0L5IPHvFr2+SL42ozW/QvJAz8qeFUKgyX3XCv+62LsUNlASyL3EPVuQqNl2vVhn2Fe9WA0v+4Yq9MpAxWzspUGy4u3xiOzDnp5DwlR0PHMwicHNgVoZLNXmFQ2rfWkIt/cacFsY4o/hoZdFBelOLKgrq4T0fjv57FYVwXQBRI2Z3rvLVGU5Bslx0K39HJJC6beyreFDiLAK9fKMtdZtrLkRoRFmNCfnk3UMec77ya6ne2sQmaBL9UaUarwzY8GQsdQ4BT+UKBn9JVulMSpDsOdEFml3SXp9daX3avgZk6JlvsLNxJL2At+oGch3XP6ou3RMivjxsndJRkkPhHyJJVNSSZsvomteZz8YuwmPSnoV6GG6iB4ekocJ3qXNLiJ/qgpXnEQbBxtXZBj5yxBUJ/N8I+T9ftpMjjikESC2+pU9WytVvwJZHDk0MizuCejNt+rNnU32a1vd3H/jPnyOZZBkj+RKBvfZf6S+lWUY/2a9BbFv712xgkGsIGSmVn+znUE17MMJclHC2UCiHmpX22dgauWrC2wagVj4EpgX0st96YIW4tLRbvSz0t+sZ0qB9ZuDekYyKeZKulrFcwNM8aw/NvZYFGpJJQQUUv78Es8JQHL/xMEykmNvzcjbegpsY62YvAw9lJwkT1gaAxTPrcLmLa1lRrV/qFRRzx2o3MKb2/GDKZJ7EZPzs9TalnRHJtjg66iMDzUOk7/t/dA9CHnXh64/NxRd6EJINXr+/PN685ZDotGm3hhgIDC5VfBsj9PtBuZar3rUytRHOjtnvJDXg+HbysKzW4etj3gMbx/3wOiN8DeVhhl8GG4JKJLCMv65/wa96UxpJp+D4ScEZ9QJN9mFefWJ1Gm6sext0F/TKzvx3YEdFD6W8G9GvuRn/fIeq8aUSX2wsrTtX5YQGz549cl8mCBhrUs4tS2u+cx6ij6rM1H3qpMnw8SlesAXbMi2jAcwbT4zr5d+d/wm9eDgzkQJ2qyTPC/6JZlZbiybFLi/pM8afZE9tzEQoctpgsNSVUElVEohqofN5PZNAsp7EqGUGsVTja9TENoqte+tAu/muplAIU9zBrznsawOi+DzqgcOLBi58urxajVFubC0aSCLOP8ZE+bAA0ArsZwnKcOUE2wo6wjHOYNYAFTIXO0vFnlKq9XRz8CgTjwZUdJkKiMp65YegOouU9WOApyCBbem9aR7bVsT5EZcsf21yybPp3zUIyxcY9srUH7mBru5GjOysuiBjUqhpS6TZJAis3x4IU+eB5ssicu8RsdbBopY8uvfaUCS+9a5KG0Ikrb+rWiXk7IE7DYg125UOCOyZi9Q//bWxJX8DA4/ILfs2EihiFIVnvmN2fR90cq0+mOilzddftflZRzNWf9gGjYFiXTIxdhKMHms431FrWNWpaUCAT9vQrmsOvKiqxljQesHL5VnB02SufvTRpJQrShsEr/4FVIUMS0q9MMY1arPsF6AGJavdxBGw1TbHjkuYnDc9qUdL3Erudyqc3iA/G1aw/EiXmD32dCThzDlb9jp2x8t9rBRt0+LjA2ZX/w/ljwS0El8KOK/9tAGeXBSXES9xS8nryFQT0VyZmBQWxzmOZE1X+FcIXXDkdT4g1iOyZbJyw4T2HGpKrKLbEzAN3YfGlRf7MHvWnHinVqwHq38X7cH77PIHazuJ9EYies2MU+i1fHn3RsTpdEhwh9VXTijc8EjELOgmppkuApPVNXy9uck6ypdnSWAslmhwabBEkfftmTR0g0uWBcAApj74sG1gDpAsD1mFarUX759lgBrICbKzwn6TIXs0MVPwBW6DLz0ZfoySfHqCwG3Ma4LwrRqoFMX4g/GSrm/KxupwO11ZGxliousumUEY3zAiUjzw+Cz6mZxzVHfWLtX/tetlDGApLJDNjqTxUSB4bKRoMA+DCinFhqL2R3MUdSyPY3hBtP2yviQQXOUhukIj84ZoRRrrmc6XjRxVuDxDkVB0NgIV4qaXKtHTOhzhy1MdOug6/5Ltmr7QOIqJfiKzGUZiwdUn1+ByHnOJPkYCHUQ72LZO6pxebp66aUvhlZ76GAzauZNkjPKk1Cn4RVcU1cWHsYcCOvGZ3UEm/7RE3Ggs2OHKba61hdLBnsJ3zMF00oA0OtCgf0Vr1uT0sSw8WcBfvmmQ3sbtKLj+1MjmKL06VJIbS0vfrlgwPYmpCM7kD9KNAVO0ETa205oS0GPJey50uLHC3lYwf+g1RqtM5K80Rgy3aakbJicBqzelR2qQnWmLO1vBPZyFe1alCaKEsuRIBn35lwAQt1/p6YP9JZb3ChGipw8r5s1BeHZdqsqLI5sW5fnpgU9NU7tmfdQdcu6h+gfDBCv+zOiN38NAqssCDZswuOopd/3H2RcUlvD4eQAkrRDytbm6MOo/1UbLEf58DFOyKDnDzGMK4ReByCN4TVkT+2XiXB65TSE2IxEGhPkFi3JY7meAnS5E7VXyqjAH7gHchQ3TVWIHXLIk3oJbsnIG47W5phX5asBG9aEVddt1mUpEmzt5+lZ7Y+Nm/uCjqkknuNkiHaapR5krWi73+undXqgXmpWnj2+z22qONanzwdbkd/9Vl//z9vKJjXjrYIZHA2JhbYMUaMlonULnSUCfGYNnKGFnT+0wGrRypASaYTscUPeWmpegjAXlpzQQsLV+bqviFiChONU6JAzSBH1aLVwOedfgTHtI4TjDT7NhEkupyEhqRZQ38QO1Qj1kJ68+gX0QGurhxRLHxlFblx8lX3BIuAwJSgGKv5DdfXE3+dLCDZ5VzqbviN/i9/h1PfotqLLTnnD1P9/GTcabCXidAkfYikhfi0u8U0vGZLFqRoL0OK7p8GPDoarsSckgL0pgzETYC9E7WA7AcqrQiKyk6BQ2zEvh8Sk+hgrofJFEfwjLfPbbSUrGeESn6XlYHGTgjeFcslsOP9nm9NcXKtn5BiNPjrAsMk1cYtuEUh4d9GBAJJsu6D4SM3ZMfe7V64MPBmnh3qkCWTYeWGBkTcY5VfFjnu1/4bmLykIQvt8PSDjKnqlBwpsj9k3zOhU5RgEPTNiqSR3aHkKTxmSMS5nOZBP1zKRCYlePS3qypMUs7o+L2bMDKiuXh6F/IzATaval5NK0kHx/xDHba+VqXKMfCHIBe2LDCPlQkYyr92lFE7ffRxMoCd9AIGSKafGGtC5pbeQcLuhIXnfVMlIOSn++uermYGyHnEgwQntmDlplmzAif5lld6Yk6Q5aMkBJagvtQFCou/qg4eDWkX9beR0TevA3kuzg4OiYJ0yGLeMck0iD/W4AxEqosIbQA4SeaBHsK8FA15vqWwTI6KhcJyYx7Ug+QUcQDzxD6seyus5ntsumNS9TWGPYCQv8r6jZYn4jL+PIymTTL9wIS6pVyqN2xZlZYbOop3tKXbObJw07Vm3RJsZDsXabIccfX7rLo5ZZgETAg4DCR5wx7+X5TPJ6OsKldpeSdhlsiDKJ93VsBRslm5WOd4652Vq+Jxkjp8jPvb/qcnv/9EEIKuywa7m97GTFzNzO47Jsd9x5A5jgj0/QVl4m9BtPjlwqm8QrD8AKpVtv7467VZSXY08J596tNqVwPuiGVU7JLFsfVRaJI8PGMK4jXGOIDAU/y3QV6fuYc1DIzwHwdNEVgIwzbu4e3AMBlzLz6dEHCoYt7PrRigH5QOo9Ihf+4rLScZmXZRU8Vz1w15qleaatJ05cXgTWT9mZCofP2qM7hh7be0W10IcbbgDA+c8MK7N2bqDQM1vmUP79A38GGq0zDQBuo2v4qJ6cfigpngwwbXnO7RW4sWNJWY/DTrxJXKLD3qayy0chpVPJLine truncated
|
"payload": "lC5SZ1Oqk+CagVfBEqB3ymOhaDxMMVFGyc5U913hyVqHtHoVWXP1BMNcyQHMTlzQRZf70qeGib3l0T5mcr5SqX59TggSneNcUyhWzEWnek+2dBboAOSMCtZFZj+BzN1v85bnDah72Wmdthh6GbeOuvED7dSMFn/i/jEJw7n7ASOJm+hEipqKrHadkt2JAd2gmdQk3x8MUlDdMPixznGP4JVzgAbSVz5DA+i+pSlLeai2PBJC0oceH62Jn3jqvj0V3pLuvzOLUpK69bWyFFThh3YU8YidpR9yt1B//xf2GBzdrFMQb+OcWeJc0ffPFItG0EavD6xtUqDn48+TBW6mhxFoUBZNgEH+d8wKxnh8Yf8l0xz9c20ASCP4dShK5QH6VwhX3xz5/OROKeQx8QoFPgS8q7lc6CDAgUYAUOfwS32jLJ4Bv+9YZCIa8B42cJtcmdspJ1Y90727I9wdB6eqESKOg1GuojlxsuoO9Oqx45TtwNbqZdCai1ILpGfm+3nUSqTSPlO6KUqZ7336JUHBDKvvUKEKEXY97FYKY4PrY1+WVC6usiGOyOtOg5WOMMA5mHhOARMnT7ZDHFokvDFTSc4HOxKB+VvXZ8vFk9xIbV5Dbi7g+KbI/P1B7PiZVxL+aK7C4N7Cm04MzW2gkrcWIvlw3MTepI8yK39MJvY4NI1Y+TJJHJGoghBJtuhU2Ajf1a4/V+JFiM2rbeObsKgyA0QuUXhxgUzWzyLBzpKHgscYz3nRH/TsMXAmTtDUkOdOm0xGSujDouysKRvsxqnwaE43Z1LwxMAfjYOlCjghMIBMobyMDCej8U4c1p+l9xVAg8YQ87CVutjg2KWqlYuoPi1L5YCdCLBvFq66SR1VWL9JJ5JP2y/JMaVmHNd6ZOulKozzPlOLBZTdBZDJHksbzcwtqkZJGL/ut483/cgUSZjNXcRKOhfNixaqFdo9+UMnGnmdLsV1UMkvFQmF4VnE8P6jPDJ9l+ezYEvs+s6ZmZzltLzLQ540+ZCdFOet4FPtO8sHCua4EuCeKbWkEyQeyUMa/B+ss/z+NTUgoxiL7U2YsUEbgNSHIYnQ4rXg8LvgjZmA/OWcBuJ+xeQy4pMksnZC9g1N8st+UTeQtDICOLHNpknliH/0FuUMpOlzoZJVWr+k4VXHGlz8YVznmAW1V7e29zvnOgugfiG9AFmwG4dKVuRkTg/i7+PyRJEKyRqA1fEv7gq4Zi1OHqcKHIQfKbh2e5sKVaFUkC7kGnORaK519MTxZ9+Qdr2U+1cxb6lYIhZ8HmJeQr22683WnyfCuszjPJprdu89OhBhneDVsBTFi/py6/Eo9i4YfnTxVhCP+HO1euLqfHFoUJb/FqMV8Buaugh4gl1dOv6N0ZupKpq83c1gGAvuRMM4bv1qy9AxpiUcqESatXISD4Ayvxnw9S3UQV3jDNZGKFhrZV0KZ3DFqWHD6eo+gKDyDk21e4stCSitN4U30VjEFAV+i4blrbGMiGwrWeOlaVC9UQwMtj7ZS6us7by3GWrecbmaN3rQF5gPWbO/ijM/nmHCv8mCxSA4mD9w/n27r4qCqIgmhb4fqHvxg9M8es0/n4lUQjeRgu8scsG5VzF3N/8umdF2OA0Bx4a9ffNWegZWOJnK15B9lS+osek17QHHoIdQGAvWfT0BMr/7urjBv8nolbrRe+McPUx7Hg2yWVuEtBGxYTJ5Jh5L+1tIcB1rtW5IrSR8XlxXURtoYtbl3p2pLua0gq7IbK5sfnm6AS9B/6dM6pcVXedssNdZj7LKeW405ov0XRNZtQYMo7nTuQs1kqqvMjMV5H6Ki6TbVvNDKoi+PoPa/DzfxHsee2lZEFMSIbmRGdbpzrWyG+Epk0YBq7/0D6BCnoIxKIcMGz5zLz3u+iC7KVNuDMDvMGovN/K8ntCMQWrz/GbB/XfbdTrF5BBSnwAsMiCjMnkQy1wjI+5fR8BmXtU/iw/K/LJYNcV9yE03+CgnXqFsiGex3d8FCxrqbiazw1+gGOhBfJQocELy38AfaDlW3lcg/+zpMujyd6KexeEwNTzGDHtzAncx0NIWDw/nHNApZF/Tjnji60lCBkHO2bV4yNeDYUdoJQUXyyTTGJDjHWSbl3YrGcxjEWQZkdcm3hzXMfszkkfFLahC6x5/UfM3/8ZkfMVg3hni54cdcrwzlNl/BO1rdanzIwhmD1ijg1AkALvP/bOkjaN12kOwCLE9LelQaPUCNRmLv/ngnBGdnr530pQx20YLB5RiXC2rzNuUSPz+Dfdlg/Rr6t5Kx6Nd4C29+b9VK7QlFI4K5t0vVLplFs3Crx+Fny9ta4+z18TzQuSbxBycEmmITvnA8Scghfd+32LLaxiGJrll61O7VIaD3RZSkkF0YXYKWGcQKE4ZBLivg8ODUbf4PxutKkNRUMEYiYg/coiqpZLCBRRDrKhQeLLA7onLkqJXh3jvlr+bwRhAo2RoPmUgioGwPQHtmvqeHpGRATAFt5XmBxE262iYOLCSj8KiWWMz0gDDROk/Cn5WZA4vSjZ6WGMAOC++H5qqPYqE0/orI5JP3DiLd/5PAzhFgtolm7wX6saDCD4rrthFynJoIOX22ex8Yq/CQWp49Up0zTM++wseydZ0Pp3hV4SEEwow4NtXS4PpiqL3WseqSj3y7Rz/PRqeuwKZOpiE3tOQBsyKpQHarxpBG0pGTRbTrsWvyAcDTlkizuMBFV3nUBfhc5N1PnxVcnRR2wJoSlwt6qJ8MTIgwoVa7wu09AFRfbesSN0ZHjZBFMPidIDa9sRHp91wi6FKTBsdWPU6ZTQN+EWJgVNhrpZ4ub/jmmoI7jmvjkfmGv0/CKCmKeRvXFaOsecfhsjVPMbzRj/WKgOY1hX02Uo4KFCqV649Fod94+vePfC5CC2BVOq1+mnIBlx5au8VRzKEMcSqhLpChXYERiCt4rJlZl9PgWE9+xVtWz9ryUyqyEurvdRLZWOdx2ptjJoz8uxclpgNfI3sjBSMYdExd4HhTz+MVVyarpWA+d7ZBlrwOri+xj8LHsdDe3sy2Jmk54cmdw4f5pJRH43Bg7uEuIN8umAekwAOoGGQaBJo84ibVffIMivV/vo6XC//FOFQUUvd4RGcFgXqgFkBCJJh/s2HiBALq1E3L6QzSY7LfCTEd+c30XvnPSdpvu4InnX9NESpfWXlZhv3gobuOQ9gKA2VmD8LTODcX2tZwahp8XhiEBAxV37X+fsd7Icl9EUG/PhXMeYtvC1kpvrLJbWyY2gsA/7GmOBDJY63+ZIXl0sRb7NlpMkyoa4mU/g5XQh0pkomnk1ws7DKcrOgEe14yVQrpn2b2Ny6VPNQ+yM0JzoIBBuPPRs9ARStNTgTD0AD2kYxEFVeACBtjsXHGtxYWRLFXCKP1N64+ZOwQTc8P9s7p+0wCdyvk08n3E38aNOzEmZiJUcvX2oSYvlKwhnSU9dq8TQfv+/fl+tCZIVbHLEwm4vlMy9CzN6Lqir9nF6h5vJLn4vAOycncfNEJHQhEe5A2jNYQ02DJZh5ieoGz71iLyMrpzKstKXJg+eyaLE2b9F8yjmPQk4z0gJaCl9qNGZLqXMZziY/I4L3b5IfZw8nPVRtGHlJmEwQ1GcGynRj5zJ2CY4fqLpPjRNDhUPAmOyA8OWD1fpjF6/ReaEijnDgMxkJWxey9Zv4+er5ndJuV/8IhhEShZK/8aK0p0NfVeE1lfL23DfI1hIrLuDFKT3VvWR4a+gVdq6SqKepzeUD7bFfHZFkNc3ie9EY3CQXLczb+l5IU7DMwXUKxMfUHdNFfh1QSP/a54bLy7/xzL20jS3VGVHZF+dTT/vwSHQPnwr6yKSKZXYD3YAxbh+MBEuiUN9y9l143FV80Wz7cyz3hEQfQj72KSs3whehoalc0qNzkEQp1KdqA3auI4SOrGbcHX8fkQR8Q9dTuIkQ8iWUayLKupJGZ8qn3u+WUZqm66+LjOAYZSgx72sde5vz56FEsRCOrb7+vua6ce5OC8kclL6vBccitDhJErVfylhgYGR3DYnJvlQHBPmt88gUDw0UXoNJltXLVAN43Pm/YFkgTXzOfne+qhMrrRE2h2kaLKJQgezqd0kn86mdg0gyfRQIZkHS6AtdmPbSnA7EeomtPNgjHggnZFX35zL/UR//Yxerc1HGzl8ph8xdTy3HqITUMGDJkEA2g2NF1tCnc+uCt96behFzRoUaQwljLK2XsegHsLh+cMVFAGWFeVzv95G98cCzzjcpfq0JrfxWnbH98O7piRdc3uzO55NfWBO5DU+hErcV0HQUQx3VO7rKj9WKyLVgzTdWj9xXhZp156bZmyclULsgwz91+HvEwl7KvGQhKamCaJ6nKuKGVvV2KBmqY6ABEHeNZX71uWBfgfpwQ7RYY7faksnlxgmDMrPDPlLjmRp8vH5TBMIxMOS0tB6aOwz6pYiwK5N1D3qZdo8V5YjvYd2Cl95knq5OaVgLwYIJveJzELMNM45PpOECpDXHldxvPxqqoHNblv4YYHAMkYhzUScydR+gHL4YCoRJbxgE0+zY/E35kofYoEcY8pMNz4gHHKlA/DhR3LeWyFzhFl3YsTsA7T//ooaxQ2BqWTzLh2eunXsLTRudtXE5l1OYOUezL1rmFPEBkWUycF8wrNe3PvEj6oJaQEiBv6jrae8+c7FOMkKR0AkyHKQefwHNBCSfyO290gmgzpTfmIWhUJQdbchsfM2eDa0oNRIOuQ4VfpQfwa8ottLpBEPO6M92gBfm3w88Xcnbwpa+bppgXadlyDgnQ7cZkEmjVJWx53UhFwgPo/6OuFirgpxDx0q+U6TKVriktLVGvYl9x8x3eV400o/JhVeseCMiE+1zx10g9Sy4PUqGM4TWVD9Lg4Rl0pcTvx6rpB6VZ2xN8s59YyaLUIiJ5m5npfrtbtTHPgYRJox1bBAX9pNTrsN6v5Wr77Kzi2pWfaa6Cwd7Q/tfau10jQtYw0yHkMBOA3
Line truncated
|
||||||
};
|
};
|
||||||
@@ -5,7 +5,7 @@
|
|||||||
@author Björn Runden <br@runden.de>
|
@author Björn Runden <br@runden.de>
|
||||||
@owner 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>
|
@assist KI-unterstützt (Claude Opus 5.5), geprüft von Björn Runden <br@runden.de>
|
||||||
@version 0.3.0 (29.10.2026)
|
@version 0.3.1 (30.10.2026)
|
||||||
@usage build_bank.py [-d] [-q] [-n] [-c] [--approved-only] [-o js/bank.js] [-e [DIR]] [-b [FILE]]
|
@usage build_bank.py [-d] [-q] [-n] [-c] [--approved-only] [-o js/bank.js] [-e [DIR]] [-b [FILE]]
|
||||||
|
|
||||||
Aufbau von data/: je Prüfung ein Ordner mit exam.json und beliebig vielen questions_*.json (Quelltext, Klartext).
|
Aufbau von data/: je Prüfung ein Ordner mit exam.json und beliebig vielen questions_*.json (Quelltext, Klartext).
|
||||||
@@ -238,7 +238,9 @@ def write_bank(exams: list[dict], output: Path) -> None:
|
|||||||
|
|
||||||
def export_site(target: Path, dry_run: bool) -> None:
|
def export_site(target: Path, dry_run: bool) -> None:
|
||||||
"""Kopiert nur die Laufzeitdateien (ohne data/, tools/, tests/) nach target.
|
"""Kopiert nur die Laufzeitdateien (ohne data/, tools/, tests/) nach target.
|
||||||
Ein vorhandenes Ziel wird nur ersetzt, wenn es von hier stammt (Markierungsdatei)."""
|
In ein vorhandenes Ziel wird nur exportiert, wenn es von hier stammt (Markierungsdatei). Ersetzt werden
|
||||||
|
ausschließlich EXPORT_ITEMS; andere Dateien im Ziel (z. B. abgelegte Pakete) bleiben unangetastet, und das
|
||||||
|
Verzeichnis selbst bleibt bestehen (ein darin laufender http.server liefert weiter aus)."""
|
||||||
target = target.resolve()
|
target = target.resolve()
|
||||||
if target == BASE or BASE in target.parents and target.name in EXPORT_ITEMS + ["data", "tools", "tests"]:
|
if target == BASE or BASE in target.parents and target.name in EXPORT_ITEMS + ["data", "tools", "tests"]:
|
||||||
raise ValueError(f"Export-Ziel {target} liegt im Quellbaum")
|
raise ValueError(f"Export-Ziel {target} liegt im Quellbaum")
|
||||||
@@ -247,14 +249,16 @@ def export_site(target: Path, dry_run: bool) -> None:
|
|||||||
if dry_run:
|
if dry_run:
|
||||||
log.info("Trockenlauf: würde %s nach %s exportieren", ", ".join(EXPORT_ITEMS), target)
|
log.info("Trockenlauf: würde %s nach %s exportieren", ", ".join(EXPORT_ITEMS), target)
|
||||||
return
|
return
|
||||||
if target.exists():
|
target.mkdir(parents=True, exist_ok=True)
|
||||||
shutil.rmtree(target)
|
|
||||||
target.mkdir(parents=True)
|
|
||||||
for item in EXPORT_ITEMS:
|
for item in EXPORT_ITEMS:
|
||||||
src = BASE / item
|
src, dst = BASE / item, target / item
|
||||||
(shutil.copytree if src.is_dir() else shutil.copy2)(src, target / item)
|
if dst.is_dir() and not dst.is_symlink():
|
||||||
(target / EXPORT_MARKER).write_text("Export von simulator/tools/build_bank.py – Verzeichnis wird beim nächsten Export ersetzt\n",
|
shutil.rmtree(dst)
|
||||||
encoding="utf-8")
|
elif dst.exists() or dst.is_symlink():
|
||||||
|
dst.unlink()
|
||||||
|
(shutil.copytree if src.is_dir() else shutil.copy2)(src, dst)
|
||||||
|
(target / EXPORT_MARKER).write_text("Export von simulator/tools/build_bank.py – beim nächsten Export werden nur "
|
||||||
|
+ ", ".join(EXPORT_ITEMS) + " ersetzt, andere Dateien bleiben\n", encoding="utf-8")
|
||||||
log.info("Export nach %s geschrieben (Start: python3 -m http.server 8080 -d %s)", target, target)
|
log.info("Export nach %s geschrieben (Start: python3 -m http.server 8080 -d %s)", target, target)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in new issue
Block a user