LPIC-2 201-450 study materials
LPIC-2 201-450 study resources

LPIC-2 201-450 common mistakes

LPIC-2 201-450 · Understand the traps and how to avoid them.

Mistake 1

Seeing "No space left on device" while `df -h` reports free blocks, then spending the session hunting for a large file instead of checking inode usage with `df -i`.

Block usage and inode usage are independent counters. ext4 and XFS allocate a fixed inode pool when the filesystem is created, so a mount holding millions of tiny files, session files, or mail queue entries can run out of inodes with plenty of space left. Candidates check df -h out of habit and never look at the inode column.

What to do instead

Always run df -i next to df -h. Locate the offenders with find /var -xdev -printf '%h\n' | sort | uniq -c | sort -n | tail. Remember the inode count is fixed at mkfs time (-i bytes-per-inode or -T usage-type), so remediation means deleting files, moving them to another filesystem, or recreating the filesystem with a different inode ratio.

Mistake 2

Blacklisting a module with a bare `blacklist foo` line in /etc/modprobe.d/foo.conf, rebooting, and finding the module loaded again, or copying a .ko into /lib/modules/$(uname -r) and calling modprobe without running depmod first.

A bare blacklist line only suppresses alias-driven autoloading; the module still loads if another module depends on it, if it was built into the kernel, or if it is pulled from the initramfs before /etc/modprobe.d is even read. Newly copied modules are invisible to modprobe until the dependency database is rebuilt.

What to do instead

Use install foo /bin/true for a hard block and check dependencies with modinfo foo and lsmod. After adding or removing modules, run depmod -a and rebuild the initramfs (update-initramfs -u on Debian, dracut -f on RHEL). Test without loading with modprobe -n -v foo and confirm the source of the load in dmesg.

Mistake 3

Setting a kernel tunable with `sysctl -w net.ipv4.ip_forward=1`, verifying it works, and assuming it survives a reboot; or dropping a line into /etc/sysctl.conf on a system whose configuration lives in /etc/sysctl.d/.

sysctl -w changes only the running kernel, and sysctl -p with no argument reads one specific file. Load order across /usr/lib/sysctl.d, /run/sysctl.d and /etc/sysctl.d is easy to misjudge, so a value can be set at boot and then overwritten by a later drop-in with the same key.

What to do instead

Persist settings in /etc/sysctl.d/99-local.conf and apply with sysctl --system. Confirm the effective value with sysctl net.ipv4.ip_forward, and check whether a vendor drop-in sets the same key with grep -r ip_forward /usr/lib/sysctl.d /etc/sysctl.d.

Mistake 4

Editing the kernel command line directly in /boot/grub/grub.cfg, or editing /etc/default/grub and rebooting without regenerating the configuration.

grub.cfg is generated output: kernel package updates and grub-mkconfig rewrite it, and BIOS versus UEFI systems use different generator paths. Candidates remember where the setting lives but not the regeneration step, so the change silently disappears or never takes effect.

What to do instead

Edit GRUB_CMDLINE_LINUX_DEFAULT in /etc/default/grub or add a script under /etc/grub.d/, then regenerate: grub-mkconfig -o /boot/grub/grub.cfg (update-grub on Debian/Ubuntu; grub2-mkconfig -o /boot/grub2/grub.cfg on RHEL). After reboot, verify the live command line with cat /proc/cmdline.

Mistake 5

Running `systemctl start sshd` and expecting the service after reboot, or changing ExecStart by editing /usr/lib/systemd/system/foo.service and losing the edit at the next package update.

start and enable are separate operations: enable creates the symlink in the target's .wants directory and start only affects the running system. /usr/lib/systemd/system is vendor territory, while /etc/systemd/system holds local overrides, so in-place edits to vendor units are both non-persistent and invisible to systemctl status output.

What to do instead

Use systemctl enable --now foo and verify with systemctl is-enabled foo. Change behaviour with systemctl edit foo, which creates a drop-in under /etc/systemd/system/foo.service.d/, or copy the unit to /etc/systemd/system/ and run systemctl daemon-reload. Check the boot target with systemctl get-default.

Mistake 6

Adding a secondary disk or network mount to /etc/fstab, testing it only with `mount /mnt/x`, and rebooting into emergency mode; or expecting the running systemd mount units to pick up an fstab edit.

fstab is read for every entry at boot; a typo, a device that is not present, or a missing nofail makes local-fs.target fail and drops the system to the emergency shell. systemd generates mount units at boot time, so manual fstab changes are not live.

What to do instead

Test with mount -a and validate with findmnt --verify before rebooting. Reference devices by UUID= or LABEL= rather than /dev/sdX, add nofail (optionally x-systemd.device-timeout=10s) for non-critical and network mounts, and run systemctl daemon-reload after editing fstab.

Mistake 7

Growing a volume with `lvextend -L +10G /dev/vg/data` and reporting it done while `df -h` still shows the old size, or running the filesystem resize tool before the logical volume has been extended.

The logical volume and the filesystem inside it are separate layers: lvextend only changes the block device. Tools also differ by filesystem: XFS cannot shrink and must be grown while mounted, while ext4 can be grown online but not shrunk.

What to do instead

Use lvextend -r -L +10G /dev/vg/data so fsadm invokes the correct resize tool, or run lvextend and then resize2fs /dev/vg/data for ext4 or xfs_growfs /mountpoint for XFS on the mounted filesystem. Order matters: extend the LV first, then the filesystem. Verify with lvs and df -h.

Mistake 8

Creating a RAID array with mdadm, confirming it in /proc/mdstat, and rebooting, only to find the array degraded, absent, or assembled under a different device name.

The initramfs was built before the array existed and therefore contains no mdadm.conf or assembly details, so the kernel cannot assemble the array by UUID. A stale /etc/mdadm/mdadm.conf on Debian or /etc/mdadm.conf on RHEL leaves the array unmanaged at boot.

What to do instead

Regenerate the metadata with mdadm --detail --scan >> /etc/mdadm/mdadm.conf (remove duplicate lines first), then rebuild the initramfs with update-initramfs -u or dracut -f. After reboot, confirm assembly with mdadm --detail /dev/md0 and mdadm --assemble --scan --verbose.

Mistake 9

Editing /etc/network/interfaces to set a static address on a host where NetworkManager owns the interface (or the reverse), then wondering why the address reverts; or adding a route with `ip route add` and expecting it after reboot.

Current enterprise distributions usually have NetworkManager or systemd-networkd managing interfaces, and they ignore ifupdown-style files entirely. Commands from iproute2 change only the running state and are never written to any configuration file.

What to do instead

Identify the owner first with nmcli device status, networkctl status, or systemctl status networking. Configure through that owner, e.g. nmcli con mod <name> ipv4.addresses 192.0.2.10/24, nmcli con mod <name> ipv4.gateway 192.0.2.1, nmcli con mod <name> +ipv4.routes "198.51.100.0/24 192.0.2.1", then nmcli con up <name>. Verify with ip addr and ip route, and again after a reboot.

Mistake 10

Running `rsync -av --delete /data /backup/data` instead of `/data/`, and wiping or nesting the backup without checking the trailing slash first.

A trailing slash on the source means "the contents of this directory"; without it the directory itself is copied inside the destination. Combined with --delete, that misunderstanding removes files from the destination or creates a nested /backup/data/data tree.

What to do instead

Decide deliberately: rsync -aHX --delete /data/ /backup/data/ mirrors the contents. Always dry-run first with rsync -avn --itemize-changes, add --one-file-system when the source has separate mounts, and use -A -X when ACLs and extended attributes must be preserved for system backups.