rein damit
This commit is contained in:
1 parent
7f6b8ebe07
commit
07dbc01c92
38 files changed
+5632
-5
No files matched your search
@@ -0,0 +1,73 @@
|
||||
{
|
||||
"meta": {
|
||||
"file": "exam.json",
|
||||
"brief": "Prüfungsdefinition LPIC-1 101-500: Eckdaten, Topics, Objectives mit Gewichtung",
|
||||
"author": "Björn Runden <br@runden.de>",
|
||||
"owner": "Björn Runden <br@runden.de>",
|
||||
"assist": "KI-unterstützt (Claude Opus 5.5), geprüft von Björn Runden <br@runden.de>",
|
||||
"version": "0.1.0 (29.10.2026)"
|
||||
},
|
||||
"exam": {
|
||||
"id": "lpic1-101",
|
||||
"level": "LPIC-1",
|
||||
"title": "LPIC-1 Prüfung 101",
|
||||
"code": "101-500",
|
||||
"lang": "de",
|
||||
"order": 101,
|
||||
"objectives_version": "5.0",
|
||||
"objectives_source": "https://www.lpi.org/de/exam-101-102-objectives/",
|
||||
"objectives_retrieved": "2026-10-29",
|
||||
"questions": 60,
|
||||
"duration_min": 90,
|
||||
"pass_percent": 65
|
||||
},
|
||||
"topics": [
|
||||
{
|
||||
"id": "101",
|
||||
"title": "Systemarchitektur",
|
||||
"objectives": [
|
||||
{ "id": "101.1", "title": "Hardwareeinstellungen ermitteln und konfigurieren", "weight": 2 },
|
||||
{ "id": "101.2", "title": "Das System starten", "weight": 3 },
|
||||
{ "id": "101.3", "title": "Runlevel wechseln und das System anhalten oder neu starten", "weight": 3 }
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "102",
|
||||
"title": "Linux-Installation und -Paketverwaltung",
|
||||
"objectives": [
|
||||
{ "id": "102.1", "title": "Festplattenaufteilung planen", "weight": 2 },
|
||||
{ "id": "102.2", "title": "Einen Bootmanager installieren", "weight": 2 },
|
||||
{ "id": "102.3", "title": "Shared Libraries verwalten", "weight": 1 },
|
||||
{ "id": "102.4", "title": "Debian-Paketverwaltung verwenden", "weight": 3 },
|
||||
{ "id": "102.5", "title": "RPM und YUM-Paketverwaltung verwenden", "weight": 3 },
|
||||
{ "id": "102.6", "title": "Linux als Virtualisierungs-Gast", "weight": 1 }
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "103",
|
||||
"title": "GNU- und Unix-Befehle",
|
||||
"objectives": [
|
||||
{ "id": "103.1", "title": "Auf der Befehlszeile arbeiten", "weight": 4 },
|
||||
{ "id": "103.2", "title": "Textströme mit Filtern verarbeiten", "weight": 2 },
|
||||
{ "id": "103.3", "title": "Grundlegende Dateiverwaltung", "weight": 4 },
|
||||
{ "id": "103.4", "title": "Ströme, Pipes und Umleitungen verwenden", "weight": 4 },
|
||||
{ "id": "103.5", "title": "Prozesse erzeugen, überwachen und beenden", "weight": 4 },
|
||||
{ "id": "103.6", "title": "Prozess-Ausführungsprioritäten ändern", "weight": 2 },
|
||||
{ "id": "103.7", "title": "Textdateien mit regulären Ausdrücken durchsuchen", "weight": 3 },
|
||||
{ "id": "103.8", "title": "Grundlegendes Editieren von Dateien", "weight": 3 }
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "104",
|
||||
"title": "Geräte, Linux-Dateisysteme, Filesystem Hierarchy Standard",
|
||||
"objectives": [
|
||||
{ "id": "104.1", "title": "Partitionen und Dateisysteme anlegen", "weight": 2 },
|
||||
{ "id": "104.2", "title": "Die Integrität von Dateisystemen sichern", "weight": 2 },
|
||||
{ "id": "104.3", "title": "Das Mounten und Unmounten von Dateisystemen steuern", "weight": 3 },
|
||||
{ "id": "104.5", "title": "Dateizugriffsrechte und -eigentümerschaft verwalten", "weight": 3 },
|
||||
{ "id": "104.6", "title": "Symbolische und Hardlinks anlegen und ändern", "weight": 2 },
|
||||
{ "id": "104.7", "title": "Systemdateien finden und Dateien am richtigen Ort platzieren", "weight": 2 }
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,173 @@
|
||||
{
|
||||
"$schema": "../schema/questions.schema.json",
|
||||
"format": "lpic-sim-questions",
|
||||
"meta": {
|
||||
"file": "questions_101.json",
|
||||
"brief": "Fragen 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 (29.10.2026)"
|
||||
},
|
||||
"exam": "lpic1-101",
|
||||
"questions": [
|
||||
{
|
||||
"id": "101.1-001",
|
||||
"objective": "101.1",
|
||||
"type": "single",
|
||||
"difficulty": 1,
|
||||
"question": "Welcher Befehl listet alle aktuell geladenen Kernelmodule auf?",
|
||||
"options": [
|
||||
{ "id": "a", "text": "`lsmod`", "correct": true, "explanation": "`lsmod` formatiert den Inhalt von `/proc/modules`: Modulname, Größe und Nutzer." },
|
||||
{ "id": "b", "text": "`modinfo`", "correct": false, "explanation": "`modinfo` zeigt Informationen zu einem bestimmten Modul (Autor, Parameter, Datei), listet aber nicht die geladenen Module." },
|
||||
{ "id": "c", "text": "`lspci -k`", "correct": false, "explanation": "`lspci -k` zeigt nur zu PCI-Geräten den verwendeten Treiber, nicht alle geladenen Module." },
|
||||
{ "id": "d", "text": "`depmod -a`", "correct": false, "explanation": "`depmod` erzeugt die Abhängigkeitsdatei `modules.dep`, es listet nichts auf." },
|
||||
{ "id": "e", "text": "`insmod -l`", "correct": false, "explanation": "`insmod` lädt eine einzelne Moduldatei ohne Abhängigkeiten; eine Listen-Option gibt es nicht." }
|
||||
],
|
||||
"explanation": "Geladene Module stehen in `/proc/modules`; `lsmod` ist die lesbare Darstellung davon.",
|
||||
"references": ["man 8 lsmod", "/proc/modules"]
|
||||
},
|
||||
{
|
||||
"id": "101.1-002",
|
||||
"objective": "101.1",
|
||||
"type": "multi",
|
||||
"difficulty": 1,
|
||||
"question": "Welche Verzeichnisse sind Einhängepunkte virtueller Dateisysteme, über die der Kernel zur Laufzeit Informationen über Prozesse, Hardware und Treiber bereitstellt?",
|
||||
"options": [
|
||||
{ "id": "a", "text": "`/proc`", "correct": true, "explanation": "procfs: Prozessinformationen und Kernel-Daten wie `/proc/cpuinfo`, `/proc/interrupts`." },
|
||||
{ "id": "b", "text": "`/sys`", "correct": true, "explanation": "sysfs: Geräte, Treiber und Busse als Verzeichnisbaum; Grundlage für udev." },
|
||||
{ "id": "c", "text": "`/boot`", "correct": false, "explanation": "`/boot` ist ein normales Dateisystem mit Kernel, initramfs und Bootloader-Dateien." },
|
||||
{ "id": "d", "text": "`/etc`", "correct": false, "explanation": "`/etc` enthält statische Konfigurationsdateien auf der Festplatte." },
|
||||
{ "id": "e", "text": "`/var/lib`", "correct": false, "explanation": "`/var/lib` enthält dauerhafte Zustandsdaten von Programmen, keine Kernel-Schnittstelle." }
|
||||
],
|
||||
"explanation": "procfs (`/proc`) und sysfs (`/sys`) existieren nur im Speicher und werden vom Kernel beim Lesen erzeugt. Werkzeuge wie `lspci`, `lsusb` und udev lesen dort.",
|
||||
"references": ["man 5 proc", "man 5 sysfs"]
|
||||
},
|
||||
{
|
||||
"id": "101.1-003",
|
||||
"objective": "101.1",
|
||||
"type": "fill",
|
||||
"difficulty": 1,
|
||||
"question": "Mit welchem Befehl (nur der Befehlsname) lädt man ein Kernelmodul **mitsamt seinen Abhängigkeiten**?",
|
||||
"answers": ["modprobe"],
|
||||
"explanation": "`modprobe` löst Abhängigkeiten über `modules.dep` auf und lädt sie mit; `modprobe -r` entlädt. `insmod` lädt dagegen nur genau die angegebene Datei.",
|
||||
"references": ["man 8 modprobe"]
|
||||
},
|
||||
{
|
||||
"id": "101.2-001",
|
||||
"objective": "101.2",
|
||||
"type": "single",
|
||||
"difficulty": 1,
|
||||
"question": "Ein Administrator möchte die Meldungen des Kernel-Ring-Buffers (z. B. Hardware-Erkennung beim Start) ansehen. Welcher Befehl gibt diesen Puffer aus?",
|
||||
"options": [
|
||||
{ "id": "a", "text": "`dmesg`", "correct": true, "explanation": "`dmesg` liest den Kernel-Ring-Buffer und gibt ihn aus." },
|
||||
{ "id": "b", "text": "`uname -a`", "correct": false, "explanation": "`uname -a` zeigt Kernelname, Version, Architektur – keine Meldungen." },
|
||||
{ "id": "c", "text": "`lsmod`", "correct": false, "explanation": "`lsmod` listet geladene Module, nicht die Kernel-Meldungen." },
|
||||
{ "id": "d", "text": "`cat /proc/cmdline`", "correct": false, "explanation": "`/proc/cmdline` enthält nur die Kernel-Parameter des letzten Starts." },
|
||||
{ "id": "e", "text": "`last -x`", "correct": false, "explanation": "`last -x` zeigt Anmeldungen sowie Shutdown-/Runlevel-Einträge aus `wtmp`, nicht den Ring-Buffer." }
|
||||
],
|
||||
"explanation": "Der Ring-Buffer hat eine feste Größe; ältere Meldungen werden überschrieben. Bei systemd sind Kernel-Meldungen zusätzlich mit `journalctl -k` im Journal abrufbar.",
|
||||
"references": ["man 1 dmesg"]
|
||||
},
|
||||
{
|
||||
"id": "101.2-002",
|
||||
"objective": "101.2",
|
||||
"type": "fill",
|
||||
"difficulty": 2,
|
||||
"question": "In welcher Datei (vollständiger Pfad) kann man nachlesen, mit welchen Parametern der laufende Kernel gestartet wurde?",
|
||||
"answers": ["/proc/cmdline"],
|
||||
"explanation": "`/proc/cmdline` enthält die vom Bootloader übergebene Kernel-Befehlszeile, z. B. `root=…`, `ro`, `quiet`.",
|
||||
"references": ["man 5 proc"]
|
||||
},
|
||||
{
|
||||
"id": "101.2-003",
|
||||
"objective": "101.2",
|
||||
"type": "single",
|
||||
"difficulty": 2,
|
||||
"question": "In welcher Reihenfolge laufen die Phasen beim Start eines BIOS-Systems mit GRUB 2 und systemd ab?",
|
||||
"options": [
|
||||
{ "id": "a", "text": "Firmware (POST) → Bootloader → Kernel mit initramfs → systemd", "correct": true, "explanation": "Die Firmware prüft die Hardware und startet den Bootloader, der Kernel und initramfs lädt; der Kernel startet zuletzt den ersten Prozess." },
|
||||
{ "id": "b", "text": "Bootloader → Firmware (POST) → Kernel mit initramfs → systemd", "correct": false, "explanation": "Der Bootloader wird erst von der Firmware gestartet, kann also nicht vor ihr laufen." },
|
||||
{ "id": "c", "text": "Firmware (POST) → Kernel mit initramfs → Bootloader → systemd", "correct": false, "explanation": "Der Bootloader lädt den Kernel – er läuft daher vor dem Kernel." },
|
||||
{ "id": "d", "text": "Firmware (POST) → Bootloader → systemd → Kernel mit initramfs", "correct": false, "explanation": "systemd ist ein Userspace-Prozess und wird vom Kernel gestartet, nicht umgekehrt." },
|
||||
{ "id": "e", "text": "Firmware (POST) → initramfs → Bootloader → Kernel → systemd", "correct": false, "explanation": "Die initramfs wird vom Bootloader gemeinsam mit dem Kernel geladen und erst vom Kernel benutzt." }
|
||||
],
|
||||
"explanation": "Ablauf: Firmware (BIOS/UEFI) → Bootloader (GRUB 2) → Kernel + initramfs (Treiber, Root-Dateisystem einhängen) → init-Prozess mit PID 1 (systemd oder SysV-init).",
|
||||
"references": ["man 7 bootup"]
|
||||
},
|
||||
{
|
||||
"id": "101.2-004",
|
||||
"objective": "101.2",
|
||||
"type": "multi",
|
||||
"difficulty": 2,
|
||||
"question": "Welche Aussagen zur initramfs treffen zu?",
|
||||
"options": [
|
||||
{ "id": "a", "text": "Sie enthält Treiber und Werkzeuge, die nötig sind, um das eigentliche Root-Dateisystem einzuhängen.", "correct": true, "explanation": "Typisch sind Module für Storage-Controller, LVM, RAID oder Verschlüsselung." },
|
||||
{ "id": "b", "text": "Sie wird vom Bootloader zusammen mit dem Kernel in den Arbeitsspeicher geladen.", "correct": true, "explanation": "GRUB lädt Kernel und initramfs (Eintrag `initrd`) gemeinsam." },
|
||||
{ "id": "c", "text": "Sie ersetzt den Kernel, wenn dieser beschädigt ist.", "correct": false, "explanation": "Die initramfs ist ein Dateisystem-Abbild, kein Ersatzkernel." },
|
||||
{ "id": "d", "text": "Sie wird nur bei UEFI-Systemen verwendet.", "correct": false, "explanation": "Die initramfs ist unabhängig von der Firmware; sie wird bei BIOS und UEFI genutzt." },
|
||||
{ "id": "e", "text": "Sie ist unter `/sys/initramfs` dauerhaft eingehängt.", "correct": false, "explanation": "Nach dem Wechsel auf das echte Root-Dateisystem wird die initramfs verworfen; ihr Abbild liegt meist in `/boot`." }
|
||||
],
|
||||
"explanation": "Die initramfs ist ein (meist komprimiertes cpio-)Abbild eines kleinen Root-Dateisystems. Sie überbrückt die Zeit, bis der Kernel das echte Root-Dateisystem einhängen kann.",
|
||||
"references": ["man 8 dracut", "man 8 update-initramfs"]
|
||||
},
|
||||
{
|
||||
"id": "101.3-001",
|
||||
"objective": "101.3",
|
||||
"type": "single",
|
||||
"difficulty": 1,
|
||||
"question": "Welches systemd-Target entspricht dem SysV-Runlevel 3 (Mehrbenutzerbetrieb mit Netzwerk, ohne grafische Oberfläche)?",
|
||||
"options": [
|
||||
{ "id": "a", "text": "`multi-user.target`", "correct": true, "explanation": "`multi-user.target` entspricht den Runlevels 2–4." },
|
||||
{ "id": "b", "text": "`graphical.target`", "correct": false, "explanation": "`graphical.target` entspricht Runlevel 5 (mit grafischer Anmeldung)." },
|
||||
{ "id": "c", "text": "`rescue.target`", "correct": false, "explanation": "`rescue.target` entspricht Runlevel 1 (Einzelbenutzer)." },
|
||||
{ "id": "d", "text": "`emergency.target`", "correct": false, "explanation": "`emergency.target` startet nur eine Notfall-Shell, Root meist nur lesend eingehängt." },
|
||||
{ "id": "e", "text": "`network.target`", "correct": false, "explanation": "`network.target` ist ein Synchronisationspunkt für Netzwerkdienste, kein Systemzustand wie ein Runlevel." }
|
||||
],
|
||||
"explanation": "Zuordnung: 0 → `poweroff.target`, 1 → `rescue.target`, 2–4 → `multi-user.target`, 5 → `graphical.target`, 6 → `reboot.target`.",
|
||||
"references": ["man 7 systemd.special", "man 1 systemctl"]
|
||||
},
|
||||
{
|
||||
"id": "101.3-002",
|
||||
"objective": "101.3",
|
||||
"type": "fill",
|
||||
"difficulty": 2,
|
||||
"question": "Geben Sie den vollständigen Befehl ein, mit dem bei systemd das Standard-Target dauerhaft auf `graphical.target` gesetzt wird.",
|
||||
"answers": ["systemctl set-default graphical.target", "systemctl set-default graphical"],
|
||||
"explanation": "`systemctl set-default` setzt den Symlink `default.target`; wirksam beim nächsten Start. `systemctl get-default` zeigt das aktuelle Standard-Target.",
|
||||
"references": ["man 1 systemctl"]
|
||||
},
|
||||
{
|
||||
"id": "101.3-003",
|
||||
"objective": "101.3",
|
||||
"type": "single",
|
||||
"difficulty": 1,
|
||||
"question": "Das System soll in 10 Minuten heruntergefahren werden; angemeldete Benutzer sollen die Nachricht „Wartung“ erhalten. Welcher Befehl leistet das?",
|
||||
"options": [
|
||||
{ "id": "a", "text": "`shutdown -h +10 \"Wartung\"`", "correct": true, "explanation": "`-h` hält/schaltet aus, `+10` bedeutet in 10 Minuten, der Text geht per wall an alle Terminals." },
|
||||
{ "id": "b", "text": "`shutdown -c +10 \"Wartung\"`", "correct": false, "explanation": "`-c` bricht einen geplanten Shutdown ab." },
|
||||
{ "id": "c", "text": "`shutdown -r now +10 \"Wartung\"`", "correct": false, "explanation": "`now` und `+10` widersprechen sich; `-r` würde zudem neu starten." },
|
||||
{ "id": "d", "text": "`halt -t 10 \"Wartung\"`", "correct": false, "explanation": "`halt` kennt keine Zeitplanung mit Nachricht; es hält das System sofort an." },
|
||||
{ "id": "e", "text": "`wall -h +10 \"Wartung\"`", "correct": false, "explanation": "`wall` sendet nur eine Nachricht, fährt aber nichts herunter." }
|
||||
],
|
||||
"explanation": "Zeitangabe bei `shutdown`: `now`, `+m` (Minuten) oder `hh:mm`. `-h`/`-P` ausschalten, `-r` Neustart, `-c` abbrechen.",
|
||||
"references": ["man 8 shutdown"]
|
||||
},
|
||||
{
|
||||
"id": "101.3-004",
|
||||
"objective": "101.3",
|
||||
"type": "multi",
|
||||
"difficulty": 2,
|
||||
"question": "Mit welchen Befehlen wechselt ein laufendes System **sofort** in den Einzelbenutzer-/Rettungsmodus?",
|
||||
"options": [
|
||||
{ "id": "a", "text": "`systemctl isolate rescue.target`", "correct": true, "explanation": "`isolate` startet das Target und beendet alle Units, die nicht dazugehören." },
|
||||
{ "id": "b", "text": "`telinit 1`", "correct": true, "explanation": "`telinit 1` (bzw. `init 1`) wechselt in Runlevel 1; unter systemd wird das auf `rescue.target` abgebildet." },
|
||||
{ "id": "c", "text": "`systemctl set-default rescue.target`", "correct": false, "explanation": "Ändert nur das Standard-Target für den nächsten Start." },
|
||||
{ "id": "d", "text": "`runlevel 1`", "correct": false, "explanation": "`runlevel` zeigt nur den vorherigen und aktuellen Runlevel an; es nimmt keinen Wechsel vor." },
|
||||
{ "id": "e", "text": "`systemctl reload rescue.target`", "correct": false, "explanation": "`reload` lässt laufende Dienste ihre Konfiguration neu lesen; ein Targetwechsel ist das nicht." }
|
||||
],
|
||||
"explanation": "Sofortiger Wechsel: `systemctl isolate <target>` bzw. klassisch `telinit <n>`/`init <n>`. Dauerhaft für den Start: `systemctl set-default`.",
|
||||
"references": ["man 1 systemctl", "man 8 telinit"]
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,317 @@
|
||||
{
|
||||
"$schema": "../schema/questions.schema.json",
|
||||
"format": "lpic-sim-questions",
|
||||
"meta": {
|
||||
"file": "questions_102.json",
|
||||
"brief": "Fragen 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 (29.10.2026)"
|
||||
},
|
||||
"exam": "lpic1-101",
|
||||
"questions": [
|
||||
{
|
||||
"id": "102.1-001",
|
||||
"objective": "102.1",
|
||||
"type": "single",
|
||||
"difficulty": 1,
|
||||
"question": "Welches Verzeichnis legt man typischerweise auf eine eigene Partition, damit wachsende Protokoll- und Spool-Dateien das Root-Dateisystem nicht füllen?",
|
||||
"options": [
|
||||
{ "id": "a", "text": "`/var`", "correct": true, "explanation": "`/var` enthält variable Daten wie Logs, Spool und Caches, die unkontrolliert wachsen können." },
|
||||
{ "id": "b", "text": "`/etc`", "correct": false, "explanation": "`/etc` wird schon früh beim Start gebraucht und muss auf dem Root-Dateisystem liegen; es wächst kaum." },
|
||||
{ "id": "c", "text": "`/bin`", "correct": false, "explanation": "`/bin` enthält grundlegende Programme, die beim Start verfügbar sein müssen." },
|
||||
{ "id": "d", "text": "`/sbin`", "correct": false, "explanation": "`/sbin` enthält Systemprogramme für Start und Reparatur und gehört auf das Root-Dateisystem." },
|
||||
{ "id": "e", "text": "`/lib`", "correct": false, "explanation": "`/lib` enthält Bibliotheken und Module, die für den Start nötig sind." }
|
||||
],
|
||||
"explanation": "Kandidaten für eigene Partitionen: `/var`, `/home`, `/tmp`, ggf. `/boot` und `/opt`. Was zum Start nötig ist (`/etc`, `/bin`, `/sbin`, `/lib`, `/dev`), bleibt auf dem Root-Dateisystem.",
|
||||
"references": ["man 7 hier"]
|
||||
},
|
||||
{
|
||||
"id": "102.1-002",
|
||||
"objective": "102.1",
|
||||
"type": "multi",
|
||||
"difficulty": 2,
|
||||
"question": "Welche Aussagen zum Logical Volume Manager (LVM) treffen zu?",
|
||||
"options": [
|
||||
{ "id": "a", "text": "Logical Volumes werden aus dem Speicher einer Volume Group zugeteilt.", "correct": true, "explanation": "Hierarchie: Physical Volume → Volume Group → Logical Volume." },
|
||||
{ "id": "b", "text": "Eine Volume Group kann mehrere Physical Volumes umfassen.", "correct": true, "explanation": "Mehrere Platten/Partitionen lassen sich zu einer Volume Group zusammenfassen und mit `vgextend` erweitern." },
|
||||
{ "id": "c", "text": "Ein Physical Volume kann immer nur genau ein Logical Volume aufnehmen.", "correct": false, "explanation": "Die Extents eines Physical Volumes können auf beliebig viele Logical Volumes verteilt sein." },
|
||||
{ "id": "d", "text": "LVM setzt zwingend eine GPT-Partitionstabelle voraus.", "correct": false, "explanation": "LVM funktioniert mit MBR, GPT oder auch ganzen Platten ohne Partitionstabelle." },
|
||||
{ "id": "e", "text": "Logical Volumes können nur vergrößert werden, wenn das System neu gestartet wird.", "correct": false, "explanation": "`lvextend` vergrößert im laufenden Betrieb; viele Dateisysteme lassen sich anschließend online wachsen." }
|
||||
],
|
||||
"explanation": "LVM entkoppelt Dateisysteme von physischen Partitionen: `pvcreate` → `vgcreate` → `lvcreate`. Vorteil: flexible Größenänderung und Snapshots.",
|
||||
"references": ["man 8 lvm"]
|
||||
},
|
||||
{
|
||||
"id": "102.1-003",
|
||||
"objective": "102.1",
|
||||
"type": "single",
|
||||
"difficulty": 1,
|
||||
"question": "Mit welchem Dateisystem muss die EFI-Systempartition (ESP) eines UEFI-Systems formatiert sein?",
|
||||
"options": [
|
||||
{ "id": "a", "text": "FAT (üblich FAT32)", "correct": true, "explanation": "Die UEFI-Spezifikation verlangt ein FAT-Dateisystem, damit die Firmware die Bootloader-Dateien lesen kann." },
|
||||
{ "id": "b", "text": "ext4", "correct": false, "explanation": "ext4 kann die Firmware in der Regel nicht lesen; es eignet sich für `/` oder `/boot`." },
|
||||
{ "id": "c", "text": "XFS", "correct": false, "explanation": "XFS wird von UEFI-Firmware nicht unterstützt." },
|
||||
{ "id": "d", "text": "swap", "correct": false, "explanation": "swap ist Auslagerungsspeicher, kein Dateisystem für Dateien." },
|
||||
{ "id": "e", "text": "Btrfs", "correct": false, "explanation": "Btrfs kann die Firmware nicht lesen." }
|
||||
],
|
||||
"explanation": "Die ESP (meist eingehängt unter `/boot/efi`) enthält die `.efi`-Bootloader und ist FAT-formatiert.",
|
||||
"references": ["UEFI-Spezifikation, Abschnitt EFI System Partition"]
|
||||
},
|
||||
{
|
||||
"id": "102.2-001",
|
||||
"objective": "102.2",
|
||||
"type": "single",
|
||||
"difficulty": 1,
|
||||
"question": "Auf einem Debian-System wurde `/etc/default/grub` geändert (z. B. `GRUB_TIMEOUT`). Welcher Befehl übernimmt die Änderung in die GRUB-2-Konfiguration?",
|
||||
"options": [
|
||||
{ "id": "a", "text": "`update-grub`", "correct": true, "explanation": "`update-grub` ist unter Debian ein Wrapper für `grub-mkconfig -o /boot/grub/grub.cfg`." },
|
||||
{ "id": "b", "text": "`grub-mkconfig`", "correct": false, "explanation": "Ohne `-o <datei>` gibt `grub-mkconfig` die Konfiguration nur auf stdout aus und schreibt nichts." },
|
||||
{ "id": "c", "text": "`grub-install /etc/default/grub`", "correct": false, "explanation": "`grub-install` installiert den Bootloader auf ein Gerät; es erwartet ein Gerät, keine Konfigurationsdatei." },
|
||||
{ "id": "d", "text": "`systemctl restart grub`", "correct": false, "explanation": "GRUB ist kein Dienst; es läuft nur beim Start, vor dem Kernel." },
|
||||
{ "id": "e", "text": "`lilo`", "correct": false, "explanation": "`lilo` gehört zum veralteten Bootloader LILO und wertet `/etc/lilo.conf` aus." }
|
||||
],
|
||||
"explanation": "GRUB 2: Einstellungen in `/etc/default/grub` und `/etc/grub.d/`, daraus erzeugt `grub-mkconfig` die Datei `grub.cfg`, die man nicht von Hand bearbeitet.",
|
||||
"references": ["man 8 grub-mkconfig", "info grub"]
|
||||
},
|
||||
{
|
||||
"id": "102.2-002",
|
||||
"objective": "102.2",
|
||||
"type": "fill",
|
||||
"difficulty": 2,
|
||||
"question": "Geben Sie den vollständigen Befehl ein, der die GRUB-2-Konfiguration neu erzeugt und direkt nach `/boot/grub/grub.cfg` schreibt (ohne den Debian-Wrapper `update-grub`).",
|
||||
"answers": ["grub-mkconfig -o /boot/grub/grub.cfg", "grub-mkconfig --output=/boot/grub/grub.cfg", "grub2-mkconfig -o /boot/grub2/grub.cfg"],
|
||||
"explanation": "`grub-mkconfig -o` schreibt die erzeugte Konfiguration in die Datei. Distributionen der Red-Hat-Familie heißen das Werkzeug `grub2-mkconfig` und nutzen `/boot/grub2/grub.cfg`.",
|
||||
"references": ["man 8 grub-mkconfig"]
|
||||
},
|
||||
{
|
||||
"id": "102.2-003",
|
||||
"objective": "102.2",
|
||||
"type": "single",
|
||||
"difficulty": 2,
|
||||
"question": "Wie heißt die Menü-Konfigurationsdatei von GRUB Legacy (Version 0.9x) üblicherweise?",
|
||||
"options": [
|
||||
{ "id": "a", "text": "`/boot/grub/menu.lst`", "correct": true, "explanation": "GRUB Legacy liest `menu.lst` (bei Red Hat auch `grub.conf`) direkt beim Start." },
|
||||
{ "id": "b", "text": "`/boot/grub/grub.cfg`", "correct": false, "explanation": "`grub.cfg` ist die generierte Konfiguration von GRUB 2." },
|
||||
{ "id": "c", "text": "`/etc/default/grub`", "correct": false, "explanation": "`/etc/default/grub` enthält die Einstellungen, aus denen GRUB 2 seine `grub.cfg` erzeugt." },
|
||||
{ "id": "d", "text": "`/etc/lilo.conf`", "correct": false, "explanation": "Das ist die Konfiguration des Bootloaders LILO." },
|
||||
{ "id": "e", "text": "`/boot/efi/grub.ini`", "correct": false, "explanation": "Eine solche Datei gibt es bei GRUB nicht." }
|
||||
],
|
||||
"explanation": "Unterschied: GRUB Legacy wird direkt über `menu.lst` konfiguriert (Partitionen ab `(hd0,0)` gezählt), GRUB 2 über generierte `grub.cfg` (Partitionen ab 1, z. B. `(hd0,1)`).",
|
||||
"references": ["info grub"]
|
||||
},
|
||||
{
|
||||
"id": "102.3-001",
|
||||
"objective": "102.3",
|
||||
"type": "single",
|
||||
"difficulty": 1,
|
||||
"question": "Welcher Befehl zeigt an, welche Shared Libraries ein Programm wie `/usr/bin/ssh` benötigt?",
|
||||
"options": [
|
||||
{ "id": "a", "text": "`ldd /usr/bin/ssh`", "correct": true, "explanation": "`ldd` listet die benötigten Bibliotheken und den Pfad, über den sie aufgelöst werden." },
|
||||
{ "id": "b", "text": "`ldconfig /usr/bin/ssh`", "correct": false, "explanation": "`ldconfig` aktualisiert Links und den Cache `/etc/ld.so.cache`; es analysiert keine Programme." },
|
||||
{ "id": "c", "text": "`ldconfig -p`", "correct": false, "explanation": "`ldconfig -p` zeigt alle Bibliotheken im Cache, nicht die eines bestimmten Programms." },
|
||||
{ "id": "d", "text": "`ld /usr/bin/ssh`", "correct": false, "explanation": "`ld` ist der Linker zum Bauen von Programmen." },
|
||||
{ "id": "e", "text": "`lsmod /usr/bin/ssh`", "correct": false, "explanation": "`lsmod` listet Kernelmodule, keine Bibliotheken." }
|
||||
],
|
||||
"explanation": "Der dynamische Linker (`ld-linux.so`) lädt beim Start die Bibliotheken. Er sucht über `LD_LIBRARY_PATH`, den Cache `/etc/ld.so.cache` und die Standardpfade.",
|
||||
"references": ["man 1 ldd", "man 8 ld.so"]
|
||||
},
|
||||
{
|
||||
"id": "102.3-002",
|
||||
"objective": "102.3",
|
||||
"type": "multi",
|
||||
"difficulty": 2,
|
||||
"question": "Eine Bibliothek wurde nach `/opt/app/lib` installiert und soll **dauerhaft für alle Programme** gefunden werden. Welche Schritte sind nötig?",
|
||||
"options": [
|
||||
{ "id": "a", "text": "Den Pfad in eine Datei unter `/etc/ld.so.conf.d/` eintragen", "correct": true, "explanation": "`/etc/ld.so.conf` bindet die Dateien aus `ld.so.conf.d/` ein; dort stehen zusätzliche Suchpfade." },
|
||||
{ "id": "b", "text": "`ldconfig` ausführen", "correct": true, "explanation": "`ldconfig` liest die Pfade ein und erzeugt den Cache `/etc/ld.so.cache` neu." },
|
||||
{ "id": "c", "text": "`ldd /opt/app/lib` ausführen", "correct": false, "explanation": "`ldd` zeigt nur Abhängigkeiten eines Programms an und ändert nichts." },
|
||||
{ "id": "d", "text": "`LD_LIBRARY_PATH` in `/etc/ld.so.conf` setzen", "correct": false, "explanation": "In `ld.so.conf` stehen Pfade, keine Variablenzuweisungen. `LD_LIBRARY_PATH` ist eine Umgebungsvariable der Shell." },
|
||||
{ "id": "e", "text": "Die Bibliothek nach `/proc/lib` kopieren", "correct": false, "explanation": "`/proc` ist ein virtuelles Dateisystem; dorthin kann man nichts dauerhaft kopieren." }
|
||||
],
|
||||
"explanation": "Dauerhaft: Pfad in `/etc/ld.so.conf(.d)` und `ldconfig`. Nur vorübergehend, für eine Sitzung oder einen Aufruf: `export LD_LIBRARY_PATH=/opt/app/lib`.",
|
||||
"references": ["man 8 ldconfig"]
|
||||
},
|
||||
{
|
||||
"id": "102.4-001",
|
||||
"objective": "102.4",
|
||||
"type": "single",
|
||||
"difficulty": 1,
|
||||
"question": "Welcher Befehl listet alle Dateien auf, die das **installierte** Debian-Paket `openssh-server` auf dem System abgelegt hat?",
|
||||
"options": [
|
||||
{ "id": "a", "text": "`dpkg -L openssh-server`", "correct": true, "explanation": "`-L` (`--listfiles`) listet die Dateien eines installierten Pakets." },
|
||||
{ "id": "b", "text": "`dpkg -l openssh-server`", "correct": false, "explanation": "`-l` zeigt nur Status, Version und Beschreibung in Kurzform." },
|
||||
{ "id": "c", "text": "`dpkg -S openssh-server`", "correct": false, "explanation": "`-S` sucht, zu welchem Paket ein Dateiname gehört." },
|
||||
{ "id": "d", "text": "`dpkg -c openssh-server`", "correct": false, "explanation": "`-c` listet den Inhalt einer `.deb`-Datei, nicht eines installierten Pakets." },
|
||||
{ "id": "e", "text": "`dpkg -s openssh-server`", "correct": false, "explanation": "`-s` zeigt Status und Metadaten, aber keine Dateiliste." }
|
||||
],
|
||||
"explanation": "Merkhilfe: `-L` Liste der Dateien, `-l` Liste der Pakete, `-S` Suche nach Datei, `-s` Status, `-c` Inhalt einer .deb, `-I` Info zu einer .deb.",
|
||||
"references": ["man 1 dpkg"]
|
||||
},
|
||||
{
|
||||
"id": "102.4-002",
|
||||
"objective": "102.4",
|
||||
"type": "fill",
|
||||
"difficulty": 2,
|
||||
"question": "Mit welchem dpkg-Aufruf (Befehl und Option, **ohne** Dateinamen) findet man heraus, zu welchem installierten Paket die Datei `/usr/bin/ls` gehört?",
|
||||
"answers": ["dpkg -S", "dpkg --search"],
|
||||
"explanation": "`dpkg -S /usr/bin/ls` liefert z. B. `coreutils: /usr/bin/ls`. Für nicht installierte Pakete hilft `apt-file search`.",
|
||||
"references": ["man 1 dpkg"]
|
||||
},
|
||||
{
|
||||
"id": "102.4-003",
|
||||
"objective": "102.4",
|
||||
"type": "single",
|
||||
"difficulty": 1,
|
||||
"question": "Welcher Befehl lädt nur die aktuellen Paketlisten aus den konfigurierten Quellen, ohne Pakete zu installieren oder zu aktualisieren?",
|
||||
"options": [
|
||||
{ "id": "a", "text": "`apt-get update`", "correct": true, "explanation": "`update` aktualisiert den Paketindex aus `/etc/apt/sources.list(.d)`." },
|
||||
{ "id": "b", "text": "`apt-get upgrade`", "correct": false, "explanation": "`upgrade` installiert neuere Versionen bereits installierter Pakete." },
|
||||
{ "id": "c", "text": "`apt-get dist-upgrade`", "correct": false, "explanation": "`dist-upgrade` aktualisiert Pakete und darf dabei auch Pakete hinzufügen oder entfernen." },
|
||||
{ "id": "d", "text": "`apt-cache update`", "correct": false, "explanation": "`apt-cache` fragt nur den Cache ab; einen Unterbefehl `update` gibt es nicht." },
|
||||
{ "id": "e", "text": "`apt-get check`", "correct": false, "explanation": "`check` prüft auf defekte Abhängigkeiten und lädt nichts herunter." }
|
||||
],
|
||||
"explanation": "Typische Reihenfolge: `apt-get update` (Listen), dann `apt-get upgrade` (Pakete). Paketquellen stehen in `/etc/apt/sources.list` und `/etc/apt/sources.list.d/`.",
|
||||
"references": ["man 8 apt-get"]
|
||||
},
|
||||
{
|
||||
"id": "102.4-004",
|
||||
"objective": "102.4",
|
||||
"type": "multi",
|
||||
"difficulty": 2,
|
||||
"question": "Mit welchen Befehlen wird ein Paket **einschließlich seiner Konfigurationsdateien** entfernt?",
|
||||
"options": [
|
||||
{ "id": "a", "text": "`apt-get purge paket`", "correct": true, "explanation": "`purge` entfernt das Paket und seine Konfigurationsdateien." },
|
||||
{ "id": "b", "text": "`dpkg -P paket`", "correct": true, "explanation": "`-P` (`--purge`) entfernt alles einschließlich Konfiguration." },
|
||||
{ "id": "c", "text": "`dpkg -r paket`", "correct": false, "explanation": "`-r` (`--remove`) lässt die Konfigurationsdateien stehen (Status `rc`)." },
|
||||
{ "id": "d", "text": "`apt-get remove paket`", "correct": false, "explanation": "`remove` entspricht `dpkg -r`: Konfigurationsdateien bleiben erhalten." },
|
||||
{ "id": "e", "text": "`apt-get autoremove paket`", "correct": false, "explanation": "`autoremove` entfernt automatisch installierte, nicht mehr benötigte Abhängigkeiten; Konfigurationen bleiben." }
|
||||
],
|
||||
"explanation": "Pakete im Zustand `rc` (removed, config-files) zeigt `dpkg -l`. Sie lassen sich nachträglich mit `dpkg -P` vollständig entfernen.",
|
||||
"references": ["man 1 dpkg", "man 8 apt-get"]
|
||||
},
|
||||
{
|
||||
"id": "102.4-005",
|
||||
"objective": "102.4",
|
||||
"type": "single",
|
||||
"difficulty": 2,
|
||||
"question": "Bei der Installation eines Pakets wurden debconf-Fragen beantwortet. Wie lassen sich diese Fragen **erneut** stellen und die Konfiguration neu erzeugen?",
|
||||
"options": [
|
||||
{ "id": "a", "text": "`dpkg-reconfigure paket`", "correct": true, "explanation": "`dpkg-reconfigure` stellt die debconf-Fragen erneut und konfiguriert das Paket neu." },
|
||||
{ "id": "b", "text": "`dpkg --configure paket`", "correct": false, "explanation": "`--configure` schließt die Konfiguration entpackter Pakete ab; bereits beantwortete Fragen werden nicht erneut gestellt." },
|
||||
{ "id": "c", "text": "`apt-get install --reinstall paket`", "correct": false, "explanation": "Die Antworten liegen in der debconf-Datenbank und werden bei der Neuinstallation wiederverwendet." },
|
||||
{ "id": "d", "text": "`apt-cache policy paket`", "correct": false, "explanation": "`policy` zeigt installierte und verfügbare Versionen sowie die Prioritäten der Quellen." },
|
||||
{ "id": "e", "text": "`debconf-show paket`", "correct": false, "explanation": "`debconf-show` zeigt die gespeicherten Antworten nur an." }
|
||||
],
|
||||
"explanation": "debconf speichert Antworten dauerhaft. Typisches Beispiel: `dpkg-reconfigure tzdata` oder `dpkg-reconfigure locales`.",
|
||||
"references": ["man 8 dpkg-reconfigure"]
|
||||
},
|
||||
{
|
||||
"id": "102.5-001",
|
||||
"objective": "102.5",
|
||||
"type": "single",
|
||||
"difficulty": 1,
|
||||
"question": "Welcher rpm-Befehl ermittelt, zu welchem installierten Paket die Datei `/etc/ssh/sshd_config` gehört?",
|
||||
"options": [
|
||||
{ "id": "a", "text": "`rpm -qf /etc/ssh/sshd_config`", "correct": true, "explanation": "`-q` Abfrage, `-f` (file): Paket, dem die Datei gehört." },
|
||||
{ "id": "b", "text": "`rpm -ql /etc/ssh/sshd_config`", "correct": false, "explanation": "`-ql` listet die Dateien eines Pakets; es erwartet einen Paketnamen." },
|
||||
{ "id": "c", "text": "`rpm -qi /etc/ssh/sshd_config`", "correct": false, "explanation": "`-qi` zeigt Informationen zu einem Paket; es erwartet einen Paketnamen." },
|
||||
{ "id": "d", "text": "`rpm -V /etc/ssh/sshd_config`", "correct": false, "explanation": "`-V` prüft installierte Pakete auf Änderungen gegenüber der RPM-Datenbank." },
|
||||
{ "id": "e", "text": "`rpm -qa /etc/ssh/sshd_config`", "correct": false, "explanation": "`-qa` listet alle installierten Pakete (das Argument wird als Muster gelesen, nicht als Datei)." }
|
||||
],
|
||||
"explanation": "Abfragen beginnen mit `-q`: `-qa` alle, `-qi` Info, `-ql` Dateien, `-qf` Besitzer einer Datei, `-qc` Konfigurationsdateien, `-qR` Abhängigkeiten, `-qp` für eine .rpm-Datei.",
|
||||
"references": ["man 8 rpm"]
|
||||
},
|
||||
{
|
||||
"id": "102.5-002",
|
||||
"objective": "102.5",
|
||||
"type": "fill",
|
||||
"difficulty": 1,
|
||||
"question": "Geben Sie den rpm-Befehl ein, der alle Dateien des installierten Pakets `bash` auflistet.",
|
||||
"answers": ["rpm -ql bash", "rpm -q -l bash", "rpm -q --list bash", "rpm --query --list bash"],
|
||||
"explanation": "`-q` (query) mit `-l` (list). Für eine noch nicht installierte Datei: `rpm -qlp paket.rpm`.",
|
||||
"references": ["man 8 rpm"]
|
||||
},
|
||||
{
|
||||
"id": "102.5-003",
|
||||
"objective": "102.5",
|
||||
"type": "single",
|
||||
"difficulty": 2,
|
||||
"question": "Welcher rpm-Aufruf aktualisiert ein Paket aus einer .rpm-Datei – und installiert es, falls es noch nicht vorhanden ist?",
|
||||
"options": [
|
||||
{ "id": "a", "text": "`rpm -Uvh paket.rpm`", "correct": true, "explanation": "`-U` (upgrade) aktualisiert oder installiert; `-v` ausführlich, `-h` Fortschrittsbalken." },
|
||||
{ "id": "b", "text": "`rpm -Fvh paket.rpm`", "correct": false, "explanation": "`-F` (freshen) aktualisiert nur, wenn das Paket bereits installiert ist." },
|
||||
{ "id": "c", "text": "`rpm -ivh paket.rpm`", "correct": false, "explanation": "`-i` installiert neu; bei installierter älterer Version entsteht ein Konflikt (Ausnahme: z. B. Kernel parallel)." },
|
||||
{ "id": "d", "text": "`rpm -e paket.rpm`", "correct": false, "explanation": "`-e` (erase) entfernt ein Paket." },
|
||||
{ "id": "e", "text": "`rpm -Vp paket.rpm`", "correct": false, "explanation": "`-V` prüft, es installiert nichts." }
|
||||
],
|
||||
"explanation": "rpm löst keine Abhängigkeiten aus Repositories auf – dafür gibt es `dnf`/`yum` bzw. `zypper`.",
|
||||
"references": ["man 8 rpm"]
|
||||
},
|
||||
{
|
||||
"id": "102.5-004",
|
||||
"objective": "102.5",
|
||||
"type": "multi",
|
||||
"difficulty": 1,
|
||||
"question": "Welche Werkzeuge installieren RPM-Pakete aus Repositories und lösen dabei Abhängigkeiten automatisch auf?",
|
||||
"options": [
|
||||
{ "id": "a", "text": "`dnf`", "correct": true, "explanation": "Nachfolger von yum, Standard bei Fedora und RHEL ab Version 8." },
|
||||
{ "id": "b", "text": "`yum`", "correct": true, "explanation": "Klassisches Frontend der Red-Hat-Familie; Repos in `/etc/yum.repos.d/`." },
|
||||
{ "id": "c", "text": "`zypper`", "correct": true, "explanation": "Paketverwaltung von openSUSE/SLES, ebenfalls auf RPM-Basis." },
|
||||
{ "id": "d", "text": "`rpm2cpio`", "correct": false, "explanation": "`rpm2cpio` wandelt ein RPM in ein cpio-Archiv um, installiert aber nichts." },
|
||||
{ "id": "e", "text": "`dpkg`", "correct": false, "explanation": "`dpkg` verwaltet Debian-Pakete und löst keine Abhängigkeiten aus Repositories auf." }
|
||||
],
|
||||
"explanation": "rpm ist die Basisschicht, `dnf`/`yum`/`zypper` sind die Frontends mit Repository- und Abhängigkeitsverwaltung (vergleichbar mit dpkg und apt).",
|
||||
"references": ["man 8 dnf", "man 8 zypper"]
|
||||
},
|
||||
{
|
||||
"id": "102.5-005",
|
||||
"objective": "102.5",
|
||||
"type": "single",
|
||||
"difficulty": 2,
|
||||
"question": "Wie entpackt man die Dateien aus `paket.rpm` in das aktuelle Verzeichnis, **ohne** das Paket zu installieren?",
|
||||
"options": [
|
||||
{ "id": "a", "text": "`rpm2cpio paket.rpm | cpio -idmv`", "correct": true, "explanation": "`rpm2cpio` gibt den Inhalt als cpio-Strom aus, `cpio -i` entpackt (`-d` Verzeichnisse anlegen, `-m` Zeiten erhalten)." },
|
||||
{ "id": "b", "text": "`rpm -x paket.rpm`", "correct": false, "explanation": "rpm hat keine Option `-x` zum Entpacken." },
|
||||
{ "id": "c", "text": "`cpio -i < paket.rpm`", "correct": false, "explanation": "Eine RPM-Datei hat einen eigenen Header vor dem Archiv; cpio kann sie nicht direkt lesen." },
|
||||
{ "id": "d", "text": "`tar xf paket.rpm`", "correct": false, "explanation": "RPM ist kein tar-Archiv." },
|
||||
{ "id": "e", "text": "`rpm -qlp paket.rpm`", "correct": false, "explanation": "Das listet nur die enthaltenen Dateien auf, entpackt aber nichts." }
|
||||
],
|
||||
"explanation": "Nützlich, um einzelne Dateien (z. B. eine Original-Konfiguration) aus einem Paket zu holen.",
|
||||
"references": ["man 8 rpm2cpio", "man 1 cpio"]
|
||||
},
|
||||
{
|
||||
"id": "102.6-001",
|
||||
"objective": "102.6",
|
||||
"type": "multi",
|
||||
"difficulty": 2,
|
||||
"question": "Eine Linux-VM wird aus einer Vorlage geklont. Was sollte auf jedem Klon **neu erzeugt** werden, weil es eindeutig sein muss?",
|
||||
"options": [
|
||||
{ "id": "a", "text": "Die D-Bus-/systemd-Maschinen-ID in `/etc/machine-id`", "correct": true, "explanation": "Die Machine-ID identifiziert das System (u. a. Journal, DHCP-Client-ID) und darf nicht doppelt vorkommen." },
|
||||
{ "id": "b", "text": "Die SSH-Host-Schlüssel unter `/etc/ssh/ssh_host_*`", "correct": true, "explanation": "Gleiche Host-Schlüssel auf mehreren Systemen untergraben die Server-Authentifizierung." },
|
||||
{ "id": "c", "text": "Den Kernel unter `/boot`", "correct": false, "explanation": "Der Kernel ist nicht systemspezifisch und kann identisch bleiben." },
|
||||
{ "id": "d", "text": "Die Datei `/etc/services`", "correct": false, "explanation": "`/etc/services` ordnet Portnummern Dienstnamen zu und ist überall gleich." },
|
||||
{ "id": "e", "text": "Die Shared Libraries unter `/usr/lib`", "correct": false, "explanation": "Bibliotheken sind Programmdateien und nicht systemspezifisch." }
|
||||
],
|
||||
"explanation": "Vorlagen werden vorher \"generalisiert\": Machine-ID leeren, SSH-Host-Schlüssel löschen, ggf. Hostname und MAC-gebundene Netzkonfiguration zurücksetzen. cloud-init oder ein Erststart-Skript erzeugt sie neu.",
|
||||
"references": ["man 5 machine-id", "man 8 ssh-keygen"]
|
||||
},
|
||||
{
|
||||
"id": "102.6-002",
|
||||
"objective": "102.6",
|
||||
"type": "single",
|
||||
"difficulty": 1,
|
||||
"question": "Welches Werkzeug richtet Cloud-Instanzen beim ersten Start anhand von Metadaten des Anbieters ein (Hostname, Benutzer, SSH-Schlüssel, Pakete)?",
|
||||
"options": [
|
||||
{ "id": "a", "text": "cloud-init", "correct": true, "explanation": "cloud-init liest Meta- und User-Data (z. B. `#cloud-config` in YAML) und konfiguriert das System beim ersten Start." },
|
||||
{ "id": "b", "text": "Kickstart", "correct": false, "explanation": "Kickstart ist eine Antwortdatei für die automatisierte Installation mit Anaconda, nicht für den Start einer fertigen Instanz." },
|
||||
{ "id": "c", "text": "`virt-install`", "correct": false, "explanation": "`virt-install` legt auf dem Host neue libvirt-VMs an; im Gast konfiguriert es nichts." },
|
||||
{ "id": "d", "text": "`dmidecode`", "correct": false, "explanation": "`dmidecode` liest Hardware-Informationen (DMI/SMBIOS) aus." },
|
||||
{ "id": "e", "text": "`qemu-img`", "correct": false, "explanation": "`qemu-img` erstellt und konvertiert Abbilder virtueller Festplatten." }
|
||||
],
|
||||
"explanation": "Begriffe aus 102.6: Virtuelle Maschine, Linux-Container, Anwendungs-Container, Gasttreiber, SSH-Host-Schlüssel, D-Bus-Machine-ID, cloud-init.",
|
||||
"references": ["https://cloudinit.readthedocs.io/"]
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,582 @@
|
||||
{
|
||||
"$schema": "../schema/questions.schema.json",
|
||||
"format": "lpic-sim-questions",
|
||||
"meta": {
|
||||
"file": "questions_103.json",
|
||||
"brief": "Fragen zu Topic 103 GNU- und Unix-Befehle (LPIC-1 101-500, Objectives 5.0)",
|
||||
"author": "Björn Runden <br@runden.de>",
|
||||
"owner": "Björn Runden <br@runden.de>",
|
||||
"assist": "KI-unterstützt (Claude Opus 5.5), geprüft von Björn Runden <br@runden.de>",
|
||||
"version": "0.1.0 (29.10.2026)"
|
||||
},
|
||||
"exam": "lpic1-101",
|
||||
"questions": [
|
||||
{
|
||||
"id": "103.1-001",
|
||||
"objective": "103.1",
|
||||
"type": "single",
|
||||
"difficulty": 1,
|
||||
"question": "Eine Shell-Variable `PROJEKT` soll auch in Programmen sichtbar sein, die aus der aktuellen Shell gestartet werden. Welcher Befehl leistet das?",
|
||||
"options": [
|
||||
{ "id": "a", "text": "`export PROJEKT`", "correct": true, "explanation": "`export` übernimmt die Variable in die Umgebung, die an Kindprozesse vererbt wird." },
|
||||
{ "id": "b", "text": "`set PROJEKT`", "correct": false, "explanation": "`set` setzt Shell-Optionen bzw. Positionsparameter; es exportiert keine Variable." },
|
||||
{ "id": "c", "text": "`env PROJEKT`", "correct": false, "explanation": "`env` würde versuchen, ein Programm namens `PROJEKT` mit der aktuellen Umgebung zu starten." },
|
||||
{ "id": "d", "text": "`local PROJEKT`", "correct": false, "explanation": "`local` erzeugt eine lokale Variable innerhalb einer Shell-Funktion." },
|
||||
{ "id": "e", "text": "`declare -r PROJEKT`", "correct": false, "explanation": "`declare -r` macht die Variable schreibgeschützt, exportiert sie aber nicht (das wäre `declare -x`)." }
|
||||
],
|
||||
"explanation": "Shell-Variablen gelten nur in der aktuellen Shell, Umgebungsvariablen werden vererbt. Anzeige: `set` (alle Shell-Variablen und Funktionen), `env`/`printenv` (nur Umgebung).",
|
||||
"references": ["man 1 bash (Abschnitt ENVIRONMENT)"]
|
||||
},
|
||||
{
|
||||
"id": "103.1-002",
|
||||
"objective": "103.1",
|
||||
"type": "single",
|
||||
"difficulty": 1,
|
||||
"question": "Welcher Befehl gibt den Text `$HOME` **wörtlich** aus, also ohne ihn durch den Pfad des Home-Verzeichnisses zu ersetzen?",
|
||||
"options": [
|
||||
{ "id": "a", "text": "`echo '$HOME'`", "correct": true, "explanation": "In einfachen Anführungszeichen findet keinerlei Ersetzung statt." },
|
||||
{ "id": "b", "text": "`echo \"$HOME\"`", "correct": false, "explanation": "In doppelten Anführungszeichen werden Variablen ersetzt; nur die Worttrennung unterbleibt." },
|
||||
{ "id": "c", "text": "`echo $HOME`", "correct": false, "explanation": "Ohne Quoting wird die Variable ersetzt." },
|
||||
{ "id": "d", "text": "`echo ${HOME}`", "correct": false, "explanation": "`${…}` ist die ausführliche Schreibweise der Variablenersetzung." },
|
||||
{ "id": "e", "text": "`echo $(HOME)`", "correct": false, "explanation": "`$(…)` ist Befehlsersetzung: Die Shell versucht, einen Befehl `HOME` auszuführen." }
|
||||
],
|
||||
"explanation": "Quoting: `'…'` alles wörtlich, `\"…\"` Variablen und Befehlsersetzung aktiv, `\\` maskiert ein einzelnes Zeichen (z. B. `echo \\$HOME`).",
|
||||
"references": ["man 1 bash (Abschnitt QUOTING)"]
|
||||
},
|
||||
{
|
||||
"id": "103.1-003",
|
||||
"objective": "103.1",
|
||||
"type": "fill",
|
||||
"difficulty": 2,
|
||||
"question": "Welches Shell-Builtin zeigt an, ob `ls` ein Alias, eine Funktion, ein Builtin oder ein Programm im `PATH` ist? (nur der Befehlsname)",
|
||||
"answers": ["type"],
|
||||
"explanation": "`type ls` liefert z. B. `ls is aliased to 'ls --color=auto'`. `which` sucht dagegen nur Programme im `PATH` und kennt keine Aliase oder Builtins.",
|
||||
"references": ["help type"]
|
||||
},
|
||||
{
|
||||
"id": "103.1-004",
|
||||
"objective": "103.1",
|
||||
"type": "multi",
|
||||
"difficulty": 2,
|
||||
"question": "Welche Aussagen zur Bash-History treffen zu?",
|
||||
"options": [
|
||||
{ "id": "a", "text": "`!!` führt den zuletzt eingegebenen Befehl erneut aus.", "correct": true, "explanation": "History-Expansion: `!!` steht für den vorherigen Befehl, z. B. `sudo !!`." },
|
||||
{ "id": "b", "text": "Die History wird standardmäßig in `~/.bash_history` gespeichert.", "correct": true, "explanation": "Die Datei legt `HISTFILE` fest; Standard ist `~/.bash_history`." },
|
||||
{ "id": "c", "text": "`history -c` löscht die Datei `~/.bash_history` sofort.", "correct": false, "explanation": "`history -c` leert nur die History im Speicher der laufenden Shell." },
|
||||
{ "id": "d", "text": "`HISTSIZE` legt die maximale Zeilenzahl der History-Datei fest.", "correct": false, "explanation": "`HISTSIZE` gilt für die History im Speicher, `HISTFILESIZE` für die Datei." },
|
||||
{ "id": "e", "text": "`!42` zeigt Befehl Nummer 42 an, ohne ihn auszuführen.", "correct": false, "explanation": "`!42` führt den Befehl aus. Nur anzeigen: `!42:p`." }
|
||||
],
|
||||
"explanation": "Weitere Expansionen: `!$` letztes Argument, `!str` letzter Befehl, der mit `str` beginnt. Strg+R sucht rückwärts in der History.",
|
||||
"references": ["man 1 bash (Abschnitt HISTORY EXPANSION)"]
|
||||
},
|
||||
{
|
||||
"id": "103.1-005",
|
||||
"objective": "103.1",
|
||||
"type": "single",
|
||||
"difficulty": 1,
|
||||
"question": "Welcher Befehl gibt **nur** die Release-Version des laufenden Kernels aus (z. B. `6.1.0-18-amd64`)?",
|
||||
"options": [
|
||||
{ "id": "a", "text": "`uname -r`", "correct": true, "explanation": "`-r` (kernel release) gibt genau die Release-Bezeichnung aus." },
|
||||
{ "id": "b", "text": "`uname -a`", "correct": false, "explanation": "`-a` gibt alle Informationen aus: Name, Host, Release, Version, Architektur …" },
|
||||
{ "id": "c", "text": "`uname -m`", "correct": false, "explanation": "`-m` zeigt die Hardware-Architektur, z. B. `x86_64`." },
|
||||
{ "id": "d", "text": "`uname -n`", "correct": false, "explanation": "`-n` zeigt den Hostnamen (nodename)." },
|
||||
{ "id": "e", "text": "`uname -s`", "correct": false, "explanation": "`-s` zeigt den Kernelnamen, also `Linux`." }
|
||||
],
|
||||
"explanation": "`uname -r` wird oft in Pfaden genutzt, z. B. `/lib/modules/$(uname -r)/`.",
|
||||
"references": ["man 1 uname"]
|
||||
},
|
||||
{
|
||||
"id": "103.1-006",
|
||||
"objective": "103.1",
|
||||
"type": "single",
|
||||
"difficulty": 2,
|
||||
"question": "Wie entfernt man die Variable `TMPDIR` **vollständig** aus der aktuellen Shell?",
|
||||
"options": [
|
||||
{ "id": "a", "text": "`unset TMPDIR`", "correct": true, "explanation": "`unset` löscht die Variable; danach ist sie weder gesetzt noch exportiert." },
|
||||
{ "id": "b", "text": "`TMPDIR=\"\"`", "correct": false, "explanation": "Die Variable bleibt gesetzt, nur ihr Wert ist leer." },
|
||||
{ "id": "c", "text": "`export -n TMPDIR`", "correct": false, "explanation": "`export -n` nimmt nur das Export-Attribut weg; die Shell-Variable bleibt bestehen." },
|
||||
{ "id": "d", "text": "`env -u TMPDIR`", "correct": false, "explanation": "`env -u` entfernt die Variable nur aus der Umgebung des damit gestarteten Befehls." },
|
||||
{ "id": "e", "text": "`set -u TMPDIR`", "correct": false, "explanation": "`set -u` lässt die Shell bei Zugriff auf ungesetzte Variablen einen Fehler melden; `TMPDIR` wird dabei zum Positionsparameter." }
|
||||
],
|
||||
"explanation": "Unterschied gesetzt/leer: `${VAR-x}` liefert `x` nur, wenn `VAR` ungesetzt ist, `${VAR:-x}` auch bei leerem Wert.",
|
||||
"references": ["help unset"]
|
||||
},
|
||||
{
|
||||
"id": "103.2-001",
|
||||
"objective": "103.2",
|
||||
"type": "single",
|
||||
"difficulty": 1,
|
||||
"question": "Welche Befehlskette gibt genau die Zeilen 11 bis 20 einer Datei aus?",
|
||||
"options": [
|
||||
{ "id": "a", "text": "`head -n 20 datei | tail -n 10`", "correct": true, "explanation": "Erst die ersten 20 Zeilen, davon die letzten 10 – also 11 bis 20." },
|
||||
{ "id": "b", "text": "`tail -n 20 datei | head -n 10`", "correct": false, "explanation": "Das liefert die ersten 10 der letzten 20 Zeilen der Datei." },
|
||||
{ "id": "c", "text": "`sed -n '10,20p' datei`", "correct": false, "explanation": "Gibt Zeilen 10 bis 20 aus, also 11 Zeilen." },
|
||||
{ "id": "d", "text": "`head -n 11-20 datei`", "correct": false, "explanation": "`head` kennt keine Bereichsangabe." },
|
||||
{ "id": "e", "text": "`cut -c 11-20 datei`", "correct": false, "explanation": "`cut -c` wählt Zeichen 11 bis 20 jeder Zeile, keine Zeilen." }
|
||||
],
|
||||
"explanation": "Alternativ `sed -n '11,20p' datei`. `tail -n +11` gibt alles ab Zeile 11 aus.",
|
||||
"references": ["man 1 head", "man 1 tail"]
|
||||
},
|
||||
{
|
||||
"id": "103.2-002",
|
||||
"objective": "103.2",
|
||||
"type": "single",
|
||||
"difficulty": 1,
|
||||
"question": "Welcher Befehl gibt nur die Benutzernamen (das erste Feld) aus `/etc/passwd` aus?",
|
||||
"options": [
|
||||
{ "id": "a", "text": "`cut -d: -f1 /etc/passwd`", "correct": true, "explanation": "`-d:` setzt den Doppelpunkt als Trenner, `-f1` wählt das erste Feld." },
|
||||
{ "id": "b", "text": "`cut -f1 /etc/passwd`", "correct": false, "explanation": "Ohne `-d` trennt `cut` an Tabulatoren; die Zeilen werden ganz ausgegeben." },
|
||||
{ "id": "c", "text": "`sort -t: -k1 /etc/passwd`", "correct": false, "explanation": "Das sortiert nach dem ersten Feld, gibt aber vollständige Zeilen aus." },
|
||||
{ "id": "d", "text": "`tr ':' ' ' < /etc/passwd`", "correct": false, "explanation": "`tr` ersetzt nur die Doppelpunkte durch Leerzeichen." },
|
||||
{ "id": "e", "text": "`paste -d: /etc/passwd`", "correct": false, "explanation": "`paste` fügt Zeilen mehrerer Dateien nebeneinander; mit einer Datei gibt es sie unverändert aus." }
|
||||
],
|
||||
"explanation": "Gleichwertig: `awk -F: '{print $1}' /etc/passwd`.",
|
||||
"references": ["man 1 cut"]
|
||||
},
|
||||
{
|
||||
"id": "103.2-003",
|
||||
"objective": "103.2",
|
||||
"type": "single",
|
||||
"difficulty": 2,
|
||||
"question": "In einer unsortierten Datei sollen alle Zeilen mit der Anzahl ihres Vorkommens ausgegeben werden. Welche Befehlskette ist korrekt?",
|
||||
"options": [
|
||||
{ "id": "a", "text": "`sort datei | uniq -c`", "correct": true, "explanation": "`uniq` fasst nur benachbarte gleiche Zeilen zusammen; daher vorher sortieren." },
|
||||
{ "id": "b", "text": "`uniq -c datei`", "correct": false, "explanation": "Ohne Sortierung werden gleiche, aber nicht benachbarte Zeilen getrennt gezählt." },
|
||||
{ "id": "c", "text": "`sort -u datei | wc -l`", "correct": false, "explanation": "Das zählt nur die Anzahl verschiedener Zeilen." },
|
||||
{ "id": "d", "text": "`uniq -d datei | sort`", "correct": false, "explanation": "`uniq -d` zeigt nur benachbarte doppelte Zeilen, ohne Zählung." },
|
||||
{ "id": "e", "text": "`cat -n datei | uniq`", "correct": false, "explanation": "Durch die Zeilennummern sind alle Zeilen verschieden; nichts wird zusammengefasst." }
|
||||
],
|
||||
"explanation": "Häufigste Zeilen zuerst: `sort datei | uniq -c | sort -nr`.",
|
||||
"references": ["man 1 uniq", "man 1 sort"]
|
||||
},
|
||||
{
|
||||
"id": "103.3-001",
|
||||
"objective": "103.3",
|
||||
"type": "single",
|
||||
"difficulty": 1,
|
||||
"question": "Ein Verzeichnis soll rekursiv kopiert werden; Rechte, Eigentümer, Zeitstempel und symbolische Links sollen erhalten bleiben. Welcher Befehl ist geeignet?",
|
||||
"options": [
|
||||
{ "id": "a", "text": "`cp -a quelle ziel`", "correct": true, "explanation": "`-a` (archive) entspricht `-dR --preserve=all`: rekursiv, Links als Links, alle Attribute." },
|
||||
{ "id": "b", "text": "`cp -r quelle ziel`", "correct": false, "explanation": "`-r` kopiert rekursiv, übernimmt aber Eigentümer und Zeitstempel nicht." },
|
||||
{ "id": "c", "text": "`cp -p quelle ziel`", "correct": false, "explanation": "`-p` erhält Attribute, kopiert aber Verzeichnisse nicht rekursiv." },
|
||||
{ "id": "d", "text": "`cp -l quelle ziel`", "correct": false, "explanation": "`-l` legt Hardlinks statt Kopien an." },
|
||||
{ "id": "e", "text": "`mv -a quelle ziel`", "correct": false, "explanation": "`mv` verschiebt und kennt keine Option `-a`." }
|
||||
],
|
||||
"explanation": "Eigentümer kann nur root übernehmen; als normaler Benutzer gehören Kopien dem Kopierenden.",
|
||||
"references": ["man 1 cp"]
|
||||
},
|
||||
{
|
||||
"id": "103.3-002",
|
||||
"objective": "103.3",
|
||||
"type": "fill",
|
||||
"difficulty": 2,
|
||||
"question": "Geben Sie den `find`-Befehl ein, der unterhalb von `/var` alle Dateien findet, die **größer als 100 MiB** sind.",
|
||||
"answers": ["find /var -size +100M", "find /var -type f -size +100M", "find /var -size +100M -type f"],
|
||||
"explanation": "`-size +100M`: größer als 100 MiB (`k`, `M`, `G` als Einheiten). `-size -100M` wäre kleiner. `-type f` beschränkt auf reguläre Dateien.",
|
||||
"references": ["man 1 find"]
|
||||
},
|
||||
{
|
||||
"id": "103.3-003",
|
||||
"objective": "103.3",
|
||||
"type": "single",
|
||||
"difficulty": 1,
|
||||
"question": "Welcher Befehl erstellt ein gzip-komprimiertes tar-Archiv `backup.tar.gz` von `/etc`?",
|
||||
"options": [
|
||||
{ "id": "a", "text": "`tar -czf backup.tar.gz /etc`", "correct": true, "explanation": "`c` create, `z` gzip, `f` Archivdatei." },
|
||||
{ "id": "b", "text": "`tar -xzf backup.tar.gz /etc`", "correct": false, "explanation": "`x` entpackt – hier würde nur `/etc` aus dem Archiv extrahiert." },
|
||||
{ "id": "c", "text": "`tar -cjf backup.tar.gz /etc`", "correct": false, "explanation": "`j` komprimiert mit bzip2; der Name `.gz` wäre irreführend." },
|
||||
{ "id": "d", "text": "`tar -tzf backup.tar.gz /etc`", "correct": false, "explanation": "`t` listet den Inhalt eines vorhandenen Archivs." },
|
||||
{ "id": "e", "text": "`gzip -r /etc > backup.tar.gz`", "correct": false, "explanation": "`gzip -r` komprimiert jede Datei in `/etc` einzeln an Ort und Stelle; es entsteht kein Archiv." }
|
||||
],
|
||||
"explanation": "Kompression bei tar: `z` gzip, `j` bzip2, `J` xz. Modi: `c` erstellen, `x` entpacken, `t` auflisten.",
|
||||
"references": ["man 1 tar"]
|
||||
},
|
||||
{
|
||||
"id": "103.3-004",
|
||||
"objective": "103.3",
|
||||
"type": "multi",
|
||||
"difficulty": 2,
|
||||
"question": "Welche Dateinamen passen auf das Shell-Muster `d?t[0-9]*`?",
|
||||
"options": [
|
||||
{ "id": "a", "text": "`dat1`", "correct": true, "explanation": "`d`, beliebiges Zeichen `a`, `t`, Ziffer `1`, danach nichts (`*` darf leer sein)." },
|
||||
{ "id": "b", "text": "`dot42.txt`", "correct": true, "explanation": "`d`, `o`, `t`, Ziffer `4`, Rest `2.txt` passt auf `*`." },
|
||||
{ "id": "c", "text": "`dt1`", "correct": false, "explanation": "`?` verlangt genau ein Zeichen zwischen `d` und `t`." },
|
||||
{ "id": "d", "text": "`data1`", "correct": false, "explanation": "Das vierte Zeichen `a` ist keine Ziffer." },
|
||||
{ "id": "e", "text": "`Dat1`", "correct": false, "explanation": "Globbing unterscheidet Groß- und Kleinschreibung; `D` ist nicht `d`." }
|
||||
],
|
||||
"explanation": "Globbing: `*` beliebig viele Zeichen (auch keine), `?` genau ein Zeichen, `[…]` ein Zeichen aus der Menge, `[!…]` ein Zeichen nicht aus der Menge.",
|
||||
"references": ["man 7 glob"]
|
||||
},
|
||||
{
|
||||
"id": "103.3-005",
|
||||
"objective": "103.3",
|
||||
"type": "single",
|
||||
"difficulty": 1,
|
||||
"question": "Welcher Befehl ermittelt den Typ einer Datei anhand ihres Inhalts (z. B. „ELF 64-bit executable“ oder „gzip compressed data“)?",
|
||||
"options": [
|
||||
{ "id": "a", "text": "`file`", "correct": true, "explanation": "`file` vergleicht den Inhalt mit Signaturen (Magic Numbers)." },
|
||||
{ "id": "b", "text": "`stat`", "correct": false, "explanation": "`stat` zeigt Metadaten aus dem Inode (Größe, Rechte, Zeiten), nicht den Inhaltstyp." },
|
||||
{ "id": "c", "text": "`type`", "correct": false, "explanation": "`type` bestimmt, wie die Shell einen Befehlsnamen auflöst." },
|
||||
{ "id": "d", "text": "`ls -l`", "correct": false, "explanation": "`ls -l` zeigt nur den Dateityp im Sinne von Datei/Verzeichnis/Link usw." },
|
||||
{ "id": "e", "text": "`which`", "correct": false, "explanation": "`which` sucht ein Programm im `PATH`." }
|
||||
],
|
||||
"explanation": "Unter Linux bestimmt nicht die Endung den Typ, sondern der Inhalt; `file` wertet dazu die magic-Datenbank aus.",
|
||||
"references": ["man 1 file"]
|
||||
},
|
||||
{
|
||||
"id": "103.3-006",
|
||||
"objective": "103.3",
|
||||
"type": "single",
|
||||
"difficulty": 2,
|
||||
"question": "Der Master Boot Record (erster Sektor, 512 Byte) von `/dev/sda` soll in die Datei `mbr.img` gesichert werden. Welcher Befehl ist korrekt?",
|
||||
"options": [
|
||||
{ "id": "a", "text": "`dd if=/dev/sda of=mbr.img bs=512 count=1`", "correct": true, "explanation": "`if` Quelle, `of` Ziel, ein Block zu 512 Byte." },
|
||||
{ "id": "b", "text": "`dd if=mbr.img of=/dev/sda bs=512 count=1`", "correct": false, "explanation": "Quelle und Ziel sind vertauscht – das würde den MBR mit der Datei überschreiben." },
|
||||
{ "id": "c", "text": "`dd if=/dev/sda of=mbr.img bs=512 skip=1 count=1`", "correct": false, "explanation": "`skip=1` überspringt den ersten Block der Quelle – kopiert würde der zweite Sektor, nicht der MBR." },
|
||||
{ "id": "d", "text": "`dd if=/dev/sda1 of=mbr.img bs=512 count=1`", "correct": false, "explanation": "`/dev/sda1` ist die erste Partition; der MBR liegt am Anfang der ganzen Platte." },
|
||||
{ "id": "e", "text": "`cp /dev/sda mbr.img`", "correct": false, "explanation": "Das würde die gesamte Platte kopieren, nicht nur den ersten Sektor." }
|
||||
],
|
||||
"explanation": "Der MBR enthält Bootloader-Code (446 Byte), Partitionstabelle (64 Byte) und Signatur (2 Byte).",
|
||||
"references": ["man 1 dd"]
|
||||
},
|
||||
{
|
||||
"id": "103.4-001",
|
||||
"objective": "103.4",
|
||||
"type": "single",
|
||||
"difficulty": 2,
|
||||
"question": "Standardausgabe **und** Fehlerausgabe eines Befehls sollen in dieselbe Datei geschrieben werden. Welche Schreibweise ist korrekt?",
|
||||
"options": [
|
||||
{ "id": "a", "text": "`befehl > log.txt 2>&1`", "correct": true, "explanation": "Erst stdout in die Datei, dann stderr auf das (bereits umgelenkte) stdout." },
|
||||
{ "id": "b", "text": "`befehl 2>&1 > log.txt`", "correct": false, "explanation": "Reihenfolge: stderr wird auf das ursprüngliche stdout (Terminal) gelegt, erst danach stdout in die Datei." },
|
||||
{ "id": "c", "text": "`befehl 2> log.txt`", "correct": false, "explanation": "Nur die Fehlerausgabe landet in der Datei." },
|
||||
{ "id": "d", "text": "`befehl | log.txt`", "correct": false, "explanation": "Die Pipe erwartet einen Befehl; `log.txt` würde als Programm gesucht." },
|
||||
{ "id": "e", "text": "`befehl >> log.txt 1>&2`", "correct": false, "explanation": "`1>&2` lenkt stdout anschließend wieder auf stderr (Terminal) um; die Datei bleibt leer." }
|
||||
],
|
||||
"explanation": "Umleitungen werden von links nach rechts ausgewertet. Bash-Kurzform: `befehl &> log.txt`.",
|
||||
"references": ["man 1 bash (Abschnitt REDIRECTION)"]
|
||||
},
|
||||
{
|
||||
"id": "103.4-002",
|
||||
"objective": "103.4",
|
||||
"type": "fill",
|
||||
"difficulty": 1,
|
||||
"question": "Welche Umleitung (nur die Umleitung, ohne Befehl) verwirft die **Fehlerausgabe** eines Befehls?",
|
||||
"answers": ["2>/dev/null", "2> /dev/null"],
|
||||
"explanation": "Dateideskriptor 2 ist stderr; `/dev/null` verwirft alles, was hineingeschrieben wird.",
|
||||
"references": ["man 4 null"]
|
||||
},
|
||||
{
|
||||
"id": "103.4-003",
|
||||
"objective": "103.4",
|
||||
"type": "single",
|
||||
"difficulty": 1,
|
||||
"question": "Die Ausgabe eines Befehls soll auf dem Bildschirm erscheinen **und** gleichzeitig in `ausgabe.txt` gespeichert werden. Wie geht das?",
|
||||
"options": [
|
||||
{ "id": "a", "text": "`befehl | tee ausgabe.txt`", "correct": true, "explanation": "`tee` kopiert stdin nach stdout und zusätzlich in die Datei(en); `-a` hängt an." },
|
||||
{ "id": "b", "text": "`befehl > ausgabe.txt | cat`", "correct": false, "explanation": "stdout geht vollständig in die Datei; an `cat` kommt nichts an." },
|
||||
{ "id": "c", "text": "`befehl >> ausgabe.txt`", "correct": false, "explanation": "Hängt nur an die Datei an; auf dem Bildschirm erscheint nichts." },
|
||||
{ "id": "d", "text": "`befehl | cat > ausgabe.txt`", "correct": false, "explanation": "Die Ausgabe landet nur in der Datei." },
|
||||
{ "id": "e", "text": "`befehl 2>&1 ausgabe.txt`", "correct": false, "explanation": "`ausgabe.txt` würde als Argument an den Befehl übergeben." }
|
||||
],
|
||||
"explanation": "`tee` ist wie ein T-Stück in der Pipe. Mit `sudo tee datei` schreibt man z. B. als root in geschützte Dateien.",
|
||||
"references": ["man 1 tee"]
|
||||
},
|
||||
{
|
||||
"id": "103.4-004",
|
||||
"objective": "103.4",
|
||||
"type": "single",
|
||||
"difficulty": 2,
|
||||
"question": "Alle von `find` gefundenen `*.tmp`-Dateien sollen gelöscht werden, indem ihre Namen als **Argumente** an `rm` übergeben werden. Welche Befehlszeile tut das?",
|
||||
"options": [
|
||||
{ "id": "a", "text": "`find . -name '*.tmp' | xargs rm`", "correct": true, "explanation": "`xargs` liest Namen von stdin und hängt sie als Argumente an `rm`." },
|
||||
{ "id": "b", "text": "`find . -name '*.tmp' | rm`", "correct": false, "explanation": "`rm` liest keine Dateinamen von stdin; es meldet fehlende Operanden." },
|
||||
{ "id": "c", "text": "`find . -name '*.tmp' > rm`", "correct": false, "explanation": "Das schreibt die Liste in eine Datei namens `rm`." },
|
||||
{ "id": "d", "text": "`find . -name '*.tmp' | tee rm`", "correct": false, "explanation": "`tee` schreibt die Liste in die Datei `rm` und auf den Bildschirm." },
|
||||
{ "id": "e", "text": "`rm < find . -name '*.tmp'`", "correct": false, "explanation": "`<` erwartet eine Datei als Eingabe, keinen Befehl." }
|
||||
],
|
||||
"explanation": "Bei Namen mit Leerzeichen: `find … -print0 | xargs -0 rm`. Alternativ ohne Pipe: `find . -name '*.tmp' -delete` oder `-exec rm {} +`.",
|
||||
"references": ["man 1 xargs"]
|
||||
},
|
||||
{
|
||||
"id": "103.4-005",
|
||||
"objective": "103.4",
|
||||
"type": "multi",
|
||||
"difficulty": 1,
|
||||
"question": "Welche Aussagen zu Umleitungen und Pipes treffen zu?",
|
||||
"options": [
|
||||
{ "id": "a", "text": "`>>` hängt die Standardausgabe an eine Datei an.", "correct": true, "explanation": "Existiert die Datei nicht, wird sie angelegt." },
|
||||
{ "id": "b", "text": "`<` liest die Standardeingabe aus einer Datei.", "correct": true, "explanation": "Beispiel: `sort < liste.txt`." },
|
||||
{ "id": "c", "text": "`2>&1` leitet die Standardausgabe auf die Fehlerausgabe um.", "correct": false, "explanation": "Umgekehrt: stderr (2) wird dorthin geleitet, wohin stdout (1) gerade zeigt." },
|
||||
{ "id": "d", "text": "`|` verbindet die Fehlerausgabe mit der Eingabe des nächsten Befehls.", "correct": false, "explanation": "Die Pipe verbindet stdout mit stdin; stderr nur mit `|&` bzw. `2>&1 |`." },
|
||||
{ "id": "e", "text": "`>` hängt an, wenn die Datei bereits existiert.", "correct": false, "explanation": "`>` überschreibt (kürzt die Datei auf 0); nur `>>` hängt an." }
|
||||
],
|
||||
"explanation": "Dateideskriptoren: 0 stdin, 1 stdout, 2 stderr. `set -o noclobber` verhindert versehentliches Überschreiben mit `>`.",
|
||||
"references": ["man 1 bash (Abschnitt REDIRECTION)"]
|
||||
},
|
||||
{
|
||||
"id": "103.4-006",
|
||||
"objective": "103.4",
|
||||
"type": "single",
|
||||
"difficulty": 1,
|
||||
"question": "Mit welcher Schreibweise setzt die Bash die **Ausgabe** eines Befehls in die Kommandozeile ein, z. B. in `echo \"Heute ist …\"`?",
|
||||
"options": [
|
||||
{ "id": "a", "text": "`$(date +%A)`", "correct": true, "explanation": "Befehlsersetzung: Die Ausgabe von `date +%A` ersetzt den Ausdruck." },
|
||||
{ "id": "b", "text": "`${date +%A}`", "correct": false, "explanation": "`${…}` ist Parameter-/Variablenersetzung und hier ein Syntaxfehler." },
|
||||
{ "id": "c", "text": "`$((date +%A))`", "correct": false, "explanation": "`$((…))` ist arithmetische Expansion." },
|
||||
{ "id": "d", "text": "`'date +%A'`", "correct": false, "explanation": "Einfache Anführungszeichen ergeben den Text wörtlich." },
|
||||
{ "id": "e", "text": "`<(date +%A)`", "correct": false, "explanation": "Prozessersetzung liefert einen Dateinamen (z. B. `/dev/fd/63`), nicht den Text." }
|
||||
],
|
||||
"explanation": "Ältere, gleichwertige Schreibweise mit Backticks (Gravis-Zeichen). `$(…)` ist besser lesbar und verschachtelbar.",
|
||||
"references": ["man 1 bash (Abschnitt Command Substitution)"]
|
||||
},
|
||||
{
|
||||
"id": "103.5-001",
|
||||
"objective": "103.5",
|
||||
"type": "single",
|
||||
"difficulty": 1,
|
||||
"question": "Welches Signal kann ein Prozess weder abfangen noch ignorieren?",
|
||||
"options": [
|
||||
{ "id": "a", "text": "SIGKILL (9)", "correct": true, "explanation": "SIGKILL beendet den Prozess unmittelbar durch den Kernel; es gibt keinen Handler." },
|
||||
{ "id": "b", "text": "SIGTERM (15)", "correct": false, "explanation": "SIGTERM ist die höfliche Aufforderung zum Beenden und kann abgefangen werden." },
|
||||
{ "id": "c", "text": "SIGHUP (1)", "correct": false, "explanation": "SIGHUP wird oft abgefangen, z. B. um Konfiguration neu zu laden." },
|
||||
{ "id": "d", "text": "SIGINT (2)", "correct": false, "explanation": "SIGINT (Strg+C) kann abgefangen werden." },
|
||||
{ "id": "e", "text": "SIGUSR1 (10)", "correct": false, "explanation": "Benutzerdefiniertes Signal, das Programme frei abfangen." }
|
||||
],
|
||||
"explanation": "Neben SIGKILL kann auch SIGSTOP nicht abgefangen werden. Liste aller Signale: `kill -l`.",
|
||||
"references": ["man 7 signal"]
|
||||
},
|
||||
{
|
||||
"id": "103.5-002",
|
||||
"objective": "103.5",
|
||||
"type": "fill",
|
||||
"difficulty": 1,
|
||||
"question": "Welches Signal sendet `kill <PID>`, wenn kein Signal angegeben wird? (Name oder Nummer)",
|
||||
"answers": ["SIGTERM", "TERM", "15"],
|
||||
"case_sensitive": false,
|
||||
"explanation": "Standard ist SIGTERM (15). Erst wenn ein Prozess darauf nicht reagiert, nimmt man SIGKILL (`kill -9`).",
|
||||
"references": ["man 1 kill"]
|
||||
},
|
||||
{
|
||||
"id": "103.5-003",
|
||||
"objective": "103.5",
|
||||
"type": "single",
|
||||
"difficulty": 1,
|
||||
"question": "Ein Skript soll weiterlaufen, nachdem sich der Benutzer abgemeldet hat. Welche Befehlszeile ist dafür gedacht?",
|
||||
"options": [
|
||||
{ "id": "a", "text": "`nohup ./skript.sh &`", "correct": true, "explanation": "`nohup` ignoriert SIGHUP und leitet die Ausgabe nach `nohup.out` um; `&` startet im Hintergrund." },
|
||||
{ "id": "b", "text": "`./skript.sh &`", "correct": false, "explanation": "Hintergrundjobs können beim Abmelden SIGHUP erhalten und beendet werden." },
|
||||
{ "id": "c", "text": "`bg ./skript.sh`", "correct": false, "explanation": "`bg` setzt einen gestoppten Job fort und erwartet eine Jobnummer, keinen Befehl." },
|
||||
{ "id": "d", "text": "`nice ./skript.sh`", "correct": false, "explanation": "`nice` ändert nur die Priorität." },
|
||||
{ "id": "e", "text": "`jobs ./skript.sh`", "correct": false, "explanation": "`jobs` listet Jobs der aktuellen Shell." }
|
||||
],
|
||||
"explanation": "Alternativen: `disown` für laufende Jobs, oder Terminal-Multiplexer wie `screen`/`tmux`, von denen man sich trennen und später wieder verbinden kann.",
|
||||
"references": ["man 1 nohup"]
|
||||
},
|
||||
{
|
||||
"id": "103.5-004",
|
||||
"objective": "103.5",
|
||||
"type": "single",
|
||||
"difficulty": 1,
|
||||
"question": "`jobs` zeigt drei Jobs. Wie holt man Job Nummer 2 in den Vordergrund?",
|
||||
"options": [
|
||||
{ "id": "a", "text": "`fg %2`", "correct": true, "explanation": "`fg` holt den angegebenen Job in den Vordergrund; `%2` ist die Jobspezifikation." },
|
||||
{ "id": "b", "text": "`bg %2`", "correct": false, "explanation": "`bg` setzt einen gestoppten Job im Hintergrund fort." },
|
||||
{ "id": "c", "text": "`jobs %2`", "correct": false, "explanation": "Zeigt nur den Status von Job 2." },
|
||||
{ "id": "d", "text": "`kill -CONT %2`", "correct": false, "explanation": "Setzt den Job fort, er bleibt aber im Hintergrund." },
|
||||
{ "id": "e", "text": "`wait %2`", "correct": false, "explanation": "`wait` wartet auf das Ende des Jobs, ohne ihn in den Vordergrund zu holen." }
|
||||
],
|
||||
"explanation": "Strg+Z stoppt den Vordergrundjob, `bg` lässt ihn im Hintergrund weiterlaufen, `fg` holt ihn zurück.",
|
||||
"references": ["help fg", "help jobs"]
|
||||
},
|
||||
{
|
||||
"id": "103.5-005",
|
||||
"objective": "103.5",
|
||||
"type": "multi",
|
||||
"difficulty": 2,
|
||||
"question": "Mit welchen Befehlen ermittelt man die Prozess-ID(s) laufender `sshd`-Prozesse anhand des Namens?",
|
||||
"options": [
|
||||
{ "id": "a", "text": "`pgrep sshd`", "correct": true, "explanation": "`pgrep` gibt die PIDs aller Prozesse aus, deren Name auf das Muster passt." },
|
||||
{ "id": "b", "text": "`pidof sshd`", "correct": true, "explanation": "`pidof` gibt die PIDs eines Programms mit genau diesem Namen aus." },
|
||||
{ "id": "c", "text": "`pkill sshd`", "correct": false, "explanation": "`pkill` sendet ein Signal (Standard SIGTERM) an die Prozesse – Vorsicht!" },
|
||||
{ "id": "d", "text": "`ps -p sshd`", "correct": false, "explanation": "`-p` erwartet eine PID-Liste, keinen Namen (richtig wäre `ps -C sshd`)." },
|
||||
{ "id": "e", "text": "`top -n sshd`", "correct": false, "explanation": "`-n` legt bei `top` die Anzahl der Durchläufe fest." }
|
||||
],
|
||||
"explanation": "Auch üblich: `ps aux | grep sshd`. `pgrep -a` zeigt zusätzlich die Befehlszeile, `pgrep -u` filtert nach Benutzer.",
|
||||
"references": ["man 1 pgrep", "man 8 pidof"]
|
||||
},
|
||||
{
|
||||
"id": "103.5-006",
|
||||
"objective": "103.5",
|
||||
"type": "single",
|
||||
"difficulty": 1,
|
||||
"question": "Welcher Befehl zeigt kompakt die Laufzeit des Systems, die Anzahl angemeldeter Benutzer und die Load Average der letzten 1, 5 und 15 Minuten?",
|
||||
"options": [
|
||||
{ "id": "a", "text": "`uptime`", "correct": true, "explanation": "`uptime` gibt genau diese Zeile aus (Werte aus `/proc/uptime` und `/proc/loadavg`)." },
|
||||
{ "id": "b", "text": "`free`", "correct": false, "explanation": "`free` zeigt Arbeitsspeicher und Swap." },
|
||||
{ "id": "c", "text": "`vmstat`", "correct": false, "explanation": "`vmstat` zeigt Prozess-, Speicher-, I/O- und CPU-Statistiken, aber keine Load Average." },
|
||||
{ "id": "d", "text": "`ps aux`", "correct": false, "explanation": "`ps aux` listet Prozesse." },
|
||||
{ "id": "e", "text": "`watch`", "correct": false, "explanation": "`watch` führt einen Befehl wiederholt aus und zeigt seine Ausgabe." }
|
||||
],
|
||||
"explanation": "Die Load Average ist die mittlere Zahl laufender bzw. auf CPU oder I/O wartender Prozesse. Sie steht auch in der ersten Zeile von `top` und `w`.",
|
||||
"references": ["man 1 uptime"]
|
||||
},
|
||||
{
|
||||
"id": "103.6-001",
|
||||
"objective": "103.6",
|
||||
"type": "single",
|
||||
"difficulty": 1,
|
||||
"question": "In welchem Bereich liegen Nice-Werte unter Linux, und welcher Wert bedeutet die **höchste** Priorität?",
|
||||
"options": [
|
||||
{ "id": "a", "text": "−20 bis 19; −20 ist die höchste Priorität", "correct": true, "explanation": "Je niedriger der Nice-Wert, desto „unfreundlicher“ ist der Prozess, also desto mehr CPU-Zeit bekommt er." },
|
||||
{ "id": "b", "text": "−20 bis 19; 19 ist die höchste Priorität", "correct": false, "explanation": "19 ist die niedrigste Priorität." },
|
||||
{ "id": "c", "text": "0 bis 39; 39 ist die höchste Priorität", "correct": false, "explanation": "Nice-Werte sind vorzeichenbehaftet und reichen von −20 bis 19." },
|
||||
{ "id": "d", "text": "1 bis 99; 99 ist die höchste Priorität", "correct": false, "explanation": "1–99 ist der Bereich der Echtzeitprioritäten, keine Nice-Werte." },
|
||||
{ "id": "e", "text": "−19 bis 20; 0 ist die höchste Priorität", "correct": false, "explanation": "Falscher Bereich; 0 ist der Standardwert." }
|
||||
],
|
||||
"explanation": "Standard ist 0. `nice` ohne `-n` startet mit +10. In `ps -l` erscheint der Wert in Spalte NI, in `top` als NI.",
|
||||
"references": ["man 1 nice"]
|
||||
},
|
||||
{
|
||||
"id": "103.6-002",
|
||||
"objective": "103.6",
|
||||
"type": "fill",
|
||||
"difficulty": 2,
|
||||
"question": "Geben Sie den Befehl ein, der den Nice-Wert des laufenden Prozesses mit der PID 1234 auf 10 setzt.",
|
||||
"answers": ["renice -n 10 -p 1234", "renice 10 1234", "renice -n 10 1234", "renice 10 -p 1234", "renice +10 1234", "renice +10 -p 1234", "renice -n +10 -p 1234"],
|
||||
"explanation": "`renice` ändert laufende Prozesse (`-p` PID, `-u` Benutzer, `-g` Prozessgruppe); `nice` gilt nur beim Starten.",
|
||||
"references": ["man 1 renice"]
|
||||
},
|
||||
{
|
||||
"id": "103.6-003",
|
||||
"objective": "103.6",
|
||||
"type": "multi",
|
||||
"difficulty": 2,
|
||||
"question": "Was darf ein **normaler Benutzer** (ohne besondere Limits) standardmäßig?",
|
||||
"options": [
|
||||
{ "id": "a", "text": "Ein Programm mit Nice-Wert 10 starten", "correct": true, "explanation": "Positive Nice-Werte (niedrigere Priorität) darf jeder setzen: `nice -n 10 programm`." },
|
||||
{ "id": "b", "text": "Den Nice-Wert eines eigenen laufenden Prozesses erhöhen", "correct": true, "explanation": "Die eigene Priorität senken ist erlaubt: `renice -n 15 -p <PID>`." },
|
||||
{ "id": "c", "text": "Ein Programm mit Nice-Wert −5 starten", "correct": false, "explanation": "Negative Nice-Werte erfordern root (bzw. CAP_SYS_NICE)." },
|
||||
{ "id": "d", "text": "Den Nice-Wert eines Prozesses eines anderen Benutzers ändern", "correct": false, "explanation": "Nur eigene Prozesse; fremde nur als root." },
|
||||
{ "id": "e", "text": "Den Nice-Wert eines eigenen Prozesses wieder unter den bisherigen Wert senken", "correct": false, "explanation": "Die Priorität wieder anheben darf standardmäßig nur root (Ausnahme: über `RLIMIT_NICE` erlaubte Bereiche)." }
|
||||
],
|
||||
"explanation": "Grundregel: Jeder darf seine Prozesse „netter“ machen, nur root darf Priorität erhöhen.",
|
||||
"references": ["man 1 renice", "man 2 setpriority"]
|
||||
},
|
||||
{
|
||||
"id": "103.7-001",
|
||||
"objective": "103.7",
|
||||
"type": "single",
|
||||
"difficulty": 1,
|
||||
"question": "Welche grep-Option gibt alle Zeilen aus, die **nicht** auf das Muster passen?",
|
||||
"options": [
|
||||
{ "id": "a", "text": "`-v`", "correct": true, "explanation": "`-v` (`--invert-match`) kehrt die Auswahl um." },
|
||||
{ "id": "b", "text": "`-i`", "correct": false, "explanation": "`-i` ignoriert Groß-/Kleinschreibung." },
|
||||
{ "id": "c", "text": "`-c`", "correct": false, "explanation": "`-c` gibt nur die Anzahl passender Zeilen aus." },
|
||||
{ "id": "d", "text": "`-l`", "correct": false, "explanation": "`-l` gibt nur die Namen der Dateien mit Treffern aus." },
|
||||
{ "id": "e", "text": "`-n`", "correct": false, "explanation": "`-n` stellt die Zeilennummer voran." }
|
||||
],
|
||||
"explanation": "Wichtige Optionen: `-E` erweiterte RE, `-F` feste Zeichenkette, `-r` rekursiv, `-w` ganzes Wort, `-o` nur den Treffer.",
|
||||
"references": ["man 1 grep"]
|
||||
},
|
||||
{
|
||||
"id": "103.7-002",
|
||||
"objective": "103.7",
|
||||
"type": "single",
|
||||
"difficulty": 2,
|
||||
"question": "Welcher Befehl gibt eine Konfigurationsdatei **ohne** Kommentarzeilen (beginnen mit `#`) und **ohne** Leerzeilen aus?",
|
||||
"options": [
|
||||
{ "id": "a", "text": "`grep -Ev '^(#|$)' datei`", "correct": true, "explanation": "Das Muster passt auf Zeilen, die mit `#` beginnen oder leer sind; `-v` kehrt um." },
|
||||
{ "id": "b", "text": "`grep -v '#' datei`", "correct": false, "explanation": "Entfernt auch Zeilen mit `#` in der Mitte und lässt Leerzeilen stehen." },
|
||||
{ "id": "c", "text": "`grep -E '^#|^$' datei`", "correct": false, "explanation": "Gibt nur Kommentar- und Leerzeilen aus." },
|
||||
{ "id": "d", "text": "`grep -v '^#$' datei`", "correct": false, "explanation": "Entfernt nur Zeilen, die ausschließlich aus `#` bestehen." },
|
||||
{ "id": "e", "text": "`grep -cv '^#' datei`", "correct": false, "explanation": "`-c` gibt nur eine Anzahl aus." }
|
||||
],
|
||||
"explanation": "Anker: `^` Zeilenanfang, `$` Zeilenende; `^$` ist eine leere Zeile. `|` (Alternative) und `( )` erfordern ERE (`-E`) oder in BRE `\\|` und `\\( \\)`.",
|
||||
"references": ["man 7 regex", "man 1 grep"]
|
||||
},
|
||||
{
|
||||
"id": "103.7-003",
|
||||
"objective": "103.7",
|
||||
"type": "fill",
|
||||
"difficulty": 2,
|
||||
"question": "Geben Sie den sed-Befehl ein, der in der Datei `datei` **jedes** Vorkommen von `foo` durch `bar` ersetzt und das Ergebnis auf stdout ausgibt.",
|
||||
"answers": ["sed 's/foo/bar/g' datei", "sed \"s/foo/bar/g\" datei", "sed s/foo/bar/g datei", "sed -e 's/foo/bar/g' datei", "sed -e \"s/foo/bar/g\" datei"],
|
||||
"explanation": "`s/alt/neu/` ersetzt das erste Vorkommen je Zeile, das Flag `g` alle. Mit `-i` wird die Datei selbst geändert.",
|
||||
"references": ["man 1 sed"]
|
||||
},
|
||||
{
|
||||
"id": "103.7-004",
|
||||
"objective": "103.7",
|
||||
"type": "multi",
|
||||
"difficulty": 2,
|
||||
"question": "Welche Aussagen zu regulären Ausdrücken (grep) treffen zu?",
|
||||
"options": [
|
||||
{ "id": "a", "text": "`.` passt auf genau ein beliebiges Zeichen.", "correct": true, "explanation": "Für einen wörtlichen Punkt: `\\.`." },
|
||||
{ "id": "b", "text": "`*` bedeutet: das vorherige Element null- oder mehrmals.", "correct": true, "explanation": "`a*` passt auch auf die leere Zeichenkette; anders als beim Shell-Globbing." },
|
||||
{ "id": "c", "text": "In Basic RE (grep ohne `-E`) bedeutet `+` „ein- oder mehrmals“.", "correct": false, "explanation": "In BRE ist `+` ein normales Zeichen; GNU grep versteht dort `\\+`. Mit `-E` ist `+` ein Quantor." },
|
||||
{ "id": "d", "text": "`$` verankert am Zeilenanfang.", "correct": false, "explanation": "`$` ist das Zeilenende, `^` der Zeilenanfang." },
|
||||
{ "id": "e", "text": "`[^a-z]` passt auf einen Kleinbuchstaben.", "correct": false, "explanation": "`^` am Anfang einer Klammer negiert: ein Zeichen, das **kein** Kleinbuchstabe ist." }
|
||||
],
|
||||
"explanation": "ERE-Zusätze: `+`, `?`, `{n,m}`, `|`, `( )`. Zeichenklassen: `[[:digit:]]`, `[[:space:]]`, `[[:alpha:]]`.",
|
||||
"references": ["man 7 regex"]
|
||||
},
|
||||
{
|
||||
"id": "103.8-001",
|
||||
"objective": "103.8",
|
||||
"type": "single",
|
||||
"difficulty": 1,
|
||||
"question": "Mit welcher Eingabe im Befehlsmodus von vi speichert man die Datei und beendet den Editor?",
|
||||
"options": [
|
||||
{ "id": "a", "text": "`:wq`", "correct": true, "explanation": "`:w` schreibt, `:q` beendet. Gleichwertig: `:x` und `ZZ`." },
|
||||
{ "id": "b", "text": "`:q!`", "correct": false, "explanation": "Beendet ohne zu speichern und verwirft Änderungen." },
|
||||
{ "id": "c", "text": "`:w`", "correct": false, "explanation": "Speichert nur, vi bleibt offen." },
|
||||
{ "id": "d", "text": "`ZQ`", "correct": false, "explanation": "`ZQ` entspricht `:q!`, also beenden ohne Speichern." },
|
||||
{ "id": "e", "text": "`:e!`", "correct": false, "explanation": "Lädt die Datei neu und verwirft ungespeicherte Änderungen." }
|
||||
],
|
||||
"explanation": "Mit Esc kommt man aus dem Einfügemodus in den Befehlsmodus. Doppelpunkt-Befehle sind Ex-Befehle.",
|
||||
"references": ["man 1 vim", ":help ZZ"]
|
||||
},
|
||||
{
|
||||
"id": "103.8-002",
|
||||
"objective": "103.8",
|
||||
"type": "fill",
|
||||
"difficulty": 1,
|
||||
"question": "Welche Tastenfolge löscht in vi im Befehlsmodus die **aktuelle Zeile** (und legt sie in den Puffer)?",
|
||||
"answers": ["dd"],
|
||||
"explanation": "`dd` löscht die Zeile, `5dd` fünf Zeilen, `yy` kopiert, `p` fügt ein, `u` macht rückgängig.",
|
||||
"references": [":help dd"]
|
||||
},
|
||||
{
|
||||
"id": "103.8-003",
|
||||
"objective": "103.8",
|
||||
"type": "single",
|
||||
"difficulty": 1,
|
||||
"question": "Wie sucht man in vi im Befehlsmodus **vorwärts** nach dem Wort `Port`?",
|
||||
"options": [
|
||||
{ "id": "a", "text": "`/Port`", "correct": true, "explanation": "`/` sucht vorwärts; `n` springt zum nächsten, `N` zum vorherigen Treffer." },
|
||||
{ "id": "b", "text": "`?Port`", "correct": false, "explanation": "`?` sucht rückwärts." },
|
||||
{ "id": "c", "text": "`:s/Port`", "correct": false, "explanation": "`:s` ist das Ersetzen in der aktuellen Zeile." },
|
||||
{ "id": "d", "text": "`fPort`", "correct": false, "explanation": "`f` springt zum nächsten Vorkommen eines einzelnen Zeichens in der aktuellen Zeile (hier `P`)." },
|
||||
{ "id": "e", "text": "`nPort`", "correct": false, "explanation": "`n` wiederholt die letzte Suche; die folgenden Zeichen würden als weitere Befehle gelesen." }
|
||||
],
|
||||
"explanation": "Suchen und ersetzen in der ganzen Datei: `:%s/alt/neu/g`.",
|
||||
"references": [":help /", ":help n"]
|
||||
},
|
||||
{
|
||||
"id": "103.8-004",
|
||||
"objective": "103.8",
|
||||
"type": "multi",
|
||||
"difficulty": 1,
|
||||
"question": "Welche Tasten wechseln in vi aus dem Befehlsmodus in den **Einfügemodus**?",
|
||||
"options": [
|
||||
{ "id": "a", "text": "`i`", "correct": true, "explanation": "Einfügen vor dem Cursor." },
|
||||
{ "id": "b", "text": "`o`", "correct": true, "explanation": "Öffnet eine neue Zeile unterhalb und wechselt in den Einfügemodus." },
|
||||
{ "id": "c", "text": "`x`", "correct": false, "explanation": "Löscht das Zeichen unter dem Cursor; man bleibt im Befehlsmodus." },
|
||||
{ "id": "d", "text": "`p`", "correct": false, "explanation": "Fügt den Pufferinhalt ein (paste); man bleibt im Befehlsmodus." },
|
||||
{ "id": "e", "text": "`u`", "correct": false, "explanation": "Macht die letzte Änderung rückgängig." }
|
||||
],
|
||||
"explanation": "Einfügemodus auch mit `a`/`A` (nach Cursor/Zeilenende), `I` (Zeilenanfang), `O` (neue Zeile oberhalb). Der Standard-Editor wird über `EDITOR`/`VISUAL` festgelegt.",
|
||||
"references": [":help insert"]
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,327 @@
|
||||
{
|
||||
"$schema": "../schema/questions.schema.json",
|
||||
"format": "lpic-sim-questions",
|
||||
"meta": {
|
||||
"file": "questions_104.json",
|
||||
"brief": "Fragen 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 (29.10.2026)"
|
||||
},
|
||||
"exam": "lpic1-101",
|
||||
"questions": [
|
||||
{
|
||||
"id": "104.1-001",
|
||||
"objective": "104.1",
|
||||
"type": "single",
|
||||
"difficulty": 1,
|
||||
"question": "Auf der ersten Partition der zweiten Festplatte (`/dev/sdb1`) soll ein ext4-Dateisystem angelegt werden. Welcher Befehl ist korrekt?",
|
||||
"options": [
|
||||
{ "id": "a", "text": "`mkfs.ext4 /dev/sdb1`", "correct": true, "explanation": "`mkfs.ext4` (gleichwertig `mkfs -t ext4` oder `mke2fs -t ext4`) legt das Dateisystem an." },
|
||||
{ "id": "b", "text": "`mkfs.ext4 /dev/sdb`", "correct": false, "explanation": "Das würde die ganze Platte ohne Partitionstabelle formatieren, nicht die erste Partition." },
|
||||
{ "id": "c", "text": "`mount -t ext4 /dev/sdb1`", "correct": false, "explanation": "`mount` hängt ein vorhandenes Dateisystem ein, es legt keines an." },
|
||||
{ "id": "d", "text": "`fdisk -t ext4 /dev/sdb1`", "correct": false, "explanation": "`fdisk` bearbeitet Partitionstabellen, legt aber keine Dateisysteme an." },
|
||||
{ "id": "e", "text": "`tune2fs -j /dev/sdb1`", "correct": false, "explanation": "`tune2fs -j` fügt einem bestehenden ext2 ein Journal hinzu." }
|
||||
],
|
||||
"explanation": "Reihenfolge: partitionieren (`fdisk`, `gdisk`, `parted`), Dateisystem anlegen (`mkfs.*`), einhängen (`mount`), dauerhaft in `/etc/fstab`.",
|
||||
"references": ["man 8 mkfs", "man 8 mke2fs"]
|
||||
},
|
||||
{
|
||||
"id": "104.1-002",
|
||||
"objective": "104.1",
|
||||
"type": "fill",
|
||||
"difficulty": 1,
|
||||
"question": "Die Partition `/dev/sdc2` soll als Swap-Bereich vorbereitet (initialisiert) werden. Geben Sie den vollständigen Befehl ein.",
|
||||
"answers": ["mkswap /dev/sdc2"],
|
||||
"explanation": "`mkswap` schreibt die Swap-Signatur; aktiviert wird mit `swapon /dev/sdc2`, dauerhaft über einen fstab-Eintrag vom Typ `swap`.",
|
||||
"references": ["man 8 mkswap", "man 8 swapon"]
|
||||
},
|
||||
{
|
||||
"id": "104.1-003",
|
||||
"objective": "104.1",
|
||||
"type": "multi",
|
||||
"difficulty": 2,
|
||||
"question": "Welche Werkzeuge können GPT-Partitionstabellen anlegen und bearbeiten?",
|
||||
"options": [
|
||||
{ "id": "a", "text": "`gdisk`", "correct": true, "explanation": "`gdisk` ist ein fdisk-ähnliches Werkzeug speziell für GPT." },
|
||||
{ "id": "b", "text": "`parted`", "correct": true, "explanation": "`parted` unterstützt MBR (msdos) und GPT und kann auch skriptgesteuert arbeiten." },
|
||||
{ "id": "c", "text": "`fdisk` (aktuelles util-linux)", "correct": true, "explanation": "Aktuelle `fdisk`-Versionen aus util-linux unterstützen GPT (Befehl `g` legt eine leere GPT an)." },
|
||||
{ "id": "d", "text": "`blkid`", "correct": false, "explanation": "`blkid` zeigt nur Attribute wie UUID, LABEL und TYPE an." },
|
||||
{ "id": "e", "text": "`mkswap`", "correct": false, "explanation": "`mkswap` initialisiert einen Swap-Bereich, partitioniert aber nicht." }
|
||||
],
|
||||
"explanation": "MBR: höchstens 4 primäre Partitionen (bzw. 3 primäre und eine erweiterte), max. 2 TiB. GPT: standardmäßig 128 Partitionen, sehr große Platten, Sicherungskopie der Tabelle am Plattenende.",
|
||||
"references": ["man 8 gdisk", "man 8 parted", "man 8 fdisk"]
|
||||
},
|
||||
{
|
||||
"id": "104.2-001",
|
||||
"objective": "104.2",
|
||||
"type": "single",
|
||||
"difficulty": 1,
|
||||
"question": "Was ist zu beachten, bevor man ein ext4-Dateisystem mit `fsck` prüft und repariert?",
|
||||
"options": [
|
||||
{ "id": "a", "text": "Das Dateisystem darf nicht (oder höchstens nur lesend) eingehängt sein.", "correct": true, "explanation": "Eine Reparatur an einem schreibend eingehängten Dateisystem kann es zerstören." },
|
||||
{ "id": "b", "text": "Das Dateisystem muss schreibend eingehängt sein.", "correct": false, "explanation": "Genau das sollte man vermeiden." },
|
||||
{ "id": "c", "text": "`fsck` funktioniert nur mit XFS.", "correct": false, "explanation": "`fsck` ist ein Frontend und ruft für ext4 `e2fsck` auf; für XFS ist es gerade nicht zuständig." },
|
||||
{ "id": "d", "text": "Vorher muss `mkfs` ausgeführt werden.", "correct": false, "explanation": "`mkfs` würde ein neues, leeres Dateisystem anlegen und alle Daten verlieren." },
|
||||
{ "id": "e", "text": "`fsck` darf nur auf Swap-Partitionen angewendet werden.", "correct": false, "explanation": "Swap enthält kein Dateisystem und wird nicht mit `fsck` geprüft." }
|
||||
],
|
||||
"explanation": "Die Root-Partition prüft man daher beim Start (sechstes Feld in `/etc/fstab`) oder aus einem Rettungssystem. `tune2fs` stellt die automatische Prüfung nach Anzahl Mounts/Zeit ein.",
|
||||
"references": ["man 8 fsck", "man 8 e2fsck"]
|
||||
},
|
||||
{
|
||||
"id": "104.2-002",
|
||||
"objective": "104.2",
|
||||
"type": "single",
|
||||
"difficulty": 2,
|
||||
"question": "Welches Werkzeug repariert ein beschädigtes **XFS**-Dateisystem?",
|
||||
"options": [
|
||||
{ "id": "a", "text": "`xfs_repair`", "correct": true, "explanation": "`xfs_repair` prüft und repariert XFS; mit `-n` nur prüfen, ohne zu ändern." },
|
||||
{ "id": "b", "text": "`xfs_fsr`", "correct": false, "explanation": "`xfs_fsr` defragmentiert ein eingehängtes XFS." },
|
||||
{ "id": "c", "text": "`fsck.xfs`", "correct": false, "explanation": "`fsck.xfs` tut absichtlich nichts und verweist auf `xfs_repair`; XFS prüft sich beim Mounten über das Journal." },
|
||||
{ "id": "d", "text": "`e2fsck`", "correct": false, "explanation": "`e2fsck` ist für ext2/3/4." },
|
||||
{ "id": "e", "text": "`xfs_info`", "correct": false, "explanation": "`xfs_info` zeigt nur die Geometrie eines XFS an." }
|
||||
],
|
||||
"explanation": "Weitere XFS-Werkzeuge: `xfs_db` (Debugger), `xfs_growfs` (vergrößern). ext-Werkzeuge: `e2fsck`, `tune2fs`, `dumpe2fs`, `debugfs`.",
|
||||
"references": ["man 8 xfs_repair"]
|
||||
},
|
||||
{
|
||||
"id": "104.2-003",
|
||||
"objective": "104.2",
|
||||
"type": "multi",
|
||||
"difficulty": 1,
|
||||
"question": "Welche Befehle helfen, den **Speicherplatz** auf Dateisystemen zu überwachen?",
|
||||
"options": [
|
||||
{ "id": "a", "text": "`df -h`", "correct": true, "explanation": "Belegter und freier Platz je eingehängtem Dateisystem; `df -i` zeigt die Inodes." },
|
||||
{ "id": "b", "text": "`du -sh /var/log`", "correct": true, "explanation": "Summe des belegten Platzes eines Verzeichnisbaums." },
|
||||
{ "id": "c", "text": "`free -h`", "correct": false, "explanation": "`free` zeigt Arbeitsspeicher und Swap, keinen Plattenplatz." },
|
||||
{ "id": "d", "text": "`blkid`", "correct": false, "explanation": "`blkid` zeigt UUID, Label und Typ, keine Belegung." },
|
||||
{ "id": "e", "text": "`mount`", "correct": false, "explanation": "`mount` ohne Argumente listet eingehängte Dateisysteme mit Optionen, ohne Belegung." }
|
||||
],
|
||||
"explanation": "Ein Dateisystem kann auch „voll“ sein, wenn noch Platz frei ist, aber keine Inodes mehr – dann hilft `df -i`.",
|
||||
"references": ["man 1 df", "man 1 du"]
|
||||
},
|
||||
{
|
||||
"id": "104.3-001",
|
||||
"objective": "104.3",
|
||||
"type": "single",
|
||||
"difficulty": 1,
|
||||
"question": "In welcher Reihenfolge stehen die sechs Felder eines Eintrags in `/etc/fstab`?",
|
||||
"options": [
|
||||
{ "id": "a", "text": "Gerät · Einhängepunkt · Dateisystemtyp · Optionen · dump · fsck-Reihenfolge", "correct": true, "explanation": "Beispiel: `UUID=… /home ext4 defaults 0 2`." },
|
||||
{ "id": "b", "text": "Einhängepunkt · Gerät · Dateisystemtyp · Optionen · dump · fsck-Reihenfolge", "correct": false, "explanation": "Das Gerät steht zuerst, danach der Einhängepunkt." },
|
||||
{ "id": "c", "text": "Gerät · Dateisystemtyp · Einhängepunkt · Optionen · dump · fsck-Reihenfolge", "correct": false, "explanation": "Der Einhängepunkt kommt vor dem Typ." },
|
||||
{ "id": "d", "text": "Gerät · Einhängepunkt · Optionen · Dateisystemtyp · fsck-Reihenfolge · dump", "correct": false, "explanation": "Typ vor Optionen; dump (5.) vor fsck-Reihenfolge (6.)." },
|
||||
{ "id": "e", "text": "Gerät · Einhängepunkt · Dateisystemtyp · Benutzer · Optionen · fsck-Reihenfolge", "correct": false, "explanation": "Ein Benutzerfeld gibt es nicht; `user`/`users` sind Optionen im vierten Feld." }
|
||||
],
|
||||
"explanation": "Sechstes Feld: 0 = nicht prüfen, 1 = Root-Dateisystem, 2 = andere Dateisysteme. systemd erzeugt aus fstab automatisch `.mount`-Units.",
|
||||
"references": ["man 5 fstab"]
|
||||
},
|
||||
{
|
||||
"id": "104.3-002",
|
||||
"objective": "104.3",
|
||||
"type": "fill",
|
||||
"difficulty": 1,
|
||||
"question": "Mit welchem Befehl (mit Option) hängt man alle in `/etc/fstab` eingetragenen Dateisysteme ein, die noch nicht eingehängt sind (außer denen mit `noauto`)?",
|
||||
"answers": ["mount -a", "mount --all"],
|
||||
"explanation": "`mount -a` eignet sich auch zum Testen eines neuen fstab-Eintrags vor dem nächsten Neustart.",
|
||||
"references": ["man 8 mount"]
|
||||
},
|
||||
{
|
||||
"id": "104.3-003",
|
||||
"objective": "104.3",
|
||||
"type": "single",
|
||||
"difficulty": 2,
|
||||
"question": "Welche Zeile ist ein gültiger `/etc/fstab`-Eintrag, der ein Dateisystem anhand seiner UUID nach `/data` einhängt?",
|
||||
"options": [
|
||||
{ "id": "a", "text": "`UUID=3f1c9a2e-77b0-4d6e-9c55-2b8e1d0a4f10 /data ext4 defaults 0 2`", "correct": true, "explanation": "Alle sechs Felder in der richtigen Reihenfolge; `UUID=` ist eine gültige Gerätekennung." },
|
||||
{ "id": "b", "text": "`/data UUID=3f1c9a2e-77b0-4d6e-9c55-2b8e1d0a4f10 ext4 defaults 0 2`", "correct": false, "explanation": "Gerät und Einhängepunkt sind vertauscht." },
|
||||
{ "id": "c", "text": "`UUID:3f1c9a2e-77b0-4d6e-9c55-2b8e1d0a4f10 /data ext4 defaults 0 2`", "correct": false, "explanation": "Die Schreibweise ist `UUID=` mit Gleichheitszeichen." },
|
||||
{ "id": "d", "text": "`UUID=3f1c9a2e-77b0-4d6e-9c55-2b8e1d0a4f10 /data defaults ext4 0 2`", "correct": false, "explanation": "Typ und Optionen sind vertauscht." },
|
||||
{ "id": "e", "text": "`/dev/disk/by-label/3f1c9a2e-77b0-4d6e-9c55-2b8e1d0a4f10 /data ext4 defaults 0 2`", "correct": false, "explanation": "`by-label` enthält Labels, keine UUIDs; der Pfad wäre `/dev/disk/by-uuid/…`." }
|
||||
],
|
||||
"explanation": "UUIDs und Labels sind stabil, Gerätenamen wie `/dev/sdb1` können sich beim Hinzufügen von Platten ändern. Auch `LABEL=…` ist erlaubt.",
|
||||
"references": ["man 5 fstab"]
|
||||
},
|
||||
{
|
||||
"id": "104.3-004",
|
||||
"objective": "104.3",
|
||||
"type": "multi",
|
||||
"difficulty": 1,
|
||||
"question": "Mit welchen Befehlen kann man die UUID des Dateisystems auf `/dev/sdb1` anzeigen?",
|
||||
"options": [
|
||||
{ "id": "a", "text": "`blkid /dev/sdb1`", "correct": true, "explanation": "`blkid` zeigt UUID, TYPE und ggf. LABEL." },
|
||||
{ "id": "b", "text": "`lsblk -f /dev/sdb1`", "correct": true, "explanation": "`-f` ergänzt die Spalten FSTYPE, LABEL und UUID." },
|
||||
{ "id": "c", "text": "`mount -U /dev/sdb1`", "correct": false, "explanation": "`mount -U <uuid>` hängt anhand einer UUID ein, zeigt aber keine an." },
|
||||
{ "id": "d", "text": "`df -u /dev/sdb1`", "correct": false, "explanation": "`df` hat keine Option zur UUID-Anzeige." },
|
||||
{ "id": "e", "text": "`swapon -s`", "correct": false, "explanation": "`swapon -s` listet aktive Swap-Bereiche." }
|
||||
],
|
||||
"explanation": "Die UUIDs stehen auch als Symlinks unter `/dev/disk/by-uuid/`.",
|
||||
"references": ["man 8 blkid", "man 8 lsblk"]
|
||||
},
|
||||
{
|
||||
"id": "104.5-001",
|
||||
"objective": "104.5",
|
||||
"type": "single",
|
||||
"difficulty": 1,
|
||||
"question": "Welche Rechte hat eine Datei nach `chmod 750 datei`?",
|
||||
"options": [
|
||||
{ "id": "a", "text": "`rwxr-x---`", "correct": true, "explanation": "7 = rwx (Eigentümer), 5 = r-x (Gruppe), 0 = --- (andere)." },
|
||||
{ "id": "b", "text": "`rwxrw----`", "correct": false, "explanation": "Das wäre 760." },
|
||||
{ "id": "c", "text": "`rw-r-x---`", "correct": false, "explanation": "Das wäre 650." },
|
||||
{ "id": "d", "text": "`rwxr-xr-x`", "correct": false, "explanation": "Das wäre 755." },
|
||||
{ "id": "e", "text": "`r-xrwx---`", "correct": false, "explanation": "Das wäre 570." }
|
||||
],
|
||||
"explanation": "Wertigkeit: r = 4, w = 2, x = 1, je Stelle für Eigentümer, Gruppe, andere addiert.",
|
||||
"references": ["man 1 chmod"]
|
||||
},
|
||||
{
|
||||
"id": "104.5-002",
|
||||
"objective": "104.5",
|
||||
"type": "fill",
|
||||
"difficulty": 1,
|
||||
"question": "Welcher oktale Modus (drei Ziffern) entspricht den Rechten `rw-r--r--`?",
|
||||
"answers": ["644", "0644"],
|
||||
"explanation": "rw- = 4+2 = 6, r-- = 4, r-- = 4. Typisch für normale Dateien; Verzeichnisse haben meist 755.",
|
||||
"references": ["man 1 chmod"]
|
||||
},
|
||||
{
|
||||
"id": "104.5-003",
|
||||
"objective": "104.5",
|
||||
"type": "single",
|
||||
"difficulty": 2,
|
||||
"question": "Welche Wirkung hat das SUID-Bit auf eine ausführbare Datei (z. B. `/usr/bin/passwd`)?",
|
||||
"options": [
|
||||
{ "id": "a", "text": "Das Programm läuft mit den Rechten des Datei-Eigentümers statt mit denen des Aufrufers.", "correct": true, "explanation": "Deshalb kann `passwd` (Eigentümer root) `/etc/shadow` ändern." },
|
||||
{ "id": "b", "text": "Neue Dateien im Verzeichnis erben die Gruppe des Verzeichnisses.", "correct": false, "explanation": "Das ist die Wirkung des SGID-Bits auf ein Verzeichnis." },
|
||||
{ "id": "c", "text": "Nur der Eigentümer darf Dateien im Verzeichnis löschen.", "correct": false, "explanation": "Das ist das Sticky-Bit auf Verzeichnissen, z. B. `/tmp`." },
|
||||
{ "id": "d", "text": "Die Datei kann nicht mehr geändert oder gelöscht werden.", "correct": false, "explanation": "Das beschreibt das immutable-Attribut (`chattr +i`)." },
|
||||
{ "id": "e", "text": "Das Programm darf nur von root ausgeführt werden.", "correct": false, "explanation": "Ausführen dürfen alle mit x-Recht; SUID ändert die effektive Benutzer-ID." }
|
||||
],
|
||||
"explanation": "Setzen: `chmod u+s datei` oder oktal 4xxx (SGID 2xxx, Sticky 1xxx). In `ls -l` erscheint `s` statt `x` beim Eigentümer.",
|
||||
"references": ["man 1 chmod", "man 7 credentials"]
|
||||
},
|
||||
{
|
||||
"id": "104.5-004",
|
||||
"objective": "104.5",
|
||||
"type": "single",
|
||||
"difficulty": 2,
|
||||
"question": "Die umask ist `027`. Welche Rechte erhält eine neu angelegte **reguläre Datei** (z. B. mit `touch`)?",
|
||||
"options": [
|
||||
{ "id": "a", "text": "`640` (`rw-r-----`)", "correct": true, "explanation": "Dateien starten mit 666; davon werden 027 maskiert → 640." },
|
||||
{ "id": "b", "text": "`750` (`rwxr-x---`)", "correct": false, "explanation": "Das erhält ein neues **Verzeichnis** (777 − 027)." },
|
||||
{ "id": "c", "text": "`027` (`----w-rwx`)", "correct": false, "explanation": "Die umask gibt an, was entfernt wird, nicht die Rechte selbst." },
|
||||
{ "id": "d", "text": "`751` (`rwxr-x--x`)", "correct": false, "explanation": "Das passt weder zu Dateien noch zu Verzeichnissen mit dieser umask." },
|
||||
{ "id": "e", "text": "`600` (`rw-------`)", "correct": false, "explanation": "Das ergäbe die umask 077." }
|
||||
],
|
||||
"explanation": "Programme erzeugen Dateien üblicherweise mit 666 und Verzeichnisse mit 777; die umask entfernt Bits. Anzeigen/Setzen mit `umask`, symbolisch mit `umask -S`.",
|
||||
"references": ["help umask"]
|
||||
},
|
||||
{
|
||||
"id": "104.5-005",
|
||||
"objective": "104.5",
|
||||
"type": "multi",
|
||||
"difficulty": 1,
|
||||
"question": "Mit welchen Befehlen ändert man die **Gruppe** der Datei `bericht.txt` auf `team`?",
|
||||
"options": [
|
||||
{ "id": "a", "text": "`chgrp team bericht.txt`", "correct": true, "explanation": "`chgrp` ändert nur die Gruppe." },
|
||||
{ "id": "b", "text": "`chown :team bericht.txt`", "correct": true, "explanation": "Bei `chown` ändert die Form `:gruppe` nur die Gruppe (auch `.gruppe` wird noch akzeptiert)." },
|
||||
{ "id": "c", "text": "`chmod g=team bericht.txt`", "correct": false, "explanation": "`chmod g=` setzt Rechte der Gruppe; `team` ist keine gültige Rechteangabe." },
|
||||
{ "id": "d", "text": "`newgrp team bericht.txt`", "correct": false, "explanation": "`newgrp` startet eine Shell mit anderer primärer Gruppe; es ändert keine Datei." },
|
||||
{ "id": "e", "text": "`usermod -g team bericht.txt`", "correct": false, "explanation": "`usermod -g` ändert die primäre Gruppe eines Benutzers." }
|
||||
],
|
||||
"explanation": "`chown benutzer:gruppe datei` ändert beides; `-R` arbeitet rekursiv. Normale Benutzer dürfen nur auf Gruppen wechseln, in denen sie Mitglied sind.",
|
||||
"references": ["man 1 chgrp", "man 1 chown"]
|
||||
},
|
||||
{
|
||||
"id": "104.6-001",
|
||||
"objective": "104.6",
|
||||
"type": "single",
|
||||
"difficulty": 1,
|
||||
"question": "Es soll ein symbolischer Link `aktuell` angelegt werden, der auf `release-2.4` zeigt. Welcher Befehl ist korrekt?",
|
||||
"options": [
|
||||
{ "id": "a", "text": "`ln -s release-2.4 aktuell`", "correct": true, "explanation": "Reihenfolge wie bei `cp`: erst Ziel (Original), dann der Name des Links." },
|
||||
{ "id": "b", "text": "`ln -s aktuell release-2.4`", "correct": false, "explanation": "Vertauscht: Das legt `release-2.4` als Link auf `aktuell` an (bzw. scheitert, wenn es existiert)." },
|
||||
{ "id": "c", "text": "`ln release-2.4 aktuell`", "correct": false, "explanation": "Ohne `-s` entsteht ein Hardlink; für Verzeichnisse ist das nicht erlaubt." },
|
||||
{ "id": "d", "text": "`link -s release-2.4 aktuell`", "correct": false, "explanation": "`link` legt nur Hardlinks an und kennt kein `-s`." },
|
||||
{ "id": "e", "text": "`mklink aktuell release-2.4`", "correct": false, "explanation": "`mklink` ist ein Windows-Befehl." }
|
||||
],
|
||||
"explanation": "Ein bestehenden Link umsetzen: `ln -sfn neues-ziel aktuell`.",
|
||||
"references": ["man 1 ln"]
|
||||
},
|
||||
{
|
||||
"id": "104.6-002",
|
||||
"objective": "104.6",
|
||||
"type": "multi",
|
||||
"difficulty": 2,
|
||||
"question": "Welche Aussagen über **Hardlinks** treffen zu?",
|
||||
"options": [
|
||||
{ "id": "a", "text": "Alle Hardlinks einer Datei verweisen auf denselben Inode.", "correct": true, "explanation": "Ein Hardlink ist nur ein weiterer Verzeichniseintrag für denselben Inode." },
|
||||
{ "id": "b", "text": "Hardlinks können nicht über Dateisystemgrenzen hinweg angelegt werden.", "correct": true, "explanation": "Inode-Nummern sind nur innerhalb eines Dateisystems eindeutig." },
|
||||
{ "id": "c", "text": "Normale Benutzer können Hardlinks auf Verzeichnisse anlegen.", "correct": false, "explanation": "Hardlinks auf Verzeichnisse sind nicht erlaubt (Schleifen im Baum)." },
|
||||
{ "id": "d", "text": "Wird die ursprüngliche Datei gelöscht, ist der Hardlink defekt.", "correct": false, "explanation": "Die Daten bleiben, bis der Linkzähler 0 erreicht; defekt werden nur Symlinks." },
|
||||
{ "id": "e", "text": "Ein Hardlink hat eigene, vom Original unabhängige Zugriffsrechte.", "correct": false, "explanation": "Rechte stehen im Inode und gelten für alle Namen gemeinsam." }
|
||||
],
|
||||
"explanation": "Der Linkzähler steht in `ls -l` in der zweiten Spalte. Symlinks haben einen eigenen Inode und enthalten den Pfad zum Ziel.",
|
||||
"references": ["man 1 ln", "man 7 inode"]
|
||||
},
|
||||
{
|
||||
"id": "104.6-003",
|
||||
"objective": "104.6",
|
||||
"type": "fill",
|
||||
"difficulty": 1,
|
||||
"question": "Welcher Befehl mit Option zeigt beim Auflisten eines Verzeichnisses die **Inode-Nummern** der Dateien an?",
|
||||
"answers": ["ls -i", "ls --inode", "ls -li", "ls -il"],
|
||||
"explanation": "Gleiche Inode-Nummer = Hardlinks derselben Datei. Alternativ zeigt `stat datei` den Inode einer einzelnen Datei.",
|
||||
"references": ["man 1 ls"]
|
||||
},
|
||||
{
|
||||
"id": "104.7-001",
|
||||
"objective": "104.7",
|
||||
"type": "single",
|
||||
"difficulty": 1,
|
||||
"question": "Wo gehören laut Filesystem Hierarchy Standard (FHS) die Protokolldateien des Systems hin?",
|
||||
"options": [
|
||||
{ "id": "a", "text": "`/var/log`", "correct": true, "explanation": "`/var` enthält variable Daten; `/var/log` die Protokolle." },
|
||||
{ "id": "b", "text": "`/usr/log`", "correct": false, "explanation": "`/usr` ist für weitgehend statische, teilbare Daten gedacht und kann nur lesend eingehängt sein." },
|
||||
{ "id": "c", "text": "`/etc/log`", "correct": false, "explanation": "`/etc` ist für hostspezifische Konfiguration gedacht." },
|
||||
{ "id": "d", "text": "`/opt/log`", "correct": false, "explanation": "`/opt` ist für zusätzliche Softwarepakete gedacht; variable Daten solcher Pakete gehören nach `/var/opt`." },
|
||||
{ "id": "e", "text": "`/srv/log`", "correct": false, "explanation": "`/srv` enthält Daten, die das System als Dienst ausliefert (z. B. Web, FTP)." }
|
||||
],
|
||||
"explanation": "Weitere FHS-Orte: `/var/spool` (Warteschlangen), `/var/cache`, `/var/lib` (Zustandsdaten), `/tmp` (temporär), `/usr/local` (lokal installierte Software).",
|
||||
"references": ["man 7 hier", "https://refspecs.linuxfoundation.org/fhs.shtml"]
|
||||
},
|
||||
{
|
||||
"id": "104.7-002",
|
||||
"objective": "104.7",
|
||||
"type": "single",
|
||||
"difficulty": 1,
|
||||
"question": "`locate` findet eine soeben angelegte Datei nicht. Was ist zu tun?",
|
||||
"options": [
|
||||
{ "id": "a", "text": "Die Datenbank mit `updatedb` aktualisieren", "correct": true, "explanation": "`locate` durchsucht eine Datenbank, die meist täglich per Cron/Timer mit `updatedb` erneuert wird." },
|
||||
{ "id": "b", "text": "`hash -r` ausführen", "correct": false, "explanation": "`hash -r` leert die Tabelle der Programmpfade der Shell." },
|
||||
{ "id": "c", "text": "`ldconfig` ausführen", "correct": false, "explanation": "`ldconfig` aktualisiert den Cache der Shared Libraries." },
|
||||
{ "id": "d", "text": "`mandb` ausführen", "correct": false, "explanation": "`mandb` aktualisiert den Index der Manpages." },
|
||||
{ "id": "e", "text": "`whereis -u` ausführen", "correct": false, "explanation": "`whereis -u` sucht nach „ungewöhnlichen“ Einträgen; mit der locate-Datenbank hat es nichts zu tun." }
|
||||
],
|
||||
"explanation": "Welche Pfade `updatedb` auslässt, steht in `/etc/updatedb.conf` (z. B. `PRUNEPATHS`, `PRUNEFS`). `find` durchsucht dagegen live das Dateisystem.",
|
||||
"references": ["man 8 updatedb", "man 5 updatedb.conf"]
|
||||
},
|
||||
{
|
||||
"id": "104.7-003",
|
||||
"objective": "104.7",
|
||||
"type": "multi",
|
||||
"difficulty": 1,
|
||||
"question": "Mit welchen Befehlen findet man heraus, wo das **Programm** `ls` im Dateisystem liegt?",
|
||||
"options": [
|
||||
{ "id": "a", "text": "`which ls`", "correct": true, "explanation": "`which` durchsucht den `PATH` und gibt den ersten Treffer aus." },
|
||||
{ "id": "b", "text": "`whereis ls`", "correct": true, "explanation": "`whereis` zeigt Programm, Quellen und Manpages zu einem Befehl." },
|
||||
{ "id": "c", "text": "`whatis ls`", "correct": false, "explanation": "`whatis` zeigt die Kurzbeschreibung aus der Manpage." },
|
||||
{ "id": "d", "text": "`file ls`", "correct": false, "explanation": "`file` bestimmt den Typ einer Datei; `ls` würde im aktuellen Verzeichnis gesucht." },
|
||||
{ "id": "e", "text": "`stat ls`", "correct": false, "explanation": "`stat` zeigt Inode-Daten einer Datei `ls` im aktuellen Verzeichnis." }
|
||||
],
|
||||
"explanation": "Für Shell-Aliase und Builtins hilft `type`; für beliebige Dateien `find` (live) oder `locate` (Datenbank).",
|
||||
"references": ["man 1 which", "man 1 whereis"]
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
{
|
||||
"meta": {
|
||||
"file": "exam.json",
|
||||
"brief": "Prüfungsdefinition LPIC-1 102-500: Eckdaten, Topics, Objectives mit Gewichtung",
|
||||
"author": "Björn Runden <br@runden.de>",
|
||||
"owner": "Björn Runden <br@runden.de>",
|
||||
"assist": "KI-unterstützt (Claude Opus 5.5), geprüft von Björn Runden <br@runden.de>",
|
||||
"version": "0.1.0 (29.10.2026)"
|
||||
},
|
||||
"exam": {
|
||||
"id": "lpic1-102",
|
||||
"level": "LPIC-1",
|
||||
"title": "LPIC-1 Prüfung 102",
|
||||
"code": "102-500",
|
||||
"lang": "de",
|
||||
"order": 102,
|
||||
"objectives_version": "5.0",
|
||||
"objectives_source": "https://www.lpi.org/de/exam-101-102-objectives/",
|
||||
"objectives_retrieved": "2026-10-29",
|
||||
"questions": 60,
|
||||
"duration_min": 90,
|
||||
"pass_percent": 65
|
||||
},
|
||||
"topics": [
|
||||
{
|
||||
"id": "105",
|
||||
"title": "Shells und Shell-Skripte",
|
||||
"objectives": [
|
||||
{ "id": "105.1", "title": "Die Shell-Umgebung anpassen und verwenden", "weight": 4 },
|
||||
{ "id": "105.2", "title": "Einfache Skripte anpassen oder schreiben", "weight": 4 }
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "106",
|
||||
"title": "Benutzerschnittstellen und Desktops",
|
||||
"objectives": [
|
||||
{ "id": "106.1", "title": "X11 installieren und konfigurieren", "weight": 2 },
|
||||
{ "id": "106.2", "title": "Grafische Desktops", "weight": 1 },
|
||||
{ "id": "106.3", "title": "Barrierefreiheit", "weight": 1 }
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "107",
|
||||
"title": "Administrative Aufgaben",
|
||||
"objectives": [
|
||||
{ "id": "107.1", "title": "Benutzer- und Gruppenkonten und dazugehörige Systemdateien verwalten", "weight": 5 },
|
||||
{ "id": "107.2", "title": "Systemadministrationsaufgaben durch Einplanen von Jobs automatisieren", "weight": 4 },
|
||||
{ "id": "107.3", "title": "Lokalisierung und Internationalisierung", "weight": 3 }
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "108",
|
||||
"title": "Grundlegende Systemdienste",
|
||||
"objectives": [
|
||||
{ "id": "108.1", "title": "Die Systemzeit verwalten", "weight": 3 },
|
||||
{ "id": "108.2", "title": "Systemprotokollierung", "weight": 4 },
|
||||
{ "id": "108.3", "title": "Grundlagen von Mail Transfer Agents (MTA)", "weight": 3 },
|
||||
{ "id": "108.4", "title": "Drucker und Druckvorgänge verwalten", "weight": 2 }
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "109",
|
||||
"title": "Netzwerkgrundlagen",
|
||||
"objectives": [
|
||||
{ "id": "109.1", "title": "Grundlagen von Internetprotokollen", "weight": 4 },
|
||||
{ "id": "109.2", "title": "Persistente Netzwerkkonfiguration", "weight": 4 },
|
||||
{ "id": "109.3", "title": "Grundlegende Netzwerkfehlerbehebung", "weight": 4 },
|
||||
{ "id": "109.4", "title": "Clientseitiges DNS konfigurieren", "weight": 2 }
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "110",
|
||||
"title": "Sicherheit",
|
||||
"objectives": [
|
||||
{ "id": "110.1", "title": "Administrationsaufgaben für Sicherheit durchführen", "weight": 3 },
|
||||
{ "id": "110.2", "title": "Einen Rechner absichern", "weight": 3 },
|
||||
{ "id": "110.3", "title": "Daten durch Verschlüsselung schützen", "weight": 4 }
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,195 @@
|
||||
{
|
||||
"$schema": "../schema/questions.schema.json",
|
||||
"format": "lpic-sim-questions",
|
||||
"meta": {
|
||||
"file": "questions_105.json",
|
||||
"brief": "Fragen 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 (29.10.2026)"
|
||||
},
|
||||
"exam": "lpic1-102",
|
||||
"questions": [
|
||||
{
|
||||
"id": "105.1-001",
|
||||
"objective": "105.1",
|
||||
"type": "single",
|
||||
"difficulty": 2,
|
||||
"question": "Welche Datei liest eine interaktive **Login**-Bash als erste ein?",
|
||||
"options": [
|
||||
{ "id": "a", "text": "`/etc/profile`", "correct": true, "explanation": "Login-Shells lesen zuerst die systemweite `/etc/profile`, danach die erste vorhandene aus `~/.bash_profile`, `~/.bash_login`, `~/.profile`." },
|
||||
{ "id": "b", "text": "`~/.bashrc`", "correct": false, "explanation": "`~/.bashrc` lesen interaktive Nicht-Login-Shells; Login-Shells nur, wenn `~/.bash_profile` sie einbindet." },
|
||||
{ "id": "c", "text": "`~/.bash_profile`", "correct": false, "explanation": "Wird gelesen, aber erst nach `/etc/profile`." },
|
||||
{ "id": "d", "text": "`/etc/bash.bashrc`", "correct": false, "explanation": "Systemweite Datei für interaktive Nicht-Login-Shells (Debian); wird oft über `/etc/profile` eingebunden." },
|
||||
{ "id": "e", "text": "`~/.bash_logout`", "correct": false, "explanation": "Wird beim Beenden einer Login-Shell ausgeführt." }
|
||||
],
|
||||
"explanation": "Login-Shell: `/etc/profile` → `~/.bash_profile` | `~/.bash_login` | `~/.profile`. Nicht-Login-Shell: `/etc/bash.bashrc` (distributionsabhängig) → `~/.bashrc`.",
|
||||
"references": ["man 1 bash (Abschnitt INVOCATION)"]
|
||||
},
|
||||
{
|
||||
"id": "105.1-002",
|
||||
"objective": "105.1",
|
||||
"type": "multi",
|
||||
"difficulty": 1,
|
||||
"question": "Welche Schreibweisen definieren in der Bash korrekt eine Funktion `gruss`?",
|
||||
"options": [
|
||||
{ "id": "a", "text": "`gruss() { echo Hallo; }`", "correct": true, "explanation": "POSIX-Schreibweise; vor der schließenden Klammer ist `;` oder ein Zeilenumbruch nötig." },
|
||||
{ "id": "b", "text": "`function gruss { echo Hallo; }`", "correct": true, "explanation": "Bash-spezifische Schreibweise mit dem Schlüsselwort `function`." },
|
||||
{ "id": "c", "text": "`def gruss(): echo Hallo`", "correct": false, "explanation": "Das ist Python-ähnliche Syntax." },
|
||||
{ "id": "d", "text": "`gruss = { echo Hallo }`", "correct": false, "explanation": "Leerzeichen um `=` und diese Klammerung sind keine gültige Funktionssyntax." },
|
||||
{ "id": "e", "text": "`alias gruss() echo Hallo`", "correct": false, "explanation": "Aliase werden mit `alias name='befehl'` gesetzt und haben keine Klammern." }
|
||||
],
|
||||
"explanation": "Funktionen sehen Argumente als `$1`, `$2`, …; `declare -f` listet definierte Funktionen. Dauerhaft z. B. in `~/.bashrc`.",
|
||||
"references": ["man 1 bash (Abschnitt FUNCTIONS)"]
|
||||
},
|
||||
{
|
||||
"id": "105.1-003",
|
||||
"objective": "105.1",
|
||||
"type": "fill",
|
||||
"difficulty": 2,
|
||||
"question": "Welches Bash-Builtin führt die Befehle einer Datei in der **aktuellen** Shell aus, sodass dort gesetzte Variablen danach erhalten bleiben? (Name des Builtins)",
|
||||
"answers": ["source", "."],
|
||||
"explanation": "`source ~/.bashrc` bzw. `. ~/.bashrc`. Ein Aufruf als `./datei` oder `bash datei` läuft dagegen in einer Subshell; deren Variablen gehen verloren.",
|
||||
"references": ["help source"]
|
||||
},
|
||||
{
|
||||
"id": "105.1-004",
|
||||
"objective": "105.1",
|
||||
"type": "single",
|
||||
"difficulty": 1,
|
||||
"question": "Der Alias `ll='ls -l'` soll für einen Benutzer dauerhaft in jeder interaktiven Bash verfügbar sein. Wo trägt man ihn ein?",
|
||||
"options": [
|
||||
{ "id": "a", "text": "`~/.bashrc`", "correct": true, "explanation": "`~/.bashrc` wird von jeder interaktiven Nicht-Login-Bash gelesen und meist auch aus `~/.bash_profile` eingebunden." },
|
||||
{ "id": "b", "text": "`/etc/aliases`", "correct": false, "explanation": "`/etc/aliases` enthält E-Mail-Aliase für den MTA, keine Shell-Aliase." },
|
||||
{ "id": "c", "text": "`~/.bash_logout`", "correct": false, "explanation": "Wird nur beim Abmelden ausgeführt." },
|
||||
{ "id": "d", "text": "`/etc/shells`", "correct": false, "explanation": "`/etc/shells` listet die zulässigen Login-Shells." },
|
||||
{ "id": "e", "text": "`~/.bash_history`", "correct": false, "explanation": "Enthält nur die gespeicherte Befehls-History." }
|
||||
],
|
||||
"explanation": "Ein Alias in der Shell gilt nur bis zum Ende der Sitzung; dauerhaft wird er durch einen Eintrag in einer Startdatei.",
|
||||
"references": ["help alias"]
|
||||
},
|
||||
{
|
||||
"id": "105.1-005",
|
||||
"objective": "105.1",
|
||||
"type": "single",
|
||||
"difficulty": 1,
|
||||
"question": "Das Verzeichnis `/opt/tools/bin` soll **zusätzlich** zum bisherigen Suchpfad verwendet werden. Welcher Befehl ist korrekt?",
|
||||
"options": [
|
||||
{ "id": "a", "text": "`export PATH=$PATH:/opt/tools/bin`", "correct": true, "explanation": "Der alte Inhalt bleibt erhalten, das neue Verzeichnis wird mit `:` angehängt." },
|
||||
{ "id": "b", "text": "`export PATH=/opt/tools/bin`", "correct": false, "explanation": "Ersetzt den Suchpfad; Standardbefehle wie `ls` werden nicht mehr gefunden." },
|
||||
{ "id": "c", "text": "`export PATH=$PATH;/opt/tools/bin`", "correct": false, "explanation": "`;` trennt Befehle; die Shell würde `/opt/tools/bin` als Befehl ausführen." },
|
||||
{ "id": "d", "text": "`export $PATH=$PATH:/opt/tools/bin`", "correct": false, "explanation": "Links vom `=` steht der Variablenname ohne `$`." },
|
||||
{ "id": "e", "text": "`set PATH /opt/tools/bin`", "correct": false, "explanation": "Das ist csh-Syntax; in der Bash setzt `set` Positionsparameter." }
|
||||
],
|
||||
"explanation": "Verzeichnisse im `PATH` werden von links nach rechts durchsucht; `$PATH` voranzustellen oder anzuhängen bestimmt die Priorität.",
|
||||
"references": ["man 1 bash (Abschnitt Shell Variables)"]
|
||||
},
|
||||
{
|
||||
"id": "105.1-006",
|
||||
"objective": "105.1",
|
||||
"type": "single",
|
||||
"difficulty": 1,
|
||||
"question": "Welches Verzeichnis enthält die Vorlagen (z. B. `.bashrc`, `.profile`), die beim Anlegen eines Benutzers mit `useradd -m` in dessen Home-Verzeichnis kopiert werden?",
|
||||
"options": [
|
||||
{ "id": "a", "text": "`/etc/skel`", "correct": true, "explanation": "Der Inhalt von `/etc/skel` wird in neue Home-Verzeichnisse kopiert." },
|
||||
{ "id": "b", "text": "`/etc/default/useradd`", "correct": false, "explanation": "Datei mit Standardwerten für `useradd` (u. a. `SKEL=`), kein Vorlagenverzeichnis." },
|
||||
{ "id": "c", "text": "`/etc/profile.d`", "correct": false, "explanation": "Enthält Skripte, die `/etc/profile` beim Login einbindet." },
|
||||
{ "id": "d", "text": "`/etc/login.defs`", "correct": false, "explanation": "Datei mit Vorgaben wie UID-Bereichen und Passwort-Alterung." },
|
||||
{ "id": "e", "text": "`/home/template`", "correct": false, "explanation": "Kein Standardpfad." }
|
||||
],
|
||||
"explanation": "Änderungen an `/etc/skel` wirken nur für künftig angelegte Benutzer.",
|
||||
"references": ["man 8 useradd"]
|
||||
},
|
||||
{
|
||||
"id": "105.2-001",
|
||||
"objective": "105.2",
|
||||
"type": "single",
|
||||
"difficulty": 1,
|
||||
"question": "Welche Variable enthält in einem Shell-Skript die **Anzahl** der übergebenen Argumente?",
|
||||
"options": [
|
||||
{ "id": "a", "text": "`$#`", "correct": true, "explanation": "`$#` ist die Anzahl der Positionsparameter." },
|
||||
{ "id": "b", "text": "`$0`", "correct": false, "explanation": "`$0` ist der Name des Skripts." },
|
||||
{ "id": "c", "text": "`$@`", "correct": false, "explanation": "`$@` sind alle Argumente als einzelne Wörter." },
|
||||
{ "id": "d", "text": "`$?`", "correct": false, "explanation": "`$?` ist der Exit-Status des letzten Befehls." },
|
||||
{ "id": "e", "text": "`$$`", "correct": false, "explanation": "`$$` ist die PID der Shell." }
|
||||
],
|
||||
"explanation": "Weitere: `$1`…`$9` Argumente, `${10}` ab dem zehnten, `$*` alle als ein Wort (in Anführungszeichen), `shift` verschiebt die Argumente.",
|
||||
"references": ["man 1 bash (Abschnitt Special Parameters)"]
|
||||
},
|
||||
{
|
||||
"id": "105.2-002",
|
||||
"objective": "105.2",
|
||||
"type": "single",
|
||||
"difficulty": 1,
|
||||
"question": "Mit welcher Bedingung prüft ein Skript, ob `/etc/app.conf` existiert **und eine reguläre Datei** ist?",
|
||||
"options": [
|
||||
{ "id": "a", "text": "`[ -f /etc/app.conf ]`", "correct": true, "explanation": "`-f` ist wahr für existierende reguläre Dateien." },
|
||||
{ "id": "b", "text": "`[ -d /etc/app.conf ]`", "correct": false, "explanation": "`-d` prüft auf ein Verzeichnis." },
|
||||
{ "id": "c", "text": "`[ -e /etc/app.conf ]`", "correct": false, "explanation": "`-e` prüft nur auf Existenz, gleich welcher Typ (auch Verzeichnis)." },
|
||||
{ "id": "d", "text": "`[ -x /etc/app.conf ]`", "correct": false, "explanation": "`-x` prüft auf Ausführbarkeit." },
|
||||
{ "id": "e", "text": "`[ -L /etc/app.conf ]`", "correct": false, "explanation": "`-L` prüft auf einen symbolischen Link." }
|
||||
],
|
||||
"explanation": "`[ … ]` ist der Befehl `test`; Leerzeichen innerhalb der Klammern sind Pflicht. Weitere Tests: `-s` nicht leer, `-r`/`-w` lesbar/schreibbar, `-z`/`-n` leerer/nicht leerer String.",
|
||||
"references": ["man 1 test"]
|
||||
},
|
||||
{
|
||||
"id": "105.2-003",
|
||||
"objective": "105.2",
|
||||
"type": "fill",
|
||||
"difficulty": 1,
|
||||
"question": "Welche spezielle Variable enthält den Exit-Status (Rückgabewert) des zuletzt ausgeführten Befehls?",
|
||||
"answers": ["$?"],
|
||||
"explanation": "0 bedeutet Erfolg, alles andere einen Fehler. Darauf bauen `&&`, `||` und `if` auf.",
|
||||
"references": ["man 1 bash (Abschnitt Special Parameters)"]
|
||||
},
|
||||
{
|
||||
"id": "105.2-004",
|
||||
"objective": "105.2",
|
||||
"type": "single",
|
||||
"difficulty": 1,
|
||||
"question": "Welche Schleife ist in der Bash syntaktisch korrekt?",
|
||||
"options": [
|
||||
{ "id": "a", "text": "`for i in 1 2 3; do echo $i; done`", "correct": true, "explanation": "Aufbau: `for <var> in <liste>; do … done`." },
|
||||
{ "id": "b", "text": "`for i in 1 2 3; then echo $i; fi`", "correct": false, "explanation": "`then`/`fi` gehören zu `if`." },
|
||||
{ "id": "c", "text": "`for (i in 1 2 3) { echo $i }`", "correct": false, "explanation": "C/JavaScript-ähnliche Syntax; die Bash kennt das nicht." },
|
||||
{ "id": "d", "text": "`foreach i (1 2 3) echo $i end`", "correct": false, "explanation": "`foreach … end` ist csh-Syntax." },
|
||||
{ "id": "e", "text": "`for i = 1 to 3; do echo $i; done`", "correct": false, "explanation": "BASIC-ähnlich; nicht gültig. Zahlenreihen: `$(seq 1 3)` oder `{1..3}`." }
|
||||
],
|
||||
"explanation": "Weitere Schleifen: `while bedingung; do … done`, `until …`. C-Stil in der Bash: `for ((i=1; i<=3; i++)); do … done`.",
|
||||
"references": ["man 1 bash (Abschnitt Compound Commands)"]
|
||||
},
|
||||
{
|
||||
"id": "105.2-005",
|
||||
"objective": "105.2",
|
||||
"type": "multi",
|
||||
"difficulty": 2,
|
||||
"question": "Welche Aussagen zum Ausführen von Shell-Skripten treffen zu?",
|
||||
"options": [
|
||||
{ "id": "a", "text": "Die erste Zeile `#!/bin/bash` legt den Interpreter fest, wenn das Skript direkt ausgeführt wird.", "correct": true, "explanation": "Der Kernel wertet die Shebang-Zeile aus und startet den angegebenen Interpreter." },
|
||||
{ "id": "b", "text": "Für den Aufruf `./skript.sh` braucht die Datei das Ausführungsrecht.", "correct": true, "explanation": "Ohne `x`-Recht meldet die Shell „Permission denied“." },
|
||||
{ "id": "c", "text": "Auch `bash skript.sh` funktioniert nur mit Ausführungsrecht.", "correct": false, "explanation": "Hier ist `bash` das ausgeführte Programm; es braucht nur Leserecht auf das Skript." },
|
||||
{ "id": "d", "text": "Die Shebang-Zeile darf an beliebiger Stelle im Skript stehen.", "correct": false, "explanation": "Sie wirkt nur als allererste Zeile und muss mit `#!` beginnen." },
|
||||
{ "id": "e", "text": "Das aktuelle Verzeichnis ist standardmäßig im `PATH`; `skript.sh` ohne `./` genügt.", "correct": false, "explanation": "Aus Sicherheitsgründen steht `.` normalerweise nicht im `PATH`." }
|
||||
],
|
||||
"explanation": "SUID/SGID-Bits werden bei Skripten unter Linux ignoriert. Mit `exec` ersetzt ein Skript sich selbst durch ein anderes Programm.",
|
||||
"references": ["man 2 execve"]
|
||||
},
|
||||
{
|
||||
"id": "105.2-006",
|
||||
"objective": "105.2",
|
||||
"type": "single",
|
||||
"difficulty": 1,
|
||||
"question": "Welcher Befehl liest in einem Skript eine Zeile von der Tastatur in die Variable `NAME` ein?",
|
||||
"options": [
|
||||
{ "id": "a", "text": "`read NAME`", "correct": true, "explanation": "`read` liest eine Zeile von stdin; `-p \"Text\"` zeigt vorher eine Eingabeaufforderung an." },
|
||||
{ "id": "b", "text": "`input NAME`", "correct": false, "explanation": "Einen Befehl `input` gibt es in der Bash nicht." },
|
||||
{ "id": "c", "text": "`echo $NAME`", "correct": false, "explanation": "Gibt den Inhalt der Variable aus, liest nichts ein." },
|
||||
{ "id": "d", "text": "`NAME < /dev/stdin`", "correct": false, "explanation": "Die Shell versucht, einen Befehl namens `NAME` auszuführen; eine Variable wird nicht gesetzt." },
|
||||
{ "id": "e", "text": "`get NAME`", "correct": false, "explanation": "Einen Befehl `get` gibt es in der Bash nicht." }
|
||||
],
|
||||
"explanation": "Mehrere Variablen: `read VORNAME NACHNAME` verteilt die Wörter nach `IFS`. Ohne Variablenname landet die Eingabe in `REPLY`.",
|
||||
"references": ["help read"]
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,127 @@
|
||||
{
|
||||
"$schema": "../schema/questions.schema.json",
|
||||
"format": "lpic-sim-questions",
|
||||
"meta": {
|
||||
"file": "questions_106.json",
|
||||
"brief": "Fragen 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 (29.10.2026)"
|
||||
},
|
||||
"exam": "lpic1-102",
|
||||
"questions": [
|
||||
{
|
||||
"id": "106.1-001",
|
||||
"objective": "106.1",
|
||||
"type": "single",
|
||||
"difficulty": 1,
|
||||
"question": "Welche Umgebungsvariable legt fest, auf welchem X-Server ein X11-Programm seine Fenster darstellt?",
|
||||
"options": [
|
||||
{ "id": "a", "text": "`DISPLAY`", "correct": true, "explanation": "Format `host:display.screen`, lokal meist `:0`." },
|
||||
{ "id": "b", "text": "`XAUTHORITY`", "correct": false, "explanation": "Verweist auf die Datei mit den Zugriffs-Cookies (Standard `~/.Xauthority`)." },
|
||||
{ "id": "c", "text": "`TERM`", "correct": false, "explanation": "Beschreibt den Typ des Text-Terminals." },
|
||||
{ "id": "d", "text": "`XDG_SESSION_TYPE`", "correct": false, "explanation": "Zeigt nur an, ob die Sitzung `x11` oder `wayland` ist." },
|
||||
{ "id": "e", "text": "`WAYLAND_DISPLAY`", "correct": false, "explanation": "Gibt den Socket des Wayland-Compositors an, nicht den X-Server." }
|
||||
],
|
||||
"explanation": "Zugriff auf einen X-Server steuern `xhost` (host-basiert) und `xauth` (Cookies). X-Weiterleitung über SSH: `ssh -X`.",
|
||||
"references": ["man 7 X"]
|
||||
},
|
||||
{
|
||||
"id": "106.1-002",
|
||||
"objective": "106.1",
|
||||
"type": "single",
|
||||
"difficulty": 1,
|
||||
"question": "Wo liegt die Hauptkonfiguration des Xorg-Servers bzw. wo legt man ergänzende Konfigurationsschnipsel ab?",
|
||||
"options": [
|
||||
{ "id": "a", "text": "`/etc/X11/xorg.conf` bzw. `/etc/X11/xorg.conf.d/`", "correct": true, "explanation": "Moderne Xorg-Server erkennen vieles automatisch; Anpassungen kommen als Dateien in `xorg.conf.d`." },
|
||||
{ "id": "b", "text": "`/etc/xorg/server.conf`", "correct": false, "explanation": "Diesen Pfad gibt es nicht." },
|
||||
{ "id": "c", "text": "`~/.xinitrc`", "correct": false, "explanation": "`~/.xinitrc` legt fest, was `startx` startet, nicht die Server-Hardwarekonfiguration." },
|
||||
{ "id": "d", "text": "`/etc/X11/Xresources`", "correct": false, "explanation": "X-Ressourcen konfigurieren das Aussehen von Clients, nicht den Server." },
|
||||
{ "id": "e", "text": "`/var/log/Xorg.0.log`", "correct": false, "explanation": "Das ist das Protokoll des Servers, hilfreich bei Fehlern, aber keine Konfiguration." }
|
||||
],
|
||||
"explanation": "Abschnitte in `xorg.conf`: `Section \"Device\"`, `\"Monitor\"`, `\"Screen\"`, `\"InputDevice\"`, `\"ServerLayout\"` … Fehlersuche über `/var/log/Xorg.0.log`.",
|
||||
"references": ["man 5 xorg.conf"]
|
||||
},
|
||||
{
|
||||
"id": "106.1-003",
|
||||
"objective": "106.1",
|
||||
"type": "multi",
|
||||
"difficulty": 2,
|
||||
"question": "Welche Aussagen zu Wayland treffen zu?",
|
||||
"options": [
|
||||
{ "id": "a", "text": "Unter Wayland übernimmt der Compositor zugleich die Aufgaben des Display-Servers.", "correct": true, "explanation": "Es gibt keinen getrennten Server wie Xorg; der Compositor (z. B. Mutter, KWin) zeichnet und verteilt Eingaben." },
|
||||
{ "id": "b", "text": "XWayland ermöglicht es, X11-Programme in einer Wayland-Sitzung auszuführen.", "correct": true, "explanation": "XWayland ist ein X-Server, der als Wayland-Client läuft." },
|
||||
{ "id": "c", "text": "Wayland wird über `/etc/X11/xorg.conf` konfiguriert.", "correct": false, "explanation": "Die Konfiguration erfolgt im jeweiligen Compositor bzw. der Desktopumgebung." },
|
||||
{ "id": "d", "text": "Wayland ist wie X11 netzwerktransparent über `DISPLAY=host:0`.", "correct": false, "explanation": "Das Wayland-Protokoll selbst ist nicht netzwerktransparent; Fernzugriff läuft über Zusatzlösungen." },
|
||||
{ "id": "e", "text": "Wayland setzt den Display-Manager `xdm` voraus.", "correct": false, "explanation": "Wayland-Sitzungen werden z. B. von GDM oder SDDM gestartet; `xdm` kann das nicht." }
|
||||
],
|
||||
"explanation": "Ob eine Sitzung X11 oder Wayland nutzt, zeigt `echo $XDG_SESSION_TYPE`.",
|
||||
"references": ["https://wayland.freedesktop.org/"]
|
||||
},
|
||||
{
|
||||
"id": "106.2-001",
|
||||
"objective": "106.2",
|
||||
"type": "single",
|
||||
"difficulty": 1,
|
||||
"question": "Welches Fernzugriffsverfahren für grafische Desktops basiert auf dem Remote-Framebuffer-Protokoll (RFB)?",
|
||||
"options": [
|
||||
{ "id": "a", "text": "VNC", "correct": true, "explanation": "VNC (Virtual Network Computing) überträgt Bildschirminhalte per RFB, Standardport 5900 + Display-Nummer." },
|
||||
{ "id": "b", "text": "RDP", "correct": false, "explanation": "RDP ist das Remote Desktop Protocol von Microsoft (Port 3389), unter Linux z. B. mit xrdp." },
|
||||
{ "id": "c", "text": "SPICE", "correct": false, "explanation": "SPICE ist ein eigenes Protokoll für die Anzeige virtueller Maschinen (QEMU/KVM)." },
|
||||
{ "id": "d", "text": "XDMCP", "correct": false, "explanation": "XDMCP vermittelt Anmeldungen an einen entfernten X-Display-Manager, unverschlüsselt." },
|
||||
{ "id": "e", "text": "SMTP", "correct": false, "explanation": "SMTP überträgt E-Mails." }
|
||||
],
|
||||
"explanation": "106.2 verlangt Grundwissen zu Desktopumgebungen und Protokollen für den entfernten Desktopzugriff (X11, XDMCP, VNC, SPICE, RDP).",
|
||||
"references": ["RFC 6143"]
|
||||
},
|
||||
{
|
||||
"id": "106.2-002",
|
||||
"objective": "106.2",
|
||||
"type": "multi",
|
||||
"difficulty": 1,
|
||||
"question": "Welche der folgenden sind **Desktopumgebungen**?",
|
||||
"options": [
|
||||
{ "id": "a", "text": "GNOME", "correct": true, "explanation": "Verbreitete Desktopumgebung (GTK-basiert)." },
|
||||
{ "id": "b", "text": "KDE Plasma", "correct": true, "explanation": "Desktopumgebung auf Qt-Basis." },
|
||||
{ "id": "c", "text": "Xfce", "correct": true, "explanation": "Ressourcenschonende Desktopumgebung (GTK-basiert)." },
|
||||
{ "id": "d", "text": "Xorg", "correct": false, "explanation": "Xorg ist der X-Display-Server, auf dem Desktopumgebungen laufen können." },
|
||||
{ "id": "e", "text": "systemd", "correct": false, "explanation": "systemd ist Init-System und Dienstverwaltung." }
|
||||
],
|
||||
"explanation": "Weitere Desktops: Cinnamon, MATE, LXDE/LXQt. Eine Desktopumgebung bündelt Fenstermanager, Panel, Dateimanager und Einstellungen.",
|
||||
"references": ["LPI 102-500 Objective 106.2"]
|
||||
},
|
||||
{
|
||||
"id": "106.3-001",
|
||||
"objective": "106.3",
|
||||
"type": "single",
|
||||
"difficulty": 1,
|
||||
"question": "Welches Programm ist ein verbreiteter **Bildschirmleser** (Screenreader) für grafische Linux-Desktops wie GNOME?",
|
||||
"options": [
|
||||
{ "id": "a", "text": "Orca", "correct": true, "explanation": "Orca gibt Bildschirminhalte per Sprachausgabe oder Braillezeile aus." },
|
||||
{ "id": "b", "text": "Onboard", "correct": false, "explanation": "Onboard ist eine Bildschirmtastatur." },
|
||||
{ "id": "c", "text": "xmag", "correct": false, "explanation": "`xmag` vergrößert einen Bildschirmausschnitt." },
|
||||
{ "id": "d", "text": "Sticky Keys", "correct": false, "explanation": "Eine Tastatureinstellung, kein Bildschirmleser." },
|
||||
{ "id": "e", "text": "`xrandr`", "correct": false, "explanation": "`xrandr` stellt Auflösung und Anordnung von Monitoren ein." }
|
||||
],
|
||||
"explanation": "Hilfstechnologien: Bildschirmleser, Braillezeilen, Bildschirmlupe, Bildschirmtastatur, Hochkontrast-Themes, große Schriften, Sprachsynthese.",
|
||||
"references": ["https://help.gnome.org/users/orca/stable/"]
|
||||
},
|
||||
{
|
||||
"id": "106.3-002",
|
||||
"objective": "106.3",
|
||||
"type": "single",
|
||||
"difficulty": 1,
|
||||
"question": "Was bewirken **einrastende Tasten** (Sticky Keys)?",
|
||||
"options": [
|
||||
{ "id": "a", "text": "Umschalt-, Strg- oder Alt-Taste bleiben nach dem Loslassen aktiv, sodass Tastenkombinationen nacheinander gedrückt werden können.", "correct": true, "explanation": "Hilft Menschen, die nicht mehrere Tasten gleichzeitig drücken können." },
|
||||
{ "id": "b", "text": "Eine Taste muss eine Weile gehalten werden, bevor der Anschlag zählt.", "correct": false, "explanation": "Das sind die Langsamen Tasten (Slow Keys)." },
|
||||
{ "id": "c", "text": "Schnell wiederholte Anschläge derselben Taste werden ignoriert.", "correct": false, "explanation": "Das sind die Springenden Tasten (Bounce Keys)." },
|
||||
{ "id": "d", "text": "Der Mauszeiger wird mit dem Ziffernblock gesteuert.", "correct": false, "explanation": "Das sind die Maustasten (Mouse Keys)." },
|
||||
{ "id": "e", "text": "Der Bildschirm wird in hohem Kontrast dargestellt.", "correct": false, "explanation": "Das ist ein Hochkontrast-Theme." }
|
||||
],
|
||||
"explanation": "AccessX-Funktionen der Tastatur: Sticky, Slow, Bounce, Toggle Keys sowie Mouse Keys.",
|
||||
"references": ["LPI 102-500 Objective 106.3"]
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,285 @@
|
||||
{
|
||||
"$schema": "../schema/questions.schema.json",
|
||||
"format": "lpic-sim-questions",
|
||||
"meta": {
|
||||
"file": "questions_107.json",
|
||||
"brief": "Fragen 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 (29.10.2026)"
|
||||
},
|
||||
"exam": "lpic1-102",
|
||||
"questions": [
|
||||
{
|
||||
"id": "107.1-001",
|
||||
"objective": "107.1",
|
||||
"type": "single",
|
||||
"difficulty": 1,
|
||||
"question": "In welcher Datei stehen auf aktuellen Linux-Systemen die Passwort-Hashes der Benutzerkonten?",
|
||||
"options": [
|
||||
{ "id": "a", "text": "`/etc/shadow`", "correct": true, "explanation": "Nur für root lesbar; enthält Hash und Daten zur Passwort-Alterung." },
|
||||
{ "id": "b", "text": "`/etc/passwd`", "correct": false, "explanation": "Für alle lesbar; im Passwortfeld steht nur `x` als Verweis auf `/etc/shadow`." },
|
||||
{ "id": "c", "text": "`/etc/group`", "correct": false, "explanation": "Enthält Gruppen und ihre Mitglieder." },
|
||||
{ "id": "d", "text": "`/etc/gshadow`", "correct": false, "explanation": "Enthält Gruppenpasswörter und Gruppenadministratoren." },
|
||||
{ "id": "e", "text": "`/etc/login.defs`", "correct": false, "explanation": "Enthält Vorgaben, z. B. UID-Bereiche und Standardwerte der Passwort-Alterung." }
|
||||
],
|
||||
"explanation": "Felder von `/etc/shadow`: Name, Hash, letzte Änderung, min, max, Warnung, Inaktivität, Ablaufdatum, reserviert.",
|
||||
"references": ["man 5 shadow"]
|
||||
},
|
||||
{
|
||||
"id": "107.1-002",
|
||||
"objective": "107.1",
|
||||
"type": "single",
|
||||
"difficulty": 1,
|
||||
"question": "Was steht im **siebten** (letzten) Feld eines Eintrags in `/etc/passwd`?",
|
||||
"options": [
|
||||
{ "id": "a", "text": "Die Login-Shell", "correct": true, "explanation": "z. B. `/bin/bash` oder `/usr/sbin/nologin` für Konten ohne Anmeldung." },
|
||||
{ "id": "b", "text": "Das Home-Verzeichnis", "correct": false, "explanation": "Das ist das sechste Feld." },
|
||||
{ "id": "c", "text": "Das GECOS-Feld (Kommentar, voller Name)", "correct": false, "explanation": "Das ist das fünfte Feld." },
|
||||
{ "id": "d", "text": "Die primäre Gruppen-ID", "correct": false, "explanation": "Das ist das vierte Feld." },
|
||||
{ "id": "e", "text": "Die Benutzer-ID", "correct": false, "explanation": "Das ist das dritte Feld." }
|
||||
],
|
||||
"explanation": "Aufbau: `name:x:UID:GID:GECOS:home:shell`, z. B. `anna:x:1001:1001:Anna:/home/anna:/bin/bash`.",
|
||||
"references": ["man 5 passwd"]
|
||||
},
|
||||
{
|
||||
"id": "107.1-003",
|
||||
"objective": "107.1",
|
||||
"type": "fill",
|
||||
"difficulty": 2,
|
||||
"question": "Der Benutzer `anna` soll zusätzlich in die Gruppe `docker` aufgenommen werden, **ohne** seine übrigen Zusatzgruppen zu verlieren. Geben Sie den Befehl ein.",
|
||||
"answers": ["usermod -aG docker anna", "usermod -a -G docker anna", "usermod -G docker -a anna", "usermod --append --groups docker anna", "gpasswd -a anna docker"],
|
||||
"explanation": "`-G` allein ersetzt die Liste der Zusatzgruppen; erst `-a` (append) hängt an. Die Änderung wirkt erst nach erneuter Anmeldung (oder mit `newgrp`).",
|
||||
"references": ["man 8 usermod", "man 1 gpasswd"]
|
||||
},
|
||||
{
|
||||
"id": "107.1-004",
|
||||
"objective": "107.1",
|
||||
"type": "single",
|
||||
"difficulty": 1,
|
||||
"question": "Mit welchem Befehl legt man den Benutzer `bob` an und erzeugt dabei gleich sein Home-Verzeichnis (mit Inhalt aus `/etc/skel`)?",
|
||||
"options": [
|
||||
{ "id": "a", "text": "`useradd -m bob`", "correct": true, "explanation": "`-m` (`--create-home`) legt das Home-Verzeichnis an und kopiert `/etc/skel`." },
|
||||
{ "id": "b", "text": "`useradd -d /home/bob bob`", "correct": false, "explanation": "`-d` legt nur den Pfad fest, erzeugt das Verzeichnis aber nicht." },
|
||||
{ "id": "c", "text": "`useradd -s /bin/bash bob`", "correct": false, "explanation": "`-s` setzt nur die Login-Shell." },
|
||||
{ "id": "d", "text": "`useradd -g users bob`", "correct": false, "explanation": "`-g` setzt die primäre Gruppe." },
|
||||
{ "id": "e", "text": "`useradd -k /etc/skel bob`", "correct": false, "explanation": "`-k` wählt das Vorlagenverzeichnis und wirkt nur zusammen mit `-m`." }
|
||||
],
|
||||
"explanation": "Ob `useradd` ohne `-m` ein Home anlegt, hängt von `CREATE_HOME` in `/etc/login.defs` ab. Debian bietet zusätzlich das interaktive `adduser`.",
|
||||
"references": ["man 8 useradd"]
|
||||
},
|
||||
{
|
||||
"id": "107.1-005",
|
||||
"objective": "107.1",
|
||||
"type": "multi",
|
||||
"difficulty": 2,
|
||||
"question": "Mit welchen Befehlen sperrt man das Passwort des Kontos `carl`, sodass keine Anmeldung per Passwort mehr möglich ist?",
|
||||
"options": [
|
||||
{ "id": "a", "text": "`usermod -L carl`", "correct": true, "explanation": "`-L` setzt ein `!` vor den Hash in `/etc/shadow`." },
|
||||
{ "id": "b", "text": "`passwd -l carl`", "correct": true, "explanation": "`passwd -l` sperrt ebenfalls durch Voranstellen von `!`; `-u` entsperrt." },
|
||||
{ "id": "c", "text": "`passwd -d carl`", "correct": false, "explanation": "`-d` löscht das Passwort – je nach Konfiguration ist dann sogar eine Anmeldung ohne Passwort möglich." },
|
||||
{ "id": "d", "text": "`chage -l carl`", "correct": false, "explanation": "`chage -l` zeigt nur die Alterungsinformationen an." },
|
||||
{ "id": "e", "text": "`userdel -l carl`", "correct": false, "explanation": "`userdel` löscht Konten; eine Option `-l` zum Sperren gibt es nicht." }
|
||||
],
|
||||
"explanation": "Eine Passwortsperre verhindert keine Anmeldung per SSH-Schlüssel. Komplett sperren: zusätzlich Ablaufdatum setzen (`usermod -e 1` bzw. `chage -E 0`) oder Shell auf `nologin`.",
|
||||
"references": ["man 8 usermod", "man 1 passwd"]
|
||||
},
|
||||
{
|
||||
"id": "107.1-006",
|
||||
"objective": "107.1",
|
||||
"type": "single",
|
||||
"difficulty": 2,
|
||||
"question": "Der Benutzer `dora` soll sein Passwort spätestens alle 90 Tage ändern müssen. Welcher Befehl setzt das?",
|
||||
"options": [
|
||||
{ "id": "a", "text": "`chage -M 90 dora`", "correct": true, "explanation": "`-M` setzt die maximale Gültigkeit des Passworts in Tagen." },
|
||||
{ "id": "b", "text": "`chage -m 90 dora`", "correct": false, "explanation": "`-m` ist die Mindestdauer zwischen zwei Änderungen." },
|
||||
{ "id": "c", "text": "`chage -W 90 dora`", "correct": false, "explanation": "`-W` legt fest, wie viele Tage vorher gewarnt wird." },
|
||||
{ "id": "d", "text": "`chage -E 90 dora`", "correct": false, "explanation": "`-E` setzt das Ablaufdatum des Kontos (Datum oder Tage seit 1.1.1970)." },
|
||||
{ "id": "e", "text": "`chage -I 90 dora`", "correct": false, "explanation": "`-I` legt die Inaktivitätsfrist nach Ablauf des Passworts fest." }
|
||||
],
|
||||
"explanation": "`chage -l dora` zeigt die aktuellen Werte. Dieselben Felder lassen sich teils auch mit `passwd -n/-x/-w/-i` setzen.",
|
||||
"references": ["man 1 chage"]
|
||||
},
|
||||
{
|
||||
"id": "107.1-007",
|
||||
"objective": "107.1",
|
||||
"type": "single",
|
||||
"difficulty": 2,
|
||||
"question": "Benutzer kommen teils aus `/etc/passwd`, teils aus LDAP. Welcher Befehl zeigt den Kontoeintrag von `anna` **unabhängig von der Quelle** an?",
|
||||
"options": [
|
||||
{ "id": "a", "text": "`getent passwd anna`", "correct": true, "explanation": "`getent` fragt die Datenbanken über NSS ab, also in der Reihenfolge aus `/etc/nsswitch.conf`." },
|
||||
{ "id": "b", "text": "`grep anna /etc/passwd`", "correct": false, "explanation": "Findet nur lokale Einträge." },
|
||||
{ "id": "c", "text": "`who anna`", "correct": false, "explanation": "`who` zeigt angemeldete Benutzer; ein Argument wird als Datei interpretiert." },
|
||||
{ "id": "d", "text": "`last anna`", "correct": false, "explanation": "`last` zeigt die Anmeldehistorie aus `wtmp`." },
|
||||
{ "id": "e", "text": "`cat /etc/nsswitch.conf`", "correct": false, "explanation": "Zeigt nur die Konfiguration der Quellen, keine Konten." }
|
||||
],
|
||||
"explanation": "Analog: `getent group`, `getent hosts`, `getent shadow` (als root).",
|
||||
"references": ["man 1 getent", "man 5 nsswitch.conf"]
|
||||
},
|
||||
{
|
||||
"id": "107.1-008",
|
||||
"objective": "107.1",
|
||||
"type": "multi",
|
||||
"difficulty": 2,
|
||||
"question": "Welche Aussagen zur Benutzer- und Gruppenverwaltung treffen zu?",
|
||||
"options": [
|
||||
{ "id": "a", "text": "`userdel -r anna` löscht auch das Home-Verzeichnis und das Mail-Spool von `anna`.", "correct": true, "explanation": "Ohne `-r` bleiben Home-Verzeichnis und Mail-Spool erhalten." },
|
||||
{ "id": "b", "text": "Systemkonten haben üblicherweise UIDs unterhalb von `UID_MIN` aus `/etc/login.defs`.", "correct": true, "explanation": "Typisch: Systemkonten unter 1000, normale Benutzer ab 1000; `useradd -r` legt Systemkonten an." },
|
||||
{ "id": "c", "text": "`groupdel` löscht eine Gruppe auch dann, wenn sie die primäre Gruppe eines Benutzers ist.", "correct": false, "explanation": "`groupdel` verweigert das; zuerst muss die primäre Gruppe des Benutzers geändert werden." },
|
||||
{ "id": "d", "text": "Die UID 0 kann nur ein Konto mit dem Namen `root` haben.", "correct": false, "explanation": "Entscheidend ist die UID: Jedes Konto mit UID 0 hat Root-Rechte – ein Sicherheitsrisiko." },
|
||||
{ "id": "e", "text": "`passwd` ohne Argument ändert immer das Passwort von root.", "correct": false, "explanation": "Ohne Argument ändert `passwd` das Passwort des aufrufenden Benutzers." }
|
||||
],
|
||||
"explanation": "Gruppen: `groupadd`, `groupmod -n neu alt` (umbenennen), `groupdel`. Mitgliedschaften prüfen: `id anna`, `groups anna`.",
|
||||
"references": ["man 8 userdel", "man 5 login.defs"]
|
||||
},
|
||||
{
|
||||
"id": "107.2-001",
|
||||
"objective": "107.2",
|
||||
"type": "single",
|
||||
"difficulty": 1,
|
||||
"question": "Wann läuft der Benutzer-crontab-Eintrag `30 2 * * 1 /usr/local/bin/backup.sh`?",
|
||||
"options": [
|
||||
{ "id": "a", "text": "Jeden Montag um 02:30 Uhr", "correct": true, "explanation": "Minute 30, Stunde 2, jeder Tag, jeder Monat, Wochentag 1 = Montag." },
|
||||
{ "id": "b", "text": "Jeden Tag um 02:30 Uhr", "correct": false, "explanation": "Das wäre `30 2 * * *`." },
|
||||
{ "id": "c", "text": "Am 1. jedes Monats um 02:30 Uhr", "correct": false, "explanation": "Das wäre `30 2 1 * *` (drittes Feld = Tag des Monats)." },
|
||||
{ "id": "d", "text": "Im Januar täglich um 02:30 Uhr", "correct": false, "explanation": "Das wäre `30 2 * 1 *` (viertes Feld = Monat)." },
|
||||
{ "id": "e", "text": "Montags alle 30 Minuten ab 02:00 Uhr", "correct": false, "explanation": "Das wäre z. B. `*/30 2-23 * * 1`." }
|
||||
],
|
||||
"explanation": "Felder: Minute · Stunde · Tag des Monats · Monat · Wochentag (0 und 7 = Sonntag) · Befehl.",
|
||||
"references": ["man 5 crontab"]
|
||||
},
|
||||
{
|
||||
"id": "107.2-002",
|
||||
"objective": "107.2",
|
||||
"type": "fill",
|
||||
"difficulty": 1,
|
||||
"question": "Mit welchem Befehl (mit Option) bearbeitet ein Benutzer seine eigene crontab?",
|
||||
"answers": ["crontab -e"],
|
||||
"explanation": "`crontab -e` öffnet den Editor und prüft beim Speichern die Syntax; `-l` listet, `-r` löscht. Die Dateien liegen unter `/var/spool/cron/`.",
|
||||
"references": ["man 1 crontab"]
|
||||
},
|
||||
{
|
||||
"id": "107.2-003",
|
||||
"objective": "107.2",
|
||||
"type": "single",
|
||||
"difficulty": 2,
|
||||
"question": "Worin unterscheidet sich ein Eintrag in `/etc/crontab` (bzw. `/etc/cron.d/*`) von einem Eintrag in einer Benutzer-crontab?",
|
||||
"options": [
|
||||
{ "id": "a", "text": "Vor dem Befehl steht zusätzlich ein Feld mit dem Benutzernamen, unter dem der Befehl läuft.", "correct": true, "explanation": "Aufbau systemweit: fünf Zeitfelder, Benutzer, Befehl – z. B. `17 * * * * root run-parts /etc/cron.hourly`." },
|
||||
{ "id": "b", "text": "Es gibt kein Feld für den Wochentag.", "correct": false, "explanation": "Die fünf Zeitfelder sind identisch." },
|
||||
{ "id": "c", "text": "Die Zeitangaben stehen in Sekunden statt in Minuten.", "correct": false, "explanation": "cron arbeitet mit Minuten als kleinster Einheit." },
|
||||
{ "id": "d", "text": "Die Datei wird mit `crontab -e` bearbeitet.", "correct": false, "explanation": "`/etc/crontab` wird direkt mit einem Editor bearbeitet." },
|
||||
{ "id": "e", "text": "Befehle laufen dort immer als root, ein Benutzerfeld gibt es nicht.", "correct": false, "explanation": "Gerade das Benutzerfeld ist der Unterschied." }
|
||||
],
|
||||
"explanation": "Daneben gibt es `/etc/cron.hourly`, `.daily`, `.weekly`, `.monthly` für Skripte ohne Zeitangabe.",
|
||||
"references": ["man 5 crontab", "man 8 cron"]
|
||||
},
|
||||
{
|
||||
"id": "107.2-004",
|
||||
"objective": "107.2",
|
||||
"type": "single",
|
||||
"difficulty": 1,
|
||||
"question": "Ein Befehl soll **einmalig** heute um 23:00 Uhr ausgeführt werden. Welches Werkzeug ist dafür gedacht?",
|
||||
"options": [
|
||||
{ "id": "a", "text": "`at 23:00`", "correct": true, "explanation": "`at` liest die Befehle von stdin und führt sie einmalig zur angegebenen Zeit aus." },
|
||||
{ "id": "b", "text": "`batch 23:00`", "correct": false, "explanation": "`batch` führt Aufträge aus, sobald die Systemlast es zulässt; eine Uhrzeit nimmt es nicht an." },
|
||||
{ "id": "c", "text": "`crontab -t 23:00`", "correct": false, "explanation": "`crontab` hat keine Option `-t`; cron ist für wiederkehrende Aufträge." },
|
||||
{ "id": "d", "text": "`sleep 23:00`", "correct": false, "explanation": "`sleep` erwartet eine Dauer, keine Uhrzeit." },
|
||||
{ "id": "e", "text": "`cron 23:00`", "correct": false, "explanation": "`cron` ist der Daemon und nimmt keine Aufträge auf der Befehlszeile an." }
|
||||
],
|
||||
"explanation": "`atq` listet anstehende at-Aufträge, `atrm` löscht sie. Zugriff steuern `/etc/at.allow` und `/etc/at.deny`. Mit systemd: `systemd-run --on-calendar=…`.",
|
||||
"references": ["man 1 at"]
|
||||
},
|
||||
{
|
||||
"id": "107.2-005",
|
||||
"objective": "107.2",
|
||||
"type": "multi",
|
||||
"difficulty": 2,
|
||||
"question": "Welche Dateien steuern, welche Benutzer `crontab` verwenden dürfen?",
|
||||
"options": [
|
||||
{ "id": "a", "text": "`/etc/cron.allow`", "correct": true, "explanation": "Existiert sie, dürfen nur die dort genannten Benutzer crontab nutzen." },
|
||||
{ "id": "b", "text": "`/etc/cron.deny`", "correct": true, "explanation": "Existiert keine `cron.allow`, sind die hier genannten Benutzer ausgeschlossen." },
|
||||
{ "id": "c", "text": "`/etc/at.deny`", "correct": false, "explanation": "Steuert nur den Zugriff auf `at`." },
|
||||
{ "id": "d", "text": "`/etc/crontab`", "correct": false, "explanation": "Die systemweite crontab enthält Aufträge, keine Zugriffsregeln." },
|
||||
{ "id": "e", "text": "`/etc/security/access.conf`", "correct": false, "explanation": "Regelt per PAM, wer sich wo anmelden darf." }
|
||||
],
|
||||
"explanation": "Fehlen beide Dateien, hängt das Verhalten von der Distribution ab (oft dürfen alle, teils nur root).",
|
||||
"references": ["man 1 crontab"]
|
||||
},
|
||||
{
|
||||
"id": "107.2-006",
|
||||
"objective": "107.2",
|
||||
"type": "single",
|
||||
"difficulty": 1,
|
||||
"question": "Welcher Befehl listet alle systemd-Timer mit ihrem nächsten und letzten Ausführungszeitpunkt auf?",
|
||||
"options": [
|
||||
{ "id": "a", "text": "`systemctl list-timers`", "correct": true, "explanation": "Mit `--all` auch inaktive Timer." },
|
||||
{ "id": "b", "text": "`systemctl status cron`", "correct": false, "explanation": "Zeigt den Zustand des cron-Dienstes, nicht die systemd-Timer." },
|
||||
{ "id": "c", "text": "`atq`", "correct": false, "explanation": "Listet at-Aufträge." },
|
||||
{ "id": "d", "text": "`crontab -l`", "correct": false, "explanation": "Listet die crontab des aktuellen Benutzers." },
|
||||
{ "id": "e", "text": "`journalctl --timers`", "correct": false, "explanation": "Eine solche Option gibt es nicht." }
|
||||
],
|
||||
"explanation": "Ein Timer (`name.timer`) startet die gleichnamige `name.service`-Unit; Zeitangaben z. B. `OnCalendar=daily` oder `OnBootSec=10min`.",
|
||||
"references": ["man 5 systemd.timer"]
|
||||
},
|
||||
{
|
||||
"id": "107.3-001",
|
||||
"objective": "107.3",
|
||||
"type": "single",
|
||||
"difficulty": 1,
|
||||
"question": "Mit welchem Befehl stellt man auf einem systemd-System die Zeitzone **dauerhaft** auf Europe/Berlin?",
|
||||
"options": [
|
||||
{ "id": "a", "text": "`timedatectl set-timezone Europe/Berlin`", "correct": true, "explanation": "Setzt den Link `/etc/localtime` auf `/usr/share/zoneinfo/Europe/Berlin`." },
|
||||
{ "id": "b", "text": "`localectl set-timezone Europe/Berlin`", "correct": false, "explanation": "`localectl` verwaltet Locale und Tastaturbelegung, keine Zeitzone." },
|
||||
{ "id": "c", "text": "`export TZ=Europe/Berlin`", "correct": false, "explanation": "Gilt nur für die aktuelle Shell und ihre Kindprozesse." },
|
||||
{ "id": "d", "text": "`hwclock --timezone Europe/Berlin`", "correct": false, "explanation": "`hwclock` liest und stellt die Hardware-Uhr, eine Zeitzone setzt es nicht." },
|
||||
{ "id": "e", "text": "`date --zone Europe/Berlin`", "correct": false, "explanation": "`date` hat keine solche Option; man kann nur per `TZ=… date` einmalig anzeigen." }
|
||||
],
|
||||
"explanation": "Ohne systemd: `/etc/localtime` von Hand verlinken bzw. unter Debian `/etc/timezone` und `dpkg-reconfigure tzdata`. Interaktiv hilft `tzselect`.",
|
||||
"references": ["man 1 timedatectl", "man 8 tzselect"]
|
||||
},
|
||||
{
|
||||
"id": "107.3-002",
|
||||
"objective": "107.3",
|
||||
"type": "single",
|
||||
"difficulty": 2,
|
||||
"question": "Welche Variable überschreibt **alle** anderen Locale-Einstellungen (`LANG` und alle `LC_*`)?",
|
||||
"options": [
|
||||
{ "id": "a", "text": "`LC_ALL`", "correct": true, "explanation": "`LC_ALL` hat Vorrang vor allen einzelnen `LC_*` und vor `LANG`." },
|
||||
{ "id": "b", "text": "`LANG`", "correct": false, "explanation": "`LANG` ist der Standardwert mit der niedrigsten Priorität." },
|
||||
{ "id": "c", "text": "`LC_MESSAGES`", "correct": false, "explanation": "Gilt nur für die Sprache von Programmmeldungen." },
|
||||
{ "id": "d", "text": "`LC_CTYPE`", "correct": false, "explanation": "Gilt nur für Zeichenklassifizierung und Zeichensatz." },
|
||||
{ "id": "e", "text": "`TZ`", "correct": false, "explanation": "`TZ` legt die Zeitzone fest, keine Locale." }
|
||||
],
|
||||
"explanation": "`locale` zeigt die wirksamen Werte, `locale -a` alle verfügbaren Locales. `LANG=C` bzw. `C.UTF-8` erzwingt neutrale Ausgaben, z. B. in Skripten.",
|
||||
"references": ["man 7 locale"]
|
||||
},
|
||||
{
|
||||
"id": "107.3-003",
|
||||
"objective": "107.3",
|
||||
"type": "fill",
|
||||
"difficulty": 1,
|
||||
"question": "Welches Programm konvertiert Textdateien zwischen Zeichenkodierungen, z. B. von ISO-8859-1 nach UTF-8? (nur der Befehlsname)",
|
||||
"answers": ["iconv"],
|
||||
"explanation": "Beispiel: `iconv -f ISO-8859-1 -t UTF-8 alt.txt > neu.txt`; `iconv -l` listet die bekannten Kodierungen.",
|
||||
"references": ["man 1 iconv"]
|
||||
},
|
||||
{
|
||||
"id": "107.3-004",
|
||||
"objective": "107.3",
|
||||
"type": "multi",
|
||||
"difficulty": 2,
|
||||
"question": "Welche Aussagen zu Zeichenkodierungen treffen zu?",
|
||||
"options": [
|
||||
{ "id": "a", "text": "UTF-8 kodiert Unicode-Zeichen mit variabler Länge (1 bis 4 Byte).", "correct": true, "explanation": "Häufige Zeichen sind kurz, seltene länger." },
|
||||
{ "id": "b", "text": "ASCII-Zeichen haben in UTF-8 dieselben Byte-Werte wie in ASCII.", "correct": true, "explanation": "UTF-8 ist abwärtskompatibel zu 7-Bit-ASCII." },
|
||||
{ "id": "c", "text": "ISO-8859-1 enthält das Euro-Zeichen.", "correct": false, "explanation": "Das Euro-Zeichen kam erst mit ISO-8859-15 (Latin-9)." },
|
||||
{ "id": "d", "text": "UTF-8 benötigt für jedes Zeichen genau 2 Byte.", "correct": false, "explanation": "Feste 2 Byte entsprächen UCS-2; UTF-8 ist variabel." },
|
||||
{ "id": "e", "text": "`LANG=C` aktiviert UTF-8 für alle Programme.", "correct": false, "explanation": "Die C/POSIX-Locale verwendet ASCII; für UTF-8 z. B. `C.UTF-8` oder `de_DE.UTF-8`." }
|
||||
],
|
||||
"explanation": "Im Objective genannt: UTF-8, ISO-8859, ASCII, Unicode sowie `locale`, `iconv`, `/etc/timezone`, `/etc/localtime`, `/usr/share/zoneinfo/`.",
|
||||
"references": ["man 7 utf-8", "man 7 charsets"]
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,269 @@
|
||||
{
|
||||
"$schema": "../schema/questions.schema.json",
|
||||
"format": "lpic-sim-questions",
|
||||
"meta": {
|
||||
"file": "questions_108.json",
|
||||
"brief": "Fragen 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 (29.10.2026)"
|
||||
},
|
||||
"exam": "lpic1-102",
|
||||
"questions": [
|
||||
{
|
||||
"id": "108.1-001",
|
||||
"objective": "108.1",
|
||||
"type": "single",
|
||||
"difficulty": 1,
|
||||
"question": "Die Systemzeit ist korrekt. Mit welchem Befehl überträgt man sie in die Hardware-Uhr (RTC)?",
|
||||
"options": [
|
||||
{ "id": "a", "text": "`hwclock --systohc`", "correct": true, "explanation": "system to hardware clock: Systemzeit → RTC." },
|
||||
{ "id": "b", "text": "`hwclock --hctosys`", "correct": false, "explanation": "Umgekehrte Richtung: RTC → Systemzeit (passiert beim Start)." },
|
||||
{ "id": "c", "text": "`hwclock --show`", "correct": false, "explanation": "Zeigt die Zeit der Hardware-Uhr nur an." },
|
||||
{ "id": "d", "text": "`date -s now`", "correct": false, "explanation": "`date -s` stellt die Systemzeit, nicht die Hardware-Uhr." },
|
||||
{ "id": "e", "text": "`timedatectl set-ntp true`", "correct": false, "explanation": "Aktiviert die NTP-Synchronisation der Systemzeit." }
|
||||
],
|
||||
"explanation": "Linux führt eine Systemuhr (Kernel) und die batteriegepufferte Hardware-Uhr. Ob die RTC in UTC oder Ortszeit läuft, zeigt `timedatectl` (RTC in local TZ).",
|
||||
"references": ["man 8 hwclock"]
|
||||
},
|
||||
{
|
||||
"id": "108.1-002",
|
||||
"objective": "108.1",
|
||||
"type": "single",
|
||||
"difficulty": 2,
|
||||
"question": "Auf einem System läuft `chronyd`. Welcher Befehl zeigt die konfigurierten Zeitquellen und deren Zustand?",
|
||||
"options": [
|
||||
{ "id": "a", "text": "`chronyc sources`", "correct": true, "explanation": "Listet die Quellen; `*` markiert die aktuell gewählte. `chronyc tracking` zeigt die Abweichung." },
|
||||
{ "id": "b", "text": "`ntpq -p`", "correct": false, "explanation": "`ntpq -p` gehört zum klassischen `ntpd` und fragt dessen Peers ab." },
|
||||
{ "id": "c", "text": "`chronyd -q`", "correct": false, "explanation": "Stellt die Uhr einmalig und beendet sich (ähnlich `ntpdate`)." },
|
||||
{ "id": "d", "text": "`timedatectl timesync-status`", "correct": false, "explanation": "Zeigt den Status von `systemd-timesyncd`, nicht von chrony." },
|
||||
{ "id": "e", "text": "`hwclock -r`", "correct": false, "explanation": "Liest nur die Hardware-Uhr." }
|
||||
],
|
||||
"explanation": "Konfiguration: `/etc/chrony.conf` bzw. `/etc/chrony/chrony.conf` (Debian), beim klassischen ntpd `/etc/ntp.conf`.",
|
||||
"references": ["man 1 chronyc"]
|
||||
},
|
||||
{
|
||||
"id": "108.1-003",
|
||||
"objective": "108.1",
|
||||
"type": "fill",
|
||||
"difficulty": 1,
|
||||
"question": "Geben Sie den `timedatectl`-Befehl ein, der die automatische Zeitsynchronisation per NTP einschaltet.",
|
||||
"answers": ["timedatectl set-ntp true", "timedatectl set-ntp yes", "timedatectl set-ntp on", "timedatectl set-ntp 1"],
|
||||
"explanation": "`timedatectl` ohne Argumente zeigt u. a. `NTP service: active` und `System clock synchronized`.",
|
||||
"references": ["man 1 timedatectl"]
|
||||
},
|
||||
{
|
||||
"id": "108.1-004",
|
||||
"objective": "108.1",
|
||||
"type": "multi",
|
||||
"difficulty": 1,
|
||||
"question": "Welche Aussagen zum Network Time Protocol (NTP) treffen zu?",
|
||||
"options": [
|
||||
{ "id": "a", "text": "NTP verwendet UDP-Port 123.", "correct": true, "explanation": "Sowohl Client als auch Server nutzen Port 123/udp." },
|
||||
{ "id": "b", "text": "`pool.ntp.org` ist ein öffentlicher Verbund von NTP-Servern.", "correct": true, "explanation": "Über DNS werden wechselnde Server aus dem Pool vergeben." },
|
||||
{ "id": "c", "text": "NTP verwendet TCP-Port 123.", "correct": false, "explanation": "NTP läuft über UDP." },
|
||||
{ "id": "d", "text": "`ntpdate` gleicht die Uhr dauerhaft und kontinuierlich ab.", "correct": false, "explanation": "`ntpdate` stellt die Uhr einmalig und ist veraltet." },
|
||||
{ "id": "e", "text": "`date` ohne Optionen stellt die Uhr nach einem Zeitserver.", "correct": false, "explanation": "`date` ohne Optionen zeigt nur Datum und Uhrzeit an." }
|
||||
],
|
||||
"explanation": "Begriffe: Stratum (Abstand zur Referenzuhr), Offset, Drift. NTP-Implementierungen: ntpd, chrony, systemd-timesyncd (nur Client).",
|
||||
"references": ["RFC 5905"]
|
||||
},
|
||||
{
|
||||
"id": "108.2-001",
|
||||
"objective": "108.2",
|
||||
"type": "single",
|
||||
"difficulty": 1,
|
||||
"question": "Wie zeigt man alle Journal-Meldungen der systemd-Unit `ssh.service` an?",
|
||||
"options": [
|
||||
{ "id": "a", "text": "`journalctl -u ssh.service`", "correct": true, "explanation": "`-u` filtert nach Unit." },
|
||||
{ "id": "b", "text": "`journalctl -k ssh.service`", "correct": false, "explanation": "`-k` zeigt nur Kernel-Meldungen." },
|
||||
{ "id": "c", "text": "`journalctl -b ssh.service`", "correct": false, "explanation": "`-b` filtert nach Boot; der Unit-Name würde als Feldfilter missverstanden." },
|
||||
{ "id": "d", "text": "`systemctl log ssh.service`", "correct": false, "explanation": "`systemctl` hat keinen Unterbefehl `log`; `systemctl status` zeigt nur die letzten Zeilen." },
|
||||
{ "id": "e", "text": "`journalctl -p ssh.service`", "correct": false, "explanation": "`-p` filtert nach Priorität, z. B. `-p err`." }
|
||||
],
|
||||
"explanation": "Kombinierbar: `journalctl -u ssh -b -p warning --since \"1 hour ago\"`.",
|
||||
"references": ["man 1 journalctl"]
|
||||
},
|
||||
{
|
||||
"id": "108.2-002",
|
||||
"objective": "108.2",
|
||||
"type": "fill",
|
||||
"difficulty": 1,
|
||||
"question": "Welche `journalctl`-Option zeigt neu eintreffende Meldungen fortlaufend an (wie `tail -f`)? (nur die Option)",
|
||||
"answers": ["-f", "--follow"],
|
||||
"explanation": "`journalctl -f` folgt dem Journal; `-n 50` zeigt zuvor die letzten 50 Zeilen.",
|
||||
"references": ["man 1 journalctl"]
|
||||
},
|
||||
{
|
||||
"id": "108.2-003",
|
||||
"objective": "108.2",
|
||||
"type": "single",
|
||||
"difficulty": 2,
|
||||
"question": "Was bewirkt die rsyslog-Regel `mail.err /var/log/mail.err`?",
|
||||
"options": [
|
||||
{ "id": "a", "text": "Meldungen der Facility `mail` mit Priorität `err` **und höher** landen in der Datei.", "correct": true, "explanation": "Eine Priorität ohne Zusatz bedeutet: diese und alle schwerwiegenderen." },
|
||||
{ "id": "b", "text": "Nur Meldungen der Facility `mail` mit genau der Priorität `err` landen in der Datei.", "correct": false, "explanation": "Genau eine Priorität: `mail.=err`." },
|
||||
{ "id": "c", "text": "Alle Meldungen der Facility `mail` landen in der Datei.", "correct": false, "explanation": "Das wäre `mail.*`." },
|
||||
{ "id": "d", "text": "Fehlermeldungen aller Facilities landen in der Datei.", "correct": false, "explanation": "Das wäre `*.err`." },
|
||||
{ "id": "e", "text": "Mail-Fehler werden per E-Mail an root geschickt.", "correct": false, "explanation": "Ziel ist eine Datei; Weiterleitung an Hosts erfolgt mit `@host` bzw. `@@host`." }
|
||||
],
|
||||
"explanation": "Prioritäten aufsteigend: debug, info, notice, warning, err, crit, alert, emerg. `none` schließt aus, z. B. `*.info;mail.none`.",
|
||||
"references": ["man 5 rsyslog.conf"]
|
||||
},
|
||||
{
|
||||
"id": "108.2-004",
|
||||
"objective": "108.2",
|
||||
"type": "single",
|
||||
"difficulty": 1,
|
||||
"question": "Mit welchem Befehl schreibt ein Shell-Skript eine eigene Meldung ins Systemprotokoll?",
|
||||
"options": [
|
||||
{ "id": "a", "text": "`logger \"Backup beendet\"`", "correct": true, "explanation": "`logger` übergibt die Meldung an syslog/journald; `-t` setzt einen Tag, `-p` die Priorität." },
|
||||
{ "id": "b", "text": "`wall \"Backup beendet\"`", "correct": false, "explanation": "`wall` sendet die Nachricht an alle Terminals." },
|
||||
{ "id": "c", "text": "`journalctl --write \"Backup beendet\"`", "correct": false, "explanation": "`journalctl` liest das Journal; eine Option `--write` gibt es nicht." },
|
||||
{ "id": "d", "text": "`dmesg -w \"Backup beendet\"`", "correct": false, "explanation": "`dmesg -w` wartet auf neue Kernel-Meldungen (follow)." },
|
||||
{ "id": "e", "text": "`syslog \"Backup beendet\"`", "correct": false, "explanation": "Einen Befehl `syslog` gibt es nicht." }
|
||||
],
|
||||
"explanation": "Beispiel mit Facility und Priorität: `logger -p local0.notice -t backup \"fertig\"`.",
|
||||
"references": ["man 1 logger"]
|
||||
},
|
||||
{
|
||||
"id": "108.2-005",
|
||||
"objective": "108.2",
|
||||
"type": "multi",
|
||||
"difficulty": 2,
|
||||
"question": "Wie erreicht man, dass das systemd-Journal Neustarts **überdauert** (persistent gespeichert wird)?",
|
||||
"options": [
|
||||
{ "id": "a", "text": "In `/etc/systemd/journald.conf` `Storage=persistent` setzen", "correct": true, "explanation": "journald schreibt dann nach `/var/log/journal`." },
|
||||
{ "id": "b", "text": "Das Verzeichnis `/var/log/journal` anlegen (bei `Storage=auto`)", "correct": true, "explanation": "Bei der Standardeinstellung `auto` wird persistent gespeichert, sobald das Verzeichnis existiert." },
|
||||
{ "id": "c", "text": "`Storage=volatile` setzen", "correct": false, "explanation": "`volatile` speichert nur im RAM unter `/run/log/journal`." },
|
||||
{ "id": "d", "text": "`journalctl --vacuum-size=1G` ausführen", "correct": false, "explanation": "Löscht alte Journal-Dateien, bis die Größe unterschritten ist." },
|
||||
{ "id": "e", "text": "`logrotate` für das Journal einrichten", "correct": false, "explanation": "journald rotiert selbst; logrotate ist für Textlogs." }
|
||||
],
|
||||
"explanation": "Größe begrenzen: `SystemMaxUse=` in `journald.conf`. Journal einer anderen Installation lesen: `journalctl -D <verzeichnis>`.",
|
||||
"references": ["man 5 journald.conf"]
|
||||
},
|
||||
{
|
||||
"id": "108.2-006",
|
||||
"objective": "108.2",
|
||||
"type": "single",
|
||||
"difficulty": 1,
|
||||
"question": "Wo legt man üblicherweise die Rotationsregeln für die Logdateien **eines einzelnen Dienstes** ab?",
|
||||
"options": [
|
||||
{ "id": "a", "text": "In einer Datei unter `/etc/logrotate.d/`", "correct": true, "explanation": "`/etc/logrotate.conf` bindet dieses Verzeichnis per `include` ein." },
|
||||
{ "id": "b", "text": "In einer Datei unter `/etc/rsyslog.d/`", "correct": false, "explanation": "Dort stehen Regeln, wohin rsyslog Meldungen schreibt, nicht wie rotiert wird." },
|
||||
{ "id": "c", "text": "In `/etc/systemd/journald.conf`", "correct": false, "explanation": "Gilt nur für das Journal, nicht für Textlogs eines Dienstes." },
|
||||
{ "id": "d", "text": "In `/var/log/rotate/`", "correct": false, "explanation": "Kein Standardpfad." },
|
||||
{ "id": "e", "text": "In `/etc/cron.daily/`", "correct": false, "explanation": "Dort liegt das Skript, das logrotate täglich startet, nicht die Regeln." }
|
||||
],
|
||||
"explanation": "Typische Direktiven: `daily`/`weekly`, `rotate 7`, `compress`, `missingok`, `notifempty`, `postrotate … endscript`.",
|
||||
"references": ["man 8 logrotate"]
|
||||
},
|
||||
{
|
||||
"id": "108.3-001",
|
||||
"objective": "108.3",
|
||||
"type": "single",
|
||||
"difficulty": 1,
|
||||
"question": "Welches der folgenden Programme ist ein **Mail Transfer Agent (MTA)**?",
|
||||
"options": [
|
||||
{ "id": "a", "text": "Postfix", "correct": true, "explanation": "Postfix nimmt Mails per SMTP an und leitet sie weiter bzw. stellt sie zu." },
|
||||
{ "id": "b", "text": "Dovecot", "correct": false, "explanation": "Dovecot ist ein IMAP/POP3-Server für den Abruf von Mails." },
|
||||
{ "id": "c", "text": "Thunderbird", "correct": false, "explanation": "Thunderbird ist ein Mail User Agent (MUA)." },
|
||||
{ "id": "d", "text": "mutt", "correct": false, "explanation": "mutt ist ein textbasierter MUA." },
|
||||
{ "id": "e", "text": "procmail", "correct": false, "explanation": "procmail ist ein Mail Delivery Agent (MDA), der Mails lokal sortiert und zustellt." }
|
||||
],
|
||||
"explanation": "Weitere MTAs: Sendmail, Exim. Alle bieten aus Kompatibilitätsgründen einen `sendmail`-Befehl.",
|
||||
"references": ["LPI 102-500 Objective 108.3"]
|
||||
},
|
||||
{
|
||||
"id": "108.3-002",
|
||||
"objective": "108.3",
|
||||
"type": "single",
|
||||
"difficulty": 1,
|
||||
"question": "In `/etc/aliases` wurde `root: admin@example.org` eingetragen. Welcher Befehl muss danach ausgeführt werden?",
|
||||
"options": [
|
||||
{ "id": "a", "text": "`newaliases`", "correct": true, "explanation": "Erzeugt die Alias-Datenbank (z. B. `/etc/aliases.db`) neu, die der MTA liest." },
|
||||
{ "id": "b", "text": "`mailq`", "correct": false, "explanation": "`mailq` zeigt die Warteschlange." },
|
||||
{ "id": "c", "text": "`sendmail -q`", "correct": false, "explanation": "Arbeitet die Warteschlange ab." },
|
||||
{ "id": "d", "text": "`postfix check`", "correct": false, "explanation": "Prüft die Postfix-Konfiguration, baut die Aliase aber nicht neu." },
|
||||
{ "id": "e", "text": "`systemctl restart aliases`", "correct": false, "explanation": "Einen Dienst `aliases` gibt es nicht." }
|
||||
],
|
||||
"explanation": "`newaliases` entspricht `sendmail -bi`.",
|
||||
"references": ["man 5 aliases", "man 1 newaliases"]
|
||||
},
|
||||
{
|
||||
"id": "108.3-003",
|
||||
"objective": "108.3",
|
||||
"type": "fill",
|
||||
"difficulty": 1,
|
||||
"question": "Welche Datei legt ein Benutzer in seinem Home-Verzeichnis an, um seine E-Mails an eine andere Adresse weiterzuleiten? (Dateiname)",
|
||||
"answers": [".forward", "~/.forward"],
|
||||
"explanation": "`~/.forward` enthält die Zieladresse(n). Systemweite Weiterleitungen gehören in `/etc/aliases`.",
|
||||
"references": ["man 5 forward"]
|
||||
},
|
||||
{
|
||||
"id": "108.3-004",
|
||||
"objective": "108.3",
|
||||
"type": "single",
|
||||
"difficulty": 1,
|
||||
"question": "Welcher Befehl zeigt die Mail-Warteschlange des lokalen MTA an?",
|
||||
"options": [
|
||||
{ "id": "a", "text": "`mailq`", "correct": true, "explanation": "`mailq` entspricht `sendmail -bp` und funktioniert bei Sendmail, Postfix und Exim." },
|
||||
{ "id": "b", "text": "`newaliases`", "correct": false, "explanation": "Baut die Alias-Datenbank neu." },
|
||||
{ "id": "c", "text": "`mail`", "correct": false, "explanation": "`mail` ist ein einfacher MUA zum Lesen und Senden." },
|
||||
{ "id": "d", "text": "`postqueue -f`", "correct": false, "explanation": "`postqueue -f` versucht, die Postfix-Warteschlange sofort zuzustellen (flush)." },
|
||||
{ "id": "e", "text": "`smtpd`", "correct": false, "explanation": "`smtpd` ist ein Serverprozess von Postfix." }
|
||||
],
|
||||
"explanation": "Lokale Mails von Diensten (z. B. cron) landen ohne Weiterleitung im Spool unter `/var/spool/mail/` bzw. `/var/mail/`.",
|
||||
"references": ["man 1 mailq"]
|
||||
},
|
||||
{
|
||||
"id": "108.4-001",
|
||||
"objective": "108.4",
|
||||
"type": "single",
|
||||
"difficulty": 1,
|
||||
"question": "Auf welchem TCP-Port ist die Weboberfläche von CUPS standardmäßig erreichbar?",
|
||||
"options": [
|
||||
{ "id": "a", "text": "631", "correct": true, "explanation": "CUPS spricht IPP auf Port 631; dort liegt auch die Weboberfläche (http://localhost:631)." },
|
||||
{ "id": "b", "text": "515", "correct": false, "explanation": "515 ist der Port des alten LPD-Protokolls." },
|
||||
{ "id": "c", "text": "9100", "correct": false, "explanation": "9100 ist der Port für Raw-/JetDirect-Druck direkt auf Netzwerkdrucker." },
|
||||
{ "id": "d", "text": "8080", "correct": false, "explanation": "Üblicher alternativer HTTP-Port, nicht CUPS." },
|
||||
{ "id": "e", "text": "443", "correct": false, "explanation": "443 ist HTTPS." }
|
||||
],
|
||||
"explanation": "CUPS-Konfiguration: `/etc/cups/cupsd.conf` (Dienst), `/etc/cups/printers.conf` (Drucker, nicht von Hand bei laufendem Dienst bearbeiten).",
|
||||
"references": ["man 8 cupsd"]
|
||||
},
|
||||
{
|
||||
"id": "108.4-002",
|
||||
"objective": "108.4",
|
||||
"type": "single",
|
||||
"difficulty": 1,
|
||||
"question": "Welcher Befehl entfernt einen Druckauftrag aus der Warteschlange?",
|
||||
"options": [
|
||||
{ "id": "a", "text": "`lprm`", "correct": true, "explanation": "`lprm <jobnr>` löscht den Auftrag (System-V-Variante: `cancel`)." },
|
||||
{ "id": "b", "text": "`lpq`", "correct": false, "explanation": "`lpq` zeigt die Warteschlange an." },
|
||||
{ "id": "c", "text": "`lpr`", "correct": false, "explanation": "`lpr` druckt eine Datei." },
|
||||
{ "id": "d", "text": "`lpstat`", "correct": false, "explanation": "`lpstat` zeigt Status von Druckern und Aufträgen." },
|
||||
{ "id": "e", "text": "`lpadmin`", "correct": false, "explanation": "`lpadmin` richtet Drucker ein und konfiguriert sie." }
|
||||
],
|
||||
"explanation": "Berkeley-Befehle: `lpr`, `lpq`, `lprm`. System-V-Befehle: `lp`, `lpstat`, `cancel`. CUPS unterstützt beide.",
|
||||
"references": ["man 1 lprm"]
|
||||
},
|
||||
{
|
||||
"id": "108.4-003",
|
||||
"objective": "108.4",
|
||||
"type": "multi",
|
||||
"difficulty": 2,
|
||||
"question": "Welche Aussagen zum Drucken unter Linux treffen zu?",
|
||||
"options": [
|
||||
{ "id": "a", "text": "`lpr -P buero bericht.pdf` druckt auf dem Drucker `buero`.", "correct": true, "explanation": "`-P` wählt den Drucker; ohne Angabe gilt der Standarddrucker." },
|
||||
{ "id": "b", "text": "`lpq` zeigt die Aufträge in der Warteschlange.", "correct": true, "explanation": "Mit `-P` für einen bestimmten Drucker, `-a` für alle." },
|
||||
{ "id": "c", "text": "`lpq` druckt eine Datei aus.", "correct": false, "explanation": "Drucken: `lpr` bzw. `lp`." },
|
||||
{ "id": "d", "text": "Die CUPS-Dienstkonfiguration liegt in `/etc/printcap.conf`.", "correct": false, "explanation": "Sie liegt in `/etc/cups/cupsd.conf`; `/etc/printcap` ist ein Überbleibsel von LPD." },
|
||||
{ "id": "e", "text": "`cupsenable buero` löscht den Drucker `buero`.", "correct": false, "explanation": "`cupsenable` aktiviert einen Drucker; löschen: `lpadmin -x buero`." }
|
||||
],
|
||||
"explanation": "Annahme von Aufträgen steuern `cupsaccept`/`cupsreject`, das Drucken `cupsenable`/`cupsdisable`.",
|
||||
"references": ["man 1 lpr", "man 1 lpq"]
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,327 @@
|
||||
{
|
||||
"$schema": "../schema/questions.schema.json",
|
||||
"format": "lpic-sim-questions",
|
||||
"meta": {
|
||||
"file": "questions_109.json",
|
||||
"brief": "Fragen 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 (29.10.2026)"
|
||||
},
|
||||
"exam": "lpic1-102",
|
||||
"questions": [
|
||||
{
|
||||
"id": "109.1-001",
|
||||
"objective": "109.1",
|
||||
"type": "single",
|
||||
"difficulty": 1,
|
||||
"question": "Welche Subnetzmaske entspricht dem Präfix `/26`?",
|
||||
"options": [
|
||||
{ "id": "a", "text": "`255.255.255.192`", "correct": true, "explanation": "26 Bits gesetzt: 24 + 2 → letztes Oktett 11000000 = 192." },
|
||||
{ "id": "b", "text": "`255.255.255.128`", "correct": false, "explanation": "Das ist `/25`." },
|
||||
{ "id": "c", "text": "`255.255.255.224`", "correct": false, "explanation": "Das ist `/27`." },
|
||||
{ "id": "d", "text": "`255.255.255.240`", "correct": false, "explanation": "Das ist `/28`." },
|
||||
{ "id": "e", "text": "`255.255.255.252`", "correct": false, "explanation": "Das ist `/30`." }
|
||||
],
|
||||
"explanation": "Werte im letzten Oktett: /25 = 128, /26 = 192, /27 = 224, /28 = 240, /29 = 248, /30 = 252.",
|
||||
"references": ["RFC 4632"]
|
||||
},
|
||||
{
|
||||
"id": "109.1-002",
|
||||
"objective": "109.1",
|
||||
"type": "single",
|
||||
"difficulty": 2,
|
||||
"question": "Wie viele Adressen stehen in einem IPv4-Subnetz `/27` für Hosts zur Verfügung?",
|
||||
"options": [
|
||||
{ "id": "a", "text": "30", "correct": true, "explanation": "2^(32−27) = 32 Adressen, abzüglich Netz- und Broadcast-Adresse = 30." },
|
||||
{ "id": "b", "text": "32", "correct": false, "explanation": "Das ist die Gesamtzahl der Adressen inklusive Netz- und Broadcast-Adresse." },
|
||||
{ "id": "c", "text": "62", "correct": false, "explanation": "Das gilt für `/26`." },
|
||||
{ "id": "d", "text": "14", "correct": false, "explanation": "Das gilt für `/28`." },
|
||||
{ "id": "e", "text": "27", "correct": false, "explanation": "Das Präfix ist die Zahl der Netzbits, nicht der Hosts." }
|
||||
],
|
||||
"explanation": "Hosts = 2^(32 − Präfix) − 2. Beispiel `192.0.2.32/27`: Netz .32, Hosts .33–.62, Broadcast .63.",
|
||||
"references": ["RFC 950"]
|
||||
},
|
||||
{
|
||||
"id": "109.1-003",
|
||||
"objective": "109.1",
|
||||
"type": "fill",
|
||||
"difficulty": 1,
|
||||
"question": "Welchen TCP-Port verwendet SSH standardmäßig? (nur die Zahl)",
|
||||
"answers": ["22"],
|
||||
"explanation": "Zuordnungen von Ports zu Diensten stehen in `/etc/services`.",
|
||||
"references": ["man 5 services"]
|
||||
},
|
||||
{
|
||||
"id": "109.1-004",
|
||||
"objective": "109.1",
|
||||
"type": "single",
|
||||
"difficulty": 2,
|
||||
"question": "Welche Adresse gehört zu einem **privaten** Adressbereich nach RFC 1918?",
|
||||
"options": [
|
||||
{ "id": "a", "text": "`172.20.1.5`", "correct": true, "explanation": "Liegt in `172.16.0.0/12` (172.16.0.0 – 172.31.255.255)." },
|
||||
{ "id": "b", "text": "`172.32.0.1`", "correct": false, "explanation": "Liegt knapp außerhalb von `172.16.0.0/12`." },
|
||||
{ "id": "c", "text": "`192.169.1.1`", "correct": false, "explanation": "Privat ist nur `192.168.0.0/16`." },
|
||||
{ "id": "d", "text": "`100.64.0.1`", "correct": false, "explanation": "`100.64.0.0/10` ist Shared Address Space für Carrier-Grade-NAT (RFC 6598), nicht RFC 1918." },
|
||||
{ "id": "e", "text": "`169.254.1.1`", "correct": false, "explanation": "`169.254.0.0/16` ist Link-Local (automatische Adressvergabe ohne DHCP)." }
|
||||
],
|
||||
"explanation": "RFC 1918: `10.0.0.0/8`, `172.16.0.0/12`, `192.168.0.0/16`.",
|
||||
"references": ["RFC 1918"]
|
||||
},
|
||||
{
|
||||
"id": "109.1-005",
|
||||
"objective": "109.1",
|
||||
"type": "multi",
|
||||
"difficulty": 2,
|
||||
"question": "Welche Aussagen zu IPv6 treffen zu?",
|
||||
"options": [
|
||||
{ "id": "a", "text": "Eine IPv6-Adresse ist 128 Bit lang.", "correct": true, "explanation": "Geschrieben als 8 Gruppen à 16 Bit in Hexadezimal." },
|
||||
{ "id": "b", "text": "`::1` ist die Loopback-Adresse.", "correct": true, "explanation": "Entspricht `127.0.0.1` bei IPv4." },
|
||||
{ "id": "c", "text": "Adressen aus `fe80::/10` sind global routbar.", "correct": false, "explanation": "`fe80::/10` ist Link-Local und wird nicht geroutet." },
|
||||
{ "id": "d", "text": "IPv6 verwendet Broadcast-Adressen wie IPv4.", "correct": false, "explanation": "IPv6 kennt keinen Broadcast; stattdessen Multicast (z. B. `ff02::1`)." },
|
||||
{ "id": "e", "text": "Mehrere Nullgruppen dürfen mehrfach in einer Adresse mit `::` abgekürzt werden.", "correct": false, "explanation": "`::` darf nur einmal pro Adresse vorkommen, sonst wäre sie mehrdeutig." }
|
||||
],
|
||||
"explanation": "Weitere Unterschiede: SLAAC zur automatischen Konfiguration, Neighbor Discovery statt ARP, Präfix meist `/64` im LAN.",
|
||||
"references": ["RFC 4291"]
|
||||
},
|
||||
{
|
||||
"id": "109.1-006",
|
||||
"objective": "109.1",
|
||||
"type": "single",
|
||||
"difficulty": 1,
|
||||
"question": "Welche Zuordnung von Standardport zu Dienst ist korrekt?",
|
||||
"options": [
|
||||
{ "id": "a", "text": "443/tcp → HTTPS", "correct": true, "explanation": "HTTP über TLS verwendet Port 443." },
|
||||
{ "id": "b", "text": "25/tcp → POP3", "correct": false, "explanation": "25 ist SMTP; POP3 nutzt 110 (POP3S 995)." },
|
||||
{ "id": "c", "text": "53 → NTP", "correct": false, "explanation": "53 ist DNS; NTP nutzt 123/udp." },
|
||||
{ "id": "d", "text": "143/tcp → SNMP", "correct": false, "explanation": "143 ist IMAP (IMAPS 993); SNMP nutzt 161/udp." },
|
||||
{ "id": "e", "text": "21/tcp → SSH", "correct": false, "explanation": "21 ist FTP (Steuerkanal); SSH nutzt 22." }
|
||||
],
|
||||
"explanation": "Prüfungsrelevant: 20/21 FTP, 22 SSH, 23 Telnet, 25 SMTP, 53 DNS, 80 HTTP, 110 POP3, 123 NTP, 139 NetBIOS, 143 IMAP, 161/162 SNMP, 389 LDAP, 443 HTTPS, 465 SMTPS, 514 syslog, 636 LDAPS, 993 IMAPS, 995 POP3S.",
|
||||
"references": ["man 5 services"]
|
||||
},
|
||||
{
|
||||
"id": "109.2-001",
|
||||
"objective": "109.2",
|
||||
"type": "single",
|
||||
"difficulty": 1,
|
||||
"question": "Welches Kommandozeilenwerkzeug verwaltet Verbindungen des NetworkManager?",
|
||||
"options": [
|
||||
{ "id": "a", "text": "`nmcli`", "correct": true, "explanation": "z. B. `nmcli connection show`, `nmcli device status`, `nmcli con up <name>`." },
|
||||
{ "id": "b", "text": "`ifconfig`", "correct": false, "explanation": "Altes Werkzeug (net-tools), das Schnittstellen direkt konfiguriert, ohne NetworkManager." },
|
||||
{ "id": "c", "text": "`iwconfig`", "correct": false, "explanation": "Altes Werkzeug für WLAN-Parameter." },
|
||||
{ "id": "d", "text": "`systemd-networkd`", "correct": false, "explanation": "Ein eigener Netzwerkdienst, kein Frontend für NetworkManager." },
|
||||
{ "id": "e", "text": "`netstat`", "correct": false, "explanation": "Zeigt Verbindungen und Routen, konfiguriert nichts." }
|
||||
],
|
||||
"explanation": "Textoberfläche für NetworkManager: `nmtui`. systemd-networkd wird über `.network`-Dateien und `networkctl` verwaltet.",
|
||||
"references": ["man 1 nmcli"]
|
||||
},
|
||||
{
|
||||
"id": "109.2-002",
|
||||
"objective": "109.2",
|
||||
"type": "single",
|
||||
"difficulty": 1,
|
||||
"question": "Wie setzt man auf einem systemd-System den Hostnamen dauerhaft auf `web01`?",
|
||||
"options": [
|
||||
{ "id": "a", "text": "`hostnamectl set-hostname web01`", "correct": true, "explanation": "Setzt den Hostnamen sofort und schreibt ihn nach `/etc/hostname`." },
|
||||
{ "id": "b", "text": "`hostname web01`", "correct": false, "explanation": "Gilt nur bis zum nächsten Neustart." },
|
||||
{ "id": "c", "text": "`sysctl kernel.hostname=web01`", "correct": false, "explanation": "Ändert nur den Laufzeitwert im Kernel." },
|
||||
{ "id": "d", "text": "`domainname web01`", "correct": false, "explanation": "Setzt den NIS-Domainnamen." },
|
||||
{ "id": "e", "text": "Nur einen Eintrag in `/etc/hosts` ergänzen", "correct": false, "explanation": "`/etc/hosts` dient der Namensauflösung, nicht dem Setzen des Hostnamens." }
|
||||
],
|
||||
"explanation": "Den eigenen Namen trotzdem in `/etc/hosts` eintragen, damit er lokal auflösbar ist.",
|
||||
"references": ["man 1 hostnamectl"]
|
||||
},
|
||||
{
|
||||
"id": "109.2-003",
|
||||
"objective": "109.2",
|
||||
"type": "fill",
|
||||
"difficulty": 1,
|
||||
"question": "In welcher Datei (vollständiger Pfad) steht der statische Hostname des Systems?",
|
||||
"answers": ["/etc/hostname"],
|
||||
"explanation": "Die Datei enthält nur den Namen in einer Zeile.",
|
||||
"references": ["man 5 hostname"]
|
||||
},
|
||||
{
|
||||
"id": "109.2-004",
|
||||
"objective": "109.2",
|
||||
"type": "single",
|
||||
"difficulty": 1,
|
||||
"question": "Welche Zeile ist in `/etc/hosts` korrekt aufgebaut?",
|
||||
"options": [
|
||||
{ "id": "a", "text": "`192.0.2.10 web01.example.org web01`", "correct": true, "explanation": "IP-Adresse, kanonischer Name, optional Aliase – durch Leerraum getrennt." },
|
||||
{ "id": "b", "text": "`web01.example.org 192.0.2.10`", "correct": false, "explanation": "Die IP-Adresse muss am Anfang stehen." },
|
||||
{ "id": "c", "text": "`192.0.2.10:web01.example.org`", "correct": false, "explanation": "Die Felder werden durch Leerraum getrennt, nicht durch Doppelpunkt." },
|
||||
{ "id": "d", "text": "`host web01 = 192.0.2.10`", "correct": false, "explanation": "Keine gültige Syntax." },
|
||||
{ "id": "e", "text": "`nameserver 192.0.2.10`", "correct": false, "explanation": "Das ist Syntax von `/etc/resolv.conf`." }
|
||||
],
|
||||
"explanation": "Ob `/etc/hosts` vor DNS gefragt wird, legt die Zeile `hosts:` in `/etc/nsswitch.conf` fest.",
|
||||
"references": ["man 5 hosts"]
|
||||
},
|
||||
{
|
||||
"id": "109.2-005",
|
||||
"objective": "109.2",
|
||||
"type": "multi",
|
||||
"difficulty": 2,
|
||||
"question": "Welche Befehle setzen (nicht dauerhaft) korrekt eine IPv4-Adresse bzw. das Standard-Gateway?",
|
||||
"options": [
|
||||
{ "id": "a", "text": "`ip addr add 192.0.2.5/24 dev eth0`", "correct": true, "explanation": "Fügt der Schnittstelle eine Adresse mit Präfix hinzu." },
|
||||
{ "id": "b", "text": "`ip route add default via 192.0.2.1`", "correct": true, "explanation": "Setzt die Standardroute über das Gateway." },
|
||||
{ "id": "c", "text": "`ip addr set eth0 192.0.2.5`", "correct": false, "explanation": "`ip addr` kennt kein `set`; Adressen werden mit `add` hinzugefügt." },
|
||||
{ "id": "d", "text": "`ip gateway add 192.0.2.1`", "correct": false, "explanation": "Ein Objekt `gateway` gibt es bei `ip` nicht." },
|
||||
{ "id": "e", "text": "`ip route default 192.0.2.1`", "correct": false, "explanation": "Es fehlen Aktion (`add`) und Schlüsselwort `via`." }
|
||||
],
|
||||
"explanation": "Mit `ip` gesetzte Werte gehen beim Neustart verloren. Dauerhaft je nach System: NetworkManager, systemd-networkd, netplan oder `/etc/network/interfaces`.",
|
||||
"references": ["man 8 ip-address", "man 8 ip-route"]
|
||||
},
|
||||
{
|
||||
"id": "109.2-006",
|
||||
"objective": "109.2",
|
||||
"type": "single",
|
||||
"difficulty": 2,
|
||||
"question": "Wo werden auf einem Debian-System mit **ifupdown** Netzwerkschnittstellen dauerhaft konfiguriert?",
|
||||
"options": [
|
||||
{ "id": "a", "text": "`/etc/network/interfaces`", "correct": true, "explanation": "Dort stehen z. B. `auto eth0` und `iface eth0 inet static` mit `address`, `gateway`; aktivieren mit `ifup`." },
|
||||
{ "id": "b", "text": "`/etc/sysconfig/network-scripts/ifcfg-eth0`", "correct": false, "explanation": "Klassischer Ort der Red-Hat-Familie, nicht Debian." },
|
||||
{ "id": "c", "text": "`/etc/netplan/01-netcfg.yaml`", "correct": false, "explanation": "netplan wird bei Ubuntu verwendet und erzeugt Konfiguration für networkd oder NetworkManager." },
|
||||
{ "id": "d", "text": "`/etc/resolv.conf`", "correct": false, "explanation": "Enthält nur DNS-Einstellungen." },
|
||||
{ "id": "e", "text": "`/etc/hosts`", "correct": false, "explanation": "Statische Namensauflösung, keine Schnittstellenkonfiguration." }
|
||||
],
|
||||
"explanation": "Hinweis: LPI hat angekündigt, `ifup`/`ifdown` und net-tools künftig aus den Objectives zu entfernen; in Version 5.0 sind sie noch enthalten (Stand 29.10.2026).",
|
||||
"references": ["man 5 interfaces"]
|
||||
},
|
||||
{
|
||||
"id": "109.3-001",
|
||||
"objective": "109.3",
|
||||
"type": "single",
|
||||
"difficulty": 1,
|
||||
"question": "Auf welchem Protokoll und welchen Nachrichten beruht `ping`?",
|
||||
"options": [
|
||||
{ "id": "a", "text": "ICMP Echo Request / Echo Reply", "correct": true, "explanation": "`ping` sendet ICMP Echo Requests und wertet die Antworten aus (IPv6: ICMPv6, `ping -6`)." },
|
||||
{ "id": "b", "text": "UDP-Pakete an Port 7", "correct": false, "explanation": "Port 7 ist der echo-Dienst; `ping` nutzt ihn nicht." },
|
||||
{ "id": "c", "text": "TCP-SYN-Pakete", "correct": false, "explanation": "TCP wird von `ping` nicht verwendet." },
|
||||
{ "id": "d", "text": "ARP Requests", "correct": false, "explanation": "ARP löst im LAN IP- in MAC-Adressen auf (`arping` nutzt ARP)." },
|
||||
{ "id": "e", "text": "DNS-Anfragen", "correct": false, "explanation": "DNS wird höchstens zur Auflösung des Zielnamens genutzt." }
|
||||
],
|
||||
"explanation": "Keine Antwort auf ping heißt nicht zwingend, dass der Host aus ist – ICMP kann gefiltert sein.",
|
||||
"references": ["man 8 ping"]
|
||||
},
|
||||
{
|
||||
"id": "109.3-002",
|
||||
"objective": "109.3",
|
||||
"type": "single",
|
||||
"difficulty": 2,
|
||||
"question": "Welcher Befehl listet alle lauschenden TCP- und UDP-Ports numerisch mit den zugehörigen Prozessen?",
|
||||
"options": [
|
||||
{ "id": "a", "text": "`ss -tulpn`", "correct": true, "explanation": "`-t` TCP, `-u` UDP, `-l` lauschend, `-p` Prozess, `-n` numerisch." },
|
||||
{ "id": "b", "text": "`netstat -r`", "correct": false, "explanation": "`-r` zeigt die Routingtabelle." },
|
||||
{ "id": "c", "text": "`ip link show`", "correct": false, "explanation": "Zeigt Schnittstellen und deren Status." },
|
||||
{ "id": "d", "text": "`ss -s`", "correct": false, "explanation": "Zeigt nur eine Zusammenfassung der Sockets." },
|
||||
{ "id": "e", "text": "`nc -l 22`", "correct": false, "explanation": "Startet selbst einen lauschenden Socket." }
|
||||
],
|
||||
"explanation": "Die alte Entsprechung ist `netstat -tulpn` (net-tools). Prozessangaben fremder Benutzer sieht nur root.",
|
||||
"references": ["man 8 ss"]
|
||||
},
|
||||
{
|
||||
"id": "109.3-003",
|
||||
"objective": "109.3",
|
||||
"type": "fill",
|
||||
"difficulty": 1,
|
||||
"question": "Mit welchem Befehl (nur der Name) ermittelt man die Router (Hops) auf dem Weg zu einem Zielhost?",
|
||||
"answers": ["traceroute", "tracepath", "traceroute6", "tracepath6", "mtr"],
|
||||
"explanation": "`traceroute` erhöht schrittweise die TTL und wertet die ICMP-Antworten „Time Exceeded“ aus. `tracepath` braucht keine Root-Rechte und ermittelt zusätzlich die Path-MTU.",
|
||||
"references": ["man 8 traceroute", "man 8 tracepath"]
|
||||
},
|
||||
{
|
||||
"id": "109.3-004",
|
||||
"objective": "109.3",
|
||||
"type": "single",
|
||||
"difficulty": 1,
|
||||
"question": "Welcher Befehl zeigt die aktuelle Routingtabelle an?",
|
||||
"options": [
|
||||
{ "id": "a", "text": "`ip route`", "correct": true, "explanation": "Kurz `ip r`; zeigt u. a. die `default`-Route." },
|
||||
{ "id": "b", "text": "`ip addr`", "correct": false, "explanation": "Zeigt die Adressen der Schnittstellen." },
|
||||
{ "id": "c", "text": "`ip neigh`", "correct": false, "explanation": "Zeigt den Neighbor-/ARP-Cache." },
|
||||
{ "id": "d", "text": "`ss -r`", "correct": false, "explanation": "`-r` löst bei `ss` Namen auf; es zeigt keine Routen." },
|
||||
{ "id": "e", "text": "`host -r`", "correct": false, "explanation": "`host` ist ein DNS-Abfragewerkzeug." }
|
||||
],
|
||||
"explanation": "Alte Werkzeuge: `route -n`, `netstat -rn`. Welche Route für ein Ziel gilt: `ip route get 198.51.100.7`.",
|
||||
"references": ["man 8 ip-route"]
|
||||
},
|
||||
{
|
||||
"id": "109.3-005",
|
||||
"objective": "109.3",
|
||||
"type": "multi",
|
||||
"difficulty": 2,
|
||||
"question": "Mit welchen Befehlen kann man prüfen, ob ein Server Verbindungen auf **TCP-Port 443** annimmt?",
|
||||
"options": [
|
||||
{ "id": "a", "text": "`nc -zv server.example.org 443`", "correct": true, "explanation": "`-z` baut nur die Verbindung auf, ohne Daten zu senden; `-v` meldet das Ergebnis." },
|
||||
{ "id": "b", "text": "`telnet server.example.org 443`", "correct": true, "explanation": "Kommt eine Verbindung zustande, nimmt der Port Verbindungen an." },
|
||||
{ "id": "c", "text": "`ping -p 443 server.example.org`", "correct": false, "explanation": "`-p` legt bei ping ein Füllmuster fest; ICMP kennt keine Ports." },
|
||||
{ "id": "d", "text": "`dig server.example.org 443`", "correct": false, "explanation": "`dig` stellt nur DNS-Anfragen." },
|
||||
{ "id": "e", "text": "`ip neigh server.example.org 443`", "correct": false, "explanation": "Zeigt den Neighbor-Cache und prüft keine Ports." }
|
||||
],
|
||||
"explanation": "Vorgehen bei Netzproblemen von unten nach oben: Link (`ip link`) → Adresse (`ip addr`) → Gateway (`ping`) → Route (`ip route`, `traceroute`) → DNS (`dig`) → Port (`nc`).",
|
||||
"references": ["man 1 nc"]
|
||||
},
|
||||
{
|
||||
"id": "109.3-006",
|
||||
"objective": "109.3",
|
||||
"type": "single",
|
||||
"difficulty": 2,
|
||||
"question": "`ping 198.51.100.7` funktioniert, `ping www.example.org` meldet jedoch „Name or service not known“. Was sollte man als Erstes prüfen?",
|
||||
"options": [
|
||||
{ "id": "a", "text": "Die Namensauflösung, z. B. `/etc/resolv.conf` bzw. `resolvectl status`", "correct": true, "explanation": "IP-Verbindung und Routing funktionieren; nur der Name lässt sich nicht auflösen." },
|
||||
{ "id": "b", "text": "Ob ein Standard-Gateway gesetzt ist", "correct": false, "explanation": "Der Ping an eine entfernte IP funktioniert – Routing ist also in Ordnung." },
|
||||
{ "id": "c", "text": "Ob die Netzwerkkarte einen Link hat", "correct": false, "explanation": "Ohne Link wäre auch der Ping an die IP gescheitert." },
|
||||
{ "id": "d", "text": "Ob eine Firewall ICMP blockiert", "correct": false, "explanation": "ICMP kommt durch, wie der erste Ping zeigt." },
|
||||
{ "id": "e", "text": "Ob die MTU zu groß ist", "correct": false, "explanation": "MTU-Probleme zeigen sich nicht als Fehler bei der Namensauflösung." }
|
||||
],
|
||||
"explanation": "DNS gezielt testen: `dig www.example.org`, `host www.example.org`, `getent hosts www.example.org`.",
|
||||
"references": ["man 5 resolv.conf"]
|
||||
},
|
||||
{
|
||||
"id": "109.4-001",
|
||||
"objective": "109.4",
|
||||
"type": "single",
|
||||
"difficulty": 2,
|
||||
"question": "Welche Datei legt fest, in welcher Reihenfolge Quellen wie `files` (also `/etc/hosts`) und `dns` zur Auflösung von Hostnamen befragt werden?",
|
||||
"options": [
|
||||
{ "id": "a", "text": "`/etc/nsswitch.conf`", "correct": true, "explanation": "Zeile z. B. `hosts: files dns`." },
|
||||
{ "id": "b", "text": "`/etc/resolv.conf`", "correct": false, "explanation": "Enthält die DNS-Server und Suchdomänen, nicht die Reihenfolge der Quellen." },
|
||||
{ "id": "c", "text": "`/etc/hosts`", "correct": false, "explanation": "Ist selbst eine Quelle (`files`)." },
|
||||
{ "id": "d", "text": "`/etc/hostname`", "correct": false, "explanation": "Enthält den eigenen Hostnamen." },
|
||||
{ "id": "e", "text": "`/etc/systemd/resolved.conf`", "correct": false, "explanation": "Konfiguriert den Dienst systemd-resolved, nicht die NSS-Reihenfolge." }
|
||||
],
|
||||
"explanation": "NSS (Name Service Switch) regelt auch `passwd`, `group` usw.; `getent` fragt genau diese Kette ab.",
|
||||
"references": ["man 5 nsswitch.conf"]
|
||||
},
|
||||
{
|
||||
"id": "109.4-002",
|
||||
"objective": "109.4",
|
||||
"type": "fill",
|
||||
"difficulty": 1,
|
||||
"question": "Mit welchem Schlüsselwort trägt man in `/etc/resolv.conf` einen DNS-Server ein?",
|
||||
"answers": ["nameserver"],
|
||||
"explanation": "Beispiel: `nameserver 192.0.2.53`. Weitere Schlüsselwörter: `search`, `domain`, `options`. Bei systemd-resolved verweist die Datei oft auf den Stub `127.0.0.53`.",
|
||||
"references": ["man 5 resolv.conf"]
|
||||
},
|
||||
{
|
||||
"id": "109.4-003",
|
||||
"objective": "109.4",
|
||||
"type": "multi",
|
||||
"difficulty": 2,
|
||||
"question": "Welche Programme stellen **gezielt DNS-Anfragen** an einen Nameserver (ohne `/etc/hosts` zu berücksichtigen)?",
|
||||
"options": [
|
||||
{ "id": "a", "text": "`dig`", "correct": true, "explanation": "Ausführliche Abfragen, z. B. `dig @192.0.2.53 example.org MX`." },
|
||||
{ "id": "b", "text": "`host`", "correct": true, "explanation": "Kompakte Ausgabe, z. B. `host example.org`." },
|
||||
{ "id": "c", "text": "`nslookup`", "correct": true, "explanation": "Älteres, interaktiv nutzbares DNS-Werkzeug." },
|
||||
{ "id": "d", "text": "`getent hosts`", "correct": false, "explanation": "Fragt über NSS ab – also auch `/etc/hosts` gemäß `nsswitch.conf`." },
|
||||
{ "id": "e", "text": "`ip neigh`", "correct": false, "explanation": "Zeigt den ARP-/Neighbor-Cache." }
|
||||
],
|
||||
"explanation": "Ein Name ist per `dig` auflösbar, Programme finden ihn trotzdem nicht? Dann `nsswitch.conf` und `/etc/hosts` prüfen – und umgekehrt.",
|
||||
"references": ["man 1 dig", "man 1 host"]
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,237 @@
|
||||
{
|
||||
"$schema": "../schema/questions.schema.json",
|
||||
"format": "lpic-sim-questions",
|
||||
"meta": {
|
||||
"file": "questions_110.json",
|
||||
"brief": "Fragen 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 (29.10.2026)"
|
||||
},
|
||||
"exam": "lpic1-102",
|
||||
"questions": [
|
||||
{
|
||||
"id": "110.1-001",
|
||||
"objective": "110.1",
|
||||
"type": "single",
|
||||
"difficulty": 2,
|
||||
"question": "Welcher Befehl findet alle Dateien, bei denen das **SUID-Bit** gesetzt ist?",
|
||||
"options": [
|
||||
{ "id": "a", "text": "`find / -perm -4000 -type f`", "correct": true, "explanation": "`-perm -4000`: mindestens das SUID-Bit gesetzt, andere Bits beliebig." },
|
||||
{ "id": "b", "text": "`find / -perm 4000 -type f`", "correct": false, "explanation": "Ohne `-` müssen die Rechte **exakt** 4000 sein – praktisch keine Datei." },
|
||||
{ "id": "c", "text": "`find / -perm -2000 -type f`", "correct": false, "explanation": "2000 ist das SGID-Bit." },
|
||||
{ "id": "d", "text": "`find / -type s`", "correct": false, "explanation": "`-type s` findet Sockets." },
|
||||
{ "id": "e", "text": "`find / -user root -type f`", "correct": false, "explanation": "Findet alle Dateien von root, unabhängig von SUID." }
|
||||
],
|
||||
"explanation": "`-perm /6000` findet Dateien mit SUID **oder** SGID. Unerwartete SUID-Programme sind ein Sicherheitsrisiko.",
|
||||
"references": ["man 1 find"]
|
||||
},
|
||||
{
|
||||
"id": "110.1-002",
|
||||
"objective": "110.1",
|
||||
"type": "single",
|
||||
"difficulty": 1,
|
||||
"question": "Wie bearbeitet man die sudo-Konfiguration `/etc/sudoers` sicher?",
|
||||
"options": [
|
||||
{ "id": "a", "text": "Mit `visudo`", "correct": true, "explanation": "`visudo` sperrt die Datei und prüft die Syntax vor dem Speichern; ein Fehler könnte sonst sudo unbenutzbar machen." },
|
||||
{ "id": "b", "text": "Direkt mit `vi /etc/sudoers`", "correct": false, "explanation": "Keine Syntaxprüfung – ein Tippfehler kann den Zugriff auf sudo sperren." },
|
||||
{ "id": "c", "text": "Mit `sudo -l`", "correct": false, "explanation": "`sudo -l` zeigt nur die erlaubten Befehle des Benutzers." },
|
||||
{ "id": "d", "text": "Mit `chmod 777 /etc/sudoers` und einem Editor", "correct": false, "explanation": "sudo verweigert den Dienst bei falschen Rechten; zudem wäre das ein Sicherheitsloch." },
|
||||
{ "id": "e", "text": "Mit `su -c sudoers`", "correct": false, "explanation": "Führt einen Befehl `sudoers` als root aus – den es nicht gibt." }
|
||||
],
|
||||
"explanation": "Ergänzungen besser als eigene Dateien unter `/etc/sudoers.d/` (`visudo -f /etc/sudoers.d/team`). Beispielzeile: `%admin ALL=(ALL) ALL`.",
|
||||
"references": ["man 8 visudo", "man 5 sudoers"]
|
||||
},
|
||||
{
|
||||
"id": "110.1-003",
|
||||
"objective": "110.1",
|
||||
"type": "fill",
|
||||
"difficulty": 1,
|
||||
"question": "Welcher Befehl (nur der Name) zeigt die Liste der letzten Anmeldungen und Neustarts aus `/var/log/wtmp`?",
|
||||
"answers": ["last"],
|
||||
"explanation": "`last` liest `wtmp`, `lastb` die fehlgeschlagenen Anmeldungen aus `btmp`. Aktuell angemeldete Benutzer zeigen `who` und `w`.",
|
||||
"references": ["man 1 last"]
|
||||
},
|
||||
{
|
||||
"id": "110.1-004",
|
||||
"objective": "110.1",
|
||||
"type": "multi",
|
||||
"difficulty": 2,
|
||||
"question": "Welche Aussagen treffen zu?",
|
||||
"options": [
|
||||
{ "id": "a", "text": "`ulimit -n` zeigt die maximale Anzahl offener Dateien für die aktuelle Shell.", "correct": true, "explanation": "`ulimit -a` zeigt alle Limits; dauerhaft per `/etc/security/limits.conf`." },
|
||||
{ "id": "b", "text": "`who` zeigt die aktuell angemeldeten Benutzer.", "correct": true, "explanation": "Liest `utmp`; `w` zeigt zusätzlich deren Aktivität." },
|
||||
{ "id": "c", "text": "`su -` übernimmt die Umgebung des aufrufenden Benutzers unverändert.", "correct": false, "explanation": "`su -` startet eine Login-Shell mit der Umgebung des Zielbenutzers." },
|
||||
{ "id": "d", "text": "`sudo -l` zeigt das Passwort von root an.", "correct": false, "explanation": "Es listet die per sudo erlaubten Befehle." },
|
||||
{ "id": "e", "text": "`chage -l anna` sperrt das Konto von `anna`.", "correct": false, "explanation": "`chage -l` zeigt nur die Passwort-Alterung an." }
|
||||
],
|
||||
"explanation": "Sicherheitsrelevante Befehle aus 110.1: `find`, `passwd`, `fuser`, `lsof`, `nmap`, `chage`, `netstat`, `sudo`, `su`, `usermod`, `ulimit`, `who`, `w`, `last`.",
|
||||
"references": ["help ulimit", "man 1 who"]
|
||||
},
|
||||
{
|
||||
"id": "110.2-001",
|
||||
"objective": "110.2",
|
||||
"type": "single",
|
||||
"difficulty": 1,
|
||||
"question": "Ein nicht benötigter Dienst soll sofort gestoppt werden und beim nächsten Start nicht mehr starten. Welcher Befehl leistet beides?",
|
||||
"options": [
|
||||
{ "id": "a", "text": "`systemctl disable --now dienst`", "correct": true, "explanation": "`disable` entfernt die Autostart-Verknüpfungen, `--now` stoppt zusätzlich sofort." },
|
||||
{ "id": "b", "text": "`systemctl stop dienst`", "correct": false, "explanation": "Stoppt nur; beim nächsten Start läuft der Dienst wieder." },
|
||||
{ "id": "c", "text": "`systemctl reload dienst`", "correct": false, "explanation": "Lässt den Dienst seine Konfiguration neu lesen." },
|
||||
{ "id": "d", "text": "`systemctl status dienst`", "correct": false, "explanation": "Zeigt nur den Zustand." },
|
||||
{ "id": "e", "text": "`systemctl isolate dienst`", "correct": false, "explanation": "`isolate` ist für Targets gedacht und beendet alle nicht zugehörigen Units." }
|
||||
],
|
||||
"explanation": "Noch strenger: `systemctl mask` verhindert auch den manuellen Start oder den Start als Abhängigkeit. Grundsatz: Was nicht läuft, kann nicht angegriffen werden.",
|
||||
"references": ["man 1 systemctl"]
|
||||
},
|
||||
{
|
||||
"id": "110.2-002",
|
||||
"objective": "110.2",
|
||||
"type": "single",
|
||||
"difficulty": 2,
|
||||
"question": "Was bedeutet ein `!` am Anfang des Passwortfelds eines Eintrags in `/etc/shadow`?",
|
||||
"options": [
|
||||
{ "id": "a", "text": "Das Passwort ist gesperrt; eine Anmeldung per Passwort ist nicht möglich.", "correct": true, "explanation": "Gesetzt z. B. durch `passwd -l` oder `usermod -L`; der ursprüngliche Hash bleibt dahinter erhalten." },
|
||||
{ "id": "b", "text": "Das Konto hat kein Passwort; Anmeldung ohne Passwort ist möglich.", "correct": false, "explanation": "Ein **leeres** Feld bedeutet kein Passwort." },
|
||||
{ "id": "c", "text": "Das Passwort muss bei der nächsten Anmeldung geändert werden.", "correct": false, "explanation": "Das wird über das Feld „letzte Änderung“ = 0 erreicht (`chage -d 0`)." },
|
||||
{ "id": "d", "text": "Der Hash wurde mit SHA-512 erzeugt.", "correct": false, "explanation": "Das Verfahren erkennt man am Präfix, z. B. `$6$` für SHA-512 oder `$y$` für yescrypt." },
|
||||
{ "id": "e", "text": "Der Benutzer ist Mitglied der Gruppe `wheel`.", "correct": false, "explanation": "Gruppenmitgliedschaften stehen in `/etc/group`." }
|
||||
],
|
||||
"explanation": "`*` oder `!` allein werden für Systemkonten verwendet, die sich nie mit Passwort anmelden sollen.",
|
||||
"references": ["man 5 shadow"]
|
||||
},
|
||||
{
|
||||
"id": "110.2-003",
|
||||
"objective": "110.2",
|
||||
"type": "single",
|
||||
"difficulty": 2,
|
||||
"question": "`/etc/hosts.allow` ist leer, `/etc/hosts.deny` enthält `ALL: ALL`. Was bewirkt das bei Diensten, die TCP-Wrapper (libwrap) verwenden?",
|
||||
"options": [
|
||||
{ "id": "a", "text": "Alle Zugriffe auf diese Dienste werden von allen Hosts abgewiesen.", "correct": true, "explanation": "Zuerst wird `hosts.allow` geprüft (kein Treffer), dann `hosts.deny`: Alle Dienste, alle Clients → abgelehnt." },
|
||||
{ "id": "b", "text": "Die Kernel-Firewall blockiert sämtlichen Netzwerkverkehr.", "correct": false, "explanation": "TCP-Wrapper wirken nur bei Programmen, die libwrap nutzen, nicht im Kernel." },
|
||||
{ "id": "c", "text": "Alle lokalen Anmeldungen an der Konsole werden verhindert.", "correct": false, "explanation": "Konsolenanmeldungen werden von TCP-Wrappern nicht erfasst." },
|
||||
{ "id": "d", "text": "Alle Zugriffe werden erlaubt, weil `hosts.deny` zuerst gelesen wird.", "correct": false, "explanation": "Die Reihenfolge ist `hosts.allow`, dann `hosts.deny`." },
|
||||
{ "id": "e", "text": "Nichts, weil die Syntax ungültig ist.", "correct": false, "explanation": "`dienst: client` mit `ALL` als Platzhalter ist gültig." }
|
||||
],
|
||||
"explanation": "Typisches Muster: `hosts.deny` = `ALL: ALL`, Ausnahmen in `hosts.allow`, z. B. `sshd: 192.0.2.`. Laut LPI sollen TCP-Wrapper künftig aus den Objectives entfallen; in 5.0 sind sie noch enthalten (Stand 29.10.2026).",
|
||||
"references": ["man 5 hosts_access"]
|
||||
},
|
||||
{
|
||||
"id": "110.2-004",
|
||||
"objective": "110.2",
|
||||
"type": "multi",
|
||||
"difficulty": 1,
|
||||
"question": "Mit welchen Befehlen stellt man fest, welche Netzwerkdienste auf einem Rechner erreichbar sind?",
|
||||
"options": [
|
||||
{ "id": "a", "text": "`ss -tuln`", "correct": true, "explanation": "Lokale Sicht: alle lauschenden TCP-/UDP-Sockets." },
|
||||
{ "id": "b", "text": "`nmap localhost`", "correct": true, "explanation": "Portscan von außen bzw. lokal; nur gegen eigene Systeme oder mit Erlaubnis." },
|
||||
{ "id": "c", "text": "`systemctl list-timers`", "correct": false, "explanation": "Listet systemd-Timer." },
|
||||
{ "id": "d", "text": "`ip addr`", "correct": false, "explanation": "Zeigt nur Adressen der Schnittstellen." },
|
||||
{ "id": "e", "text": "`lsmod`", "correct": false, "explanation": "Listet Kernelmodule." }
|
||||
],
|
||||
"explanation": "Weitere: `netstat -tuln`, `lsof -i`, `fuser`. Ziel: unnötige Dienste finden und abschalten.",
|
||||
"references": ["man 8 ss", "man 1 nmap"]
|
||||
},
|
||||
{
|
||||
"id": "110.2-005",
|
||||
"objective": "110.2",
|
||||
"type": "fill",
|
||||
"difficulty": 1,
|
||||
"question": "Welche Datei (vollständiger Pfad) verhindert, solange sie existiert, die Anmeldung aller Benutzer außer root? Ihr Inhalt wird abgewiesenen Benutzern angezeigt.",
|
||||
"answers": ["/etc/nologin"],
|
||||
"explanation": "Nützlich bei Wartungsarbeiten; `shutdown` legt sie kurz vor dem Herunterfahren automatisch an (bei systemd unter `/run/nologin`).",
|
||||
"references": ["man 5 nologin"]
|
||||
},
|
||||
{
|
||||
"id": "110.3-001",
|
||||
"objective": "110.3",
|
||||
"type": "single",
|
||||
"difficulty": 1,
|
||||
"question": "Mit welchem Befehl erzeugt ein Benutzer ein neues SSH-Schlüsselpaar vom Typ Ed25519?",
|
||||
"options": [
|
||||
{ "id": "a", "text": "`ssh-keygen -t ed25519`", "correct": true, "explanation": "Erzeugt `~/.ssh/id_ed25519` (privat) und `~/.ssh/id_ed25519.pub` (öffentlich)." },
|
||||
{ "id": "b", "text": "`ssh-add -t ed25519`", "correct": false, "explanation": "`ssh-add` lädt Schlüssel in den ssh-agent (`-t` = Lebensdauer)." },
|
||||
{ "id": "c", "text": "`ssh-copy-id -t ed25519`", "correct": false, "explanation": "`ssh-copy-id` überträgt einen öffentlichen Schlüssel auf einen Server." },
|
||||
{ "id": "d", "text": "`ssh-agent ed25519`", "correct": false, "explanation": "`ssh-agent` hält entschlüsselte Schlüssel im Speicher, erzeugt aber keine." },
|
||||
{ "id": "e", "text": "`gpg --gen-key --ssh`", "correct": false, "explanation": "`gpg` erzeugt OpenPGP-Schlüssel; die Option `--ssh` gibt es so nicht." }
|
||||
],
|
||||
"explanation": "Weitere Typen: `rsa` (mit `-b 4096`), `ecdsa`. Eine Passphrase schützt den privaten Schlüssel.",
|
||||
"references": ["man 1 ssh-keygen"]
|
||||
},
|
||||
{
|
||||
"id": "110.3-002",
|
||||
"objective": "110.3",
|
||||
"type": "fill",
|
||||
"difficulty": 1,
|
||||
"question": "In welche Datei im Home-Verzeichnis des Zielbenutzers auf dem **Server** gehört der öffentliche Schlüssel, damit eine Anmeldung per Schlüssel möglich ist? (Pfad relativ zum Home oder mit `~`)",
|
||||
"answers": ["~/.ssh/authorized_keys", ".ssh/authorized_keys", "authorized_keys"],
|
||||
"explanation": "Ein Schlüssel pro Zeile; `ssh-copy-id benutzer@server` trägt ihn ein. Zu offene Rechte auf `~/.ssh` (700) oder die Datei (600) lassen sshd den Schlüssel ignorieren.",
|
||||
"references": ["man 8 sshd (Abschnitt AUTHORIZED_KEYS FILE FORMAT)"]
|
||||
},
|
||||
{
|
||||
"id": "110.3-003",
|
||||
"objective": "110.3",
|
||||
"type": "single",
|
||||
"difficulty": 1,
|
||||
"question": "Wozu dient die Datei `~/.ssh/known_hosts` auf dem Client?",
|
||||
"options": [
|
||||
{ "id": "a", "text": "Sie speichert die Host-Schlüssel bereits besuchter Server, um sie bei späteren Verbindungen zu prüfen.", "correct": true, "explanation": "Ändert sich der Host-Schlüssel, warnt ssh vor einem möglichen Man-in-the-Middle-Angriff." },
|
||||
{ "id": "b", "text": "Sie enthält die öffentlichen Schlüssel von Benutzern, die sich anmelden dürfen.", "correct": false, "explanation": "Das ist `~/.ssh/authorized_keys` auf dem Server." },
|
||||
{ "id": "c", "text": "Sie enthält den privaten Schlüssel des Benutzers.", "correct": false, "explanation": "Private Schlüssel liegen z. B. in `~/.ssh/id_ed25519`." },
|
||||
{ "id": "d", "text": "Sie listet die Hosts, die per SSH gesperrt sind.", "correct": false, "explanation": "Eine Sperrliste ist das nicht." },
|
||||
{ "id": "e", "text": "Sie enthält die Client-Einstellungen wie Benutzername und Port je Host.", "correct": false, "explanation": "Das ist `~/.ssh/config`." }
|
||||
],
|
||||
"explanation": "Einen veralteten Eintrag entfernt man mit `ssh-keygen -R host`. Die Host-Schlüssel des Servers liegen in `/etc/ssh/ssh_host_*`.",
|
||||
"references": ["man 1 ssh (Abschnitt VERIFYING HOST KEYS)"]
|
||||
},
|
||||
{
|
||||
"id": "110.3-004",
|
||||
"objective": "110.3",
|
||||
"type": "single",
|
||||
"difficulty": 2,
|
||||
"question": "Die Datei `vertrag.pdf` soll mit GnuPG so verschlüsselt werden, dass nur `anna@example.org` sie entschlüsseln kann. Welcher Befehl ist korrekt?",
|
||||
"options": [
|
||||
{ "id": "a", "text": "`gpg --encrypt --recipient anna@example.org vertrag.pdf`", "correct": true, "explanation": "Verschlüsselt mit Annas öffentlichem Schlüssel; Ergebnis `vertrag.pdf.gpg`." },
|
||||
{ "id": "b", "text": "`gpg --sign --recipient anna@example.org vertrag.pdf`", "correct": false, "explanation": "`--sign` signiert mit dem eigenen privaten Schlüssel; verschlüsselt wird nicht." },
|
||||
{ "id": "c", "text": "`gpg --export anna@example.org vertrag.pdf`", "correct": false, "explanation": "`--export` gibt öffentliche Schlüssel aus." },
|
||||
{ "id": "d", "text": "`gpg --decrypt --recipient anna@example.org vertrag.pdf`", "correct": false, "explanation": "`--decrypt` entschlüsselt." },
|
||||
{ "id": "e", "text": "`gpg --gen-key anna@example.org vertrag.pdf`", "correct": false, "explanation": "`--gen-key` erzeugt ein neues eigenes Schlüsselpaar." }
|
||||
],
|
||||
"explanation": "Dazu muss Annas öffentlicher Schlüssel importiert sein (`gpg --import`). Signatur prüfen: `gpg --verify`. Schlüssel widerrufen: Widerrufszertifikat (`--gen-revoke`).",
|
||||
"references": ["man 1 gpg"]
|
||||
},
|
||||
{
|
||||
"id": "110.3-005",
|
||||
"objective": "110.3",
|
||||
"type": "multi",
|
||||
"difficulty": 2,
|
||||
"question": "Welche Aussagen zu OpenSSH treffen zu?",
|
||||
"options": [
|
||||
{ "id": "a", "text": "Mit `ssh -L 8080:localhost:80 benutzer@server` wird der lokale Port 8080 über SSH an Port 80 des Servers weitergeleitet.", "correct": true, "explanation": "Lokales Port-Forwarding; „localhost“ ist aus Sicht des Servers gemeint." },
|
||||
{ "id": "b", "text": "`ssh-agent` hält entschlüsselte private Schlüssel im Speicher, sodass die Passphrase nur einmal eingegeben werden muss.", "correct": true, "explanation": "Schlüssel werden mit `ssh-add` in den Agent geladen." },
|
||||
{ "id": "c", "text": "Ein privater Schlüssel sollte die Rechte 644 haben.", "correct": false, "explanation": "Private Schlüssel nur für den Eigentümer lesbar (600); sonst verweigert ssh sie." },
|
||||
{ "id": "d", "text": "`ssh -R` startet auf dem Server eine grafische X11-Sitzung.", "correct": false, "explanation": "`-R` richtet Remote-Port-Forwarding ein; X11-Weiterleitung ist `-X`/`-Y`." },
|
||||
{ "id": "e", "text": "Die Server-Konfiguration steht in `~/.ssh/config`.", "correct": false, "explanation": "Server: `/etc/ssh/sshd_config`; `~/.ssh/config` ist Client-Konfiguration." }
|
||||
],
|
||||
"explanation": "Härtung in `sshd_config`: z. B. `PermitRootLogin no`, `PasswordAuthentication no`.",
|
||||
"references": ["man 1 ssh", "man 5 sshd_config"]
|
||||
},
|
||||
{
|
||||
"id": "110.3-006",
|
||||
"objective": "110.3",
|
||||
"type": "single",
|
||||
"difficulty": 1,
|
||||
"question": "Nach `ssh-keygen -t ed25519` mit Standardnamen: Welche Datei ist der **private** Schlüssel?",
|
||||
"options": [
|
||||
{ "id": "a", "text": "`~/.ssh/id_ed25519`", "correct": true, "explanation": "Die Datei ohne Endung ist der private Schlüssel; sie darf das System nie verlassen." },
|
||||
{ "id": "b", "text": "`~/.ssh/id_ed25519.pub`", "correct": false, "explanation": "`.pub` ist der öffentliche Schlüssel, der auf Server verteilt wird." },
|
||||
{ "id": "c", "text": "`~/.ssh/authorized_keys`", "correct": false, "explanation": "Liste erlaubter öffentlicher Schlüssel (serverseitig)." },
|
||||
{ "id": "d", "text": "`~/.ssh/known_hosts`", "correct": false, "explanation": "Host-Schlüssel bekannter Server." },
|
||||
{ "id": "e", "text": "`/etc/ssh/ssh_host_ed25519_key`", "correct": false, "explanation": "Privater **Host**-Schlüssel des SSH-Servers, nicht des Benutzers." }
|
||||
],
|
||||
"explanation": "Öffentliche und private Schlüssel gibt es auch beim Server (Host-Schlüssel). Benutzer- und Host-Schlüssel nicht verwechseln.",
|
||||
"references": ["man 1 ssh-keygen"]
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
{
|
||||
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
||||
"$id": "questions.schema.json",
|
||||
"title": "LPIC-Simulator: Fragendatei",
|
||||
"description": "Fragenpaket für eine Prüfung. Datei-Header in 'meta' (Regel headers.md). Fachliche Regeln (genau 5 Optionen, Erläuterung je Option) prüft zusätzlich tools/build_bank.py.",
|
||||
"type": "object",
|
||||
"required": ["format", "exam", "questions"],
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"$schema": { "type": "string" },
|
||||
"format": { "const": "lpic-sim-questions" },
|
||||
"meta": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"file": { "type": "string" },
|
||||
"brief": { "type": "string" },
|
||||
"author": { "type": "string" },
|
||||
"owner": { "type": "string" },
|
||||
"assist": { "type": "string" },
|
||||
"version": { "type": "string" }
|
||||
}
|
||||
},
|
||||
"exam": { "type": "string", "description": "id der Prüfung aus exam.json, z. B. lpic1-101", "pattern": "^[a-z0-9-]+$" },
|
||||
"questions": { "type": "array", "items": { "$ref": "#/$defs/question" } }
|
||||
},
|
||||
"$defs": {
|
||||
"question": {
|
||||
"type": "object",
|
||||
"required": ["id", "objective", "type", "question", "explanation"],
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"id": { "type": "string", "pattern": "^[0-9]{3}\\.[0-9]+-[0-9]{3}$", "description": "<objective>-<laufende Nr.>, z. B. 103.1-004" },
|
||||
"objective": { "type": "string", "pattern": "^[0-9]{3}\\.[0-9]+$" },
|
||||
"type": { "enum": ["single", "multi", "fill"], "description": "single: genau 1 richtig · multi: 2–4 richtig (Anzahl wird angezeigt) · fill: Lückentext" },
|
||||
"lang": { "type": "string", "default": "de" },
|
||||
"difficulty": { "type": "integer", "minimum": 1, "maximum": 3 },
|
||||
"question": { "type": "string", "description": "Fragetext; `Inline-Code` in Backticks, **fett** möglich" },
|
||||
"code": { "type": "string", "description": "optionaler mehrzeiliger Block (Ausgabe, Datei, Befehl)" },
|
||||
"options": {
|
||||
"type": "array",
|
||||
"minItems": 5,
|
||||
"maxItems": 5,
|
||||
"items": {
|
||||
"type": "object",
|
||||
"required": ["id", "text", "correct", "explanation"],
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"id": { "enum": ["a", "b", "c", "d", "e"] },
|
||||
"text": { "type": "string" },
|
||||
"correct": { "type": "boolean" },
|
||||
"explanation": { "type": "string", "description": "Warum diese Option richtig bzw. falsch ist" }
|
||||
}
|
||||
}
|
||||
},
|
||||
"answers": { "type": "array", "minItems": 1, "items": { "type": "string" }, "description": "fill: akzeptierte Antworten (erste = Musterlösung)" },
|
||||
"case_sensitive": { "type": "boolean", "default": true },
|
||||
"explanation": { "type": "string", "description": "Gesamterläuterung zur Frage" },
|
||||
"references": { "type": "array", "items": { "type": "string" }, "description": "z. B. man 8 modprobe" },
|
||||
"review": {
|
||||
"type": "object",
|
||||
"description": "Prüfvermerk. Fehlt er, gilt pending. rejected wird nie in die Bank übernommen, mit --approved-only nur approved.",
|
||||
"required": ["status"],
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"status": { "enum": ["pending", "approved", "rejected"] },
|
||||
"by": { "type": "string", "description": "Prüfer (Name oder Rolle)" },
|
||||
"date": { "type": "string", "pattern": "^\\d{4}-\\d{2}-\\d{2}$" },
|
||||
"note": { "type": "string", "description": "Begründung, v. a. bei rejected" }
|
||||
}
|
||||
}
|
||||
},
|
||||
"allOf": [
|
||||
{ "if": { "properties": { "type": { "const": "fill" } } }, "then": { "required": ["answers"] }, "else": { "required": ["options"] } }
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user