LPIC-2 command cheat sheet
The commands 201-450 and 202-450 ask for, grouped by LPI topic number. Storage and kernel work is captured on a real spare disk and real modules; the DNS rows are captured from a client that runs no name server, which is the only way to know a service actually answers.
- Debian familyUbuntu 26.04 LTS - kernel 7.0.0-30-generic, systemd 259
- RPM familyAlmaLinux 10.2 - kernel 6.12.0-211.7.3.el10_2, systemd 257
- Shellzsh 5.9 login shell on both - bash 5.3.9 (Ubuntu) / 5.2.26 (AlmaLinux)
- Block devicesone 50 GB disk - RAID and LVM work runs on loop devices
- Commands24
Topic 201 - Linux kernel
-
lsmodLoaded modules. The third column is a reference count - non-zero means it cannot be unloaded until its users go first.
bash Example session lsmod | head -6; echo "---"; lsmod | wc -l; echo "modules loaded (plus one header line)"Module Size Used byqrtr 53248 2nfnetlink 20480 1cfg80211 1536000 0binfmt_misc 24576 1intel_rapl_msr 20480 0---49modules loaded (plus one header line) -
modinfo <mod> · modinfo -p <mod>Reads the module file on disk without loading it. `-p` lists the parameters it accepts, which is the fastest answer to "what can I tune".
bash Example session modinfo dummy | grep -E '^(filename|description|license|depends|vermagic)'filename: /lib/modules/7.0.0-30-generic/kernel/drivers/net/dummy.ko.zstdescription: Dummy netdevice driver which discards all packets sent to itlicense: GPLdepends:vermagic: 7.0.0-30-generic SMP preempt mod_unload modversions -
modprobe <mod> <param>=<value>Loads the module AND its dependencies. `insmod` takes a path and resolves nothing, which is why it fails on anything with a dependency.
bash Example session sudo modprobe dummy numdummies=2 && lsmod | grep '^dummy'; echo "--- loaded"dummy 16384 0--- loaded -
modinfo -F depends <mod> · depmod -aDependencies come from `modules.dep`, which `depmod` writes. Add a module by hand and modprobe will not find it until you rerun depmod.
bash Example session modinfo -F depends dummy; echo "(empty = no dependencies)"; echo "---"; modinfo -F depends bridge (empty = no dependencies)---stp,llc -
modprobe -r <mod>Unloads it and anything it pulled in. Interfaces or devices the module created disappear with it.
bash Example session sudo modprobe -r dummy && lsmod | grep -c '^dummy '; echo "0 means it is gone"00 means it is gone -
sysctl <name> == cat /proc/sys/<name with / for .>The dots are directory separators. `net.ipv4.ip_forward` IS `/proc/sys/net/ipv4/ip_forward`.
bash Example session sysctl net.ipv4.ip_forward; echo "---"; cat /proc/sys/net/ipv4/ip_forward; echo "--- the same value, two spellings"net.ipv4.ip_forward = 0---0--- the same value, two spellings -
sysctl -w <name>=<value> (runtime only)Changes the running kernel and nothing on disk. Lasts until reboot - which is why a setting "keeps resetting itself".
bash Example session sudo sysctl -w net.ipv4.ip_forward=1 | tail -1; cat /proc/sys/net/ipv4/ip_forwardnet.ipv4.ip_forward = 11 -
/etc/sysctl.d/*.conf then sysctl --systemThe persistent half. Writing the file alone changes nothing until reboot; `--system` re-reads them all now.
bash Example session ls /etc/sysctl.d/ 2>/dev/null | head -4; echo "--- where a persistent setting belongs"README.sysctl--- where a persistent setting belongs
Topics 203/204 - Filesystems and advanced storage
-
lsblk -o NAME,SIZE,TYPE,FSTYPE,MOUNTPOINT <disk>Prove a disk is spare before destroying it: no partitions, no filesystem, no mountpoint - and check root is elsewhere.
bash Example session lsblk -o NAME,SIZE,TYPE,FSTYPE,MOUNTPOINT /dev/sdb; echo "--- partitions: $(lsblk -no NAME /dev/sdb | tail -n +2 | wc -l), filesystem: [$(lsblk -dno FSTYPE /dev/sdb)], mounted: [$(lsblk -no MOUNTPOINT /dev/sdb | tr -d ' \n')]"NAME SIZE TYPE FSTYPE MOUNTPOINTsdb 5G disk--- partitions: 0, filesystem: [], mounted: [] -
pvcreate <disk> · pvs · pvdisplayA bare PV reports `Allocatable NO` and `Total PE 0` - the extent size is decided by the volume group, so that is not an error.
bash Example session sudo pvcreate -f /dev/sdb && sudo pvs /dev/sdb Physical volume "/dev/sdb" successfully created. PV VG Fmt Attr PSize PFree /dev/sdb lvm2 --- 5.00g 5.00g -
vgcreate <vg> <pv> · vgdisplay <vg>The VG sets the extent size - 4 MiB by default. Every LV is a whole number of extents, which is why sizes round.
bash Example session sudo vgcreate lpic2vg /dev/sdb && sudo vgs lpic2vg Volume group "lpic2vg" successfully created VG #PV #LV #SN Attr VSize VFree lpic2vg 1 0 0 wz--n- <5.00g <5.00g -
lvcreate -n <lv> -L <size> <vg>Reachable at both `/dev/<vg>/<lv>` and `/dev/mapper/<vg>-<lv>`. `lvs` reports the first, `df` the second.
bash Example session sudo lvcreate -n data -L 2G lpic2vg && sudo lvs lpic2vg Logical volume "data" created. LV VG Attr LSize Pool Origin Data% Meta% Move Log Cpy%Sync Convert data lpic2vg -wi-a----- 2.00g -
lvextend -L +<size> <lv> (device only)Grows the block device. `df` still shows the OLD size - stopping here is the commonest LVM mistake.
bash Example session sudo lvextend -L +1G /dev/lpic2vg/data 2>&1 | tail -1; df -h /mnt/lpic2 | tail -1; echo "--- the volume grew, the filesystem has not yet" Logical volume lpic2vg/data successfully resized./dev/mapper/lpic2vg-data 2.0G 536K 1.8G 1% /mnt/lpic2--- the volume grew, the filesystem has not yet -
resize2fs <lv> (ext) · xfs_growfs <mountpoint> (XFS)The second half. `lvextend -r` does both at once. XFS takes the MOUNTPOINT, not the device, and cannot be shrunk at all.
bash Example session sudo resize2fs /dev/lpic2vg/data 2>&1 | tail -1; df -h /mnt/lpic2 | tail -1; echo "--- now the filesystem has caught up, still mounted throughout" /dev/mapper/lpic2vg-data 2.9G 536K 2.8G 1% /mnt/lpic2--- now the filesystem has caught up, still mounted throughout -
mdadm --create /dev/md0 --level=1 --raid-devices=2 --spare-devices=1 <devs>RAID 1 capacity equals ONE device - the mirrors buy redundancy, not space.
bash Example session sudo mdadm --create /dev/md0 --level=1 --raid-devices=2 --spare-devices=1 $(losetup -a | grep lpic2 | cut -d: -f1 | tr '\n' ' ') --run 2>&1 | tail -2mdadm: Defaulting to version 1.2 metadatamdadm: array /dev/md0 started. -
mdadm --fail <md> <dev> · mdadm --detail <md>The spare is promoted automatically and the array stays `clean`. Watch a real rebuild in /proc/mdstat.
bash Example session sudo mdadm --fail /dev/md0 $(losetup -a | grep lpic2 | head -1 | cut -d: -f1) 2>&1 | tail -1; sleep 3; sudo mdadm --detail /dev/md0 | grep -E 'State :|Failed Devices|Spare Devices' State : clean Failed Devices : 1 Spare Devices : 0
Topic 207 - Domain name server
-
named-checkconfValidate named.conf before restarting anything. Silence means valid - it reports problems and nothing else.
bash Example session sudo named-checkconf && echo "named-checkconf: no output means the syntax is valid, exit $?"named-checkconf: no output means the syntax is valid, exit 0 -
named-checkzone <zone> <file>Echoes the serial it loaded, so it doubles as a check that you remembered to increment it.
bash Example session sudo named-checkzone lpic2.lab /etc/bind/db.lpic2.labzone lpic2.lab/IN: loaded serial 2026082901OK -
named-checkzone (a failure)A bad record names the line and the reason, and the zone is `NOT LOADED`. Restarting with a broken zone keeps serving the OLD data instead.
bash Example session sudo cp /etc/bind/db.lpic2.lab /tmp/db.good && printf 'bad IN A not-an-address\n' | sudo tee -a /etc/bind/db.lpic2.lab >/dev/null && sudo named-checkzone lpic2.lab /etc/bind/db.lpic2.lab 2>&1 | tail -3; echo "--- exit $?"dns_rdata_fromtext: /etc/bind/db.lpic2.lab:13: near 'not-an-address': bad dotted quadzone lpic2.lab/IN: loading from master file /etc/bind/db.lpic2.lab failed: bad dotted quadzone lpic2.lab/IN: not loaded due to errors.--- exit 0 -
dig @<server> <name> +short (from a CLIENT)The only query worth trusting. From the server itself it proves the zone parsed and nothing about reachability.
bash Example session dig @192.168.0.78 ns1.lpic2.lab +short; echo "--- THIS is the test that matters"192.168.0.78--- THIS is the test that matters -
dig @<server> <cname> +shortA CNAME shows the whole chain - target name first, then its address.
bash Example session dig @192.168.0.78 www.lpic2.lab +short; echo "--- a CNAME resolves to its target and then to an address"web.lpic2.lab.192.168.0.79--- a CNAME resolves to its target and then to an address -
dig <name> → status: NXDOMAINThe name does not exist, authoritatively (`aa` flag). `+short` shows nothing AND exits 0, which is the trap.
bash Example session dig @192.168.0.78 nothing.lpic2.lab | grep -E 'status:|AUTHORITY SECTION' -A1 | head -4; echo "--- NXDOMAIN, with the SOA saying how long to cache that fact";; ->>HEADER<<- opcode: QUERY, status: NXDOMAIN, id: 29365;; flags: qr aa rd; QUERY: 1, ANSWER: 0, AUTHORITY: 1, ADDITIONAL: 1--;; AUTHORITY SECTION:--- NXDOMAIN, with the SOA saying how long to cache that fact -
dig <out-of-zone name> → status: REFUSEDNot a failure - a policy. `recursion no` means this server answers only for its own zones, which is what an authoritative server should do.
bash Example session dig @192.168.0.78 www.google.com | grep -E 'status:' | head -1; echo "--- REFUSED rather than a wrong answer";; ->>HEADER<<- opcode: QUERY, status: REFUSED, id: 47785--- REFUSED rather than a wrong answer -
communications error (nothing listening)A transport error, not a DNS status - no header, no flags. Distinguish it from a silent timeout, which usually means a firewall dropped the packet.
bash Example session dig @192.168.0.78 ns1.lpic2.lab +short 2>&1 | head -2; echo "--- nothing answers on .78 any more (exit $?)";; communications error to 192.168.0.78#53: connection refused;; communications error to 192.168.0.78#53: connection refused--- nothing answers on .78 any more (exit 0)
No command matches that search.