LFCS command cheat sheet
The commands an LFCS task actually needs, grouped by the five objective domains. Every output is from a real session - Ubuntu 26.04 where the exam is most likely to put you, RHEL 10 where the two families differ.
- Ubuntu26.04 LTS - kernel 7.0.0-30-generic, systemd 259
- AlmaLinux10.2 - kernel 6.12.0-211.7.3.el10_2, systemd 257
- Login shellzsh 5.9 on all three hosts
- LVM2.03.31 (Ubuntu) / 2.03.36 (AlmaLinux)
- nftables1.1.6 (Ubuntu) / 1.1.5 (AlmaLinux)
- Firewallufw 0.36.2 enabled but reporting inactive / firewalld active
- Network confignetplan + systemd-networkd / NetworkManager 1.56.0
- Commands32
Domain 1 - Essential Commands (20%)
-
stat -c '%A %a %U:%G %n' <file>Mode, owner and size in one line you choose the shape of. `ls -l` for reading, `stat -c` for scripting.
bash Example session cd ~/ess/files && stat -c '%A %a %h %U:%G %s %y %n' report.txt logs current.txt-rw-rw-r-- 664 1 sysadmin:sysadmin 14 2026-08-29 09:40:52.878729254 +0000 report.txtdrwxrwxr-x 775 2 sysadmin:sysadmin 4096 2026-08-29 09:40:52.879729251 +0000 logslrwxrwxrwx 777 1 sysadmin:sysadmin 10 2026-08-29 09:40:52.880729247 +0000 current.txt -
find . -type f -size +1kSize filters take `k`, `M`, `G` - and round UP to whole units, which is why a `+1k` matches a 1-byte file on some filesystems.
bash Example session cd ~/ess/f && find . -type f -size +1k | sort; echo "--- and the sizes for comparison:"; find . -type f -printf '%6s %p\n' | sort -rn--- and the sizes for comparison: 292 ./app/logs/big.log 2 ./app/logs/small.log 2 ./app/conf/app.conf 0 ./tmp/scratch 0 ./app/logs/old.log -
chmod 640 <file>Numeric sets all three groups at once; symbolic (`g+w`) changes one and leaves the rest. Use numeric when a task states the whole mode.
bash Example session cd ~/ess/perm && chmod 640 newfile && stat -c '%A %a' newfile && chmod u=rw,g=r,o= newfile && stat -c '%A %a' newfile-rw-r----- 640-rw-r----- 640 -
grep -E '<pattern>' <file>Extended regex without the backslashes. `-c` counts, `-n` numbers, `-i` ignores case, `-v` inverts.
bash Example session cd ~/ess/text && grep -E '" (4[0-9]{2}|5[0-9]{2}) ' access.log; echo "--- and the same thing with basic regex needs backslashes:"; grep '" \(4[0-9][0-9]\|5[0-9][0-9]\) ' access.log | wc -l10.0.0.9 - - [24/Aug/2026:10:01:12] "GET /admin HTTP/1.1" 403 9910.0.0.7 - - [24/Aug/2026:10:01:30] "POST /api/orders HTTP/1.1" 500 21010.0.0.9 - - [24/Aug/2026:10:02:44] "GET /admin HTTP/1.1" 403 9910.0.0.7 - - [24/Aug/2026:10:03:00] "POST /api/orders HTTP/1.1" 500 210--- and the same thing with basic regex needs backslashes:4 -
tar -tf <archive>ALWAYS list before extracting. An archive with absolute paths or `../` will write outside the directory you are standing in.
bash Example session cd ~/ess/t && tar -tf site.tar | head -5; echo "---"; tar -tf site.tar | wc -lsite/site/conf/site/conf/nginx.confsite/current.confsite/logs/---8
Domain 2 - Operations Deployment (25%)
-
dpkg -S <path> / rpm -qf <path>Which package owns a file. `-S` searches and `-L` lists on Debian; `-qf` and `-ql` on Red Hat. The most-fumbled pair in the domain.
bash Example session dpkg -S /usr/bin/tar; echo "---"; dpkg -S /usr/bin/wtar: /usr/bin/tar---procps: /usr/bin/w -
dnf provides <path>Finds the package for a command you do NOT have. apt has no built-in equivalent - `apt-file` is a separate package needing `apt-file update`.
bash Example session dnf provides /usr/bin/tree 2>&1 | grep -E '^tree|Repo|Matched' | head -4tree-2.1.0-8.el10.x86_64 : File system tree viewerRepo : baseosMatched from: -
dpkg -V <pkg> / rpm -V <pkg>Silence means every file matches what was installed. Column 3 is the checksum and is the one that always catches a content change.
bash Example session dpkg -V tar; echo "dpkg -V exit $? (silence means unmodified)"dpkg -V exit 0 (silence means unmodified) -
apt-mark hold <pkg> / showholdRun `showhold` when an upgrade mysteriously skips one package. dnf uses `exclude=` in dnf.conf, or the versionlock plugin.
bash Example session sudo apt-mark hold tar 2>&1 | tail -1; apt-mark showhold; echo "--- held: apt will not upgrade it"tar set on hold.tar--- held: apt will not upgrade it -
systemctl --failedThe first command to run on a machine you have inherited. It is short, and anything in it is a real problem.
bash Example session systemctl --failed --no-pager; echo "--- failed units above" UNIT LOAD ACTIVE SUB DESCRIPTION 0 loaded units listed.--- failed units above -
journalctl -u <unit> -n 20`-b` for this boot, `--since "1 hour ago"`, `-p err` for priority, `-f` to follow. `-o short-iso` for timestamps you can sort.
bash Example session sudo journalctl -u sshd --no-pager -n 4 -o short-iso | tail -52026-08-29T15:11:38+05:30 lfcs-c01 sshd-session[8789]: pam_unix(sshd:session): session opened for user sysadmin(uid=1000) by sysadmin(uid=0)2026-08-29T15:11:38+05:30 lfcs-c01 sshd-session[8789]: pam_unix(sshd:session): session closed for user sysadmin2026-08-29T15:11:38+05:30 lfcs-c01 sshd-session[8800]: Accepted publickey for sysadmin from 192.168.0.254 port 57409 ssh2: ED25519 SHA256:aTxQ2TUQ/xdcGpeWfiZcVs2wa6VhoiGwnj43sn/bXyU2026-08-29T15:11:38+05:30 lfcs-c01 sshd-session[8800]: pam_unix(sshd:session): session opened for user sysadmin(uid=1000) by sysadmin(uid=0) -
ps -eo <fields> --sort=-pcpuChoose your own columns and sort by one. Far more useful under pressure than memorising what `aux` happens to print.
bash Example session ps -eo pid,ppid,user,pcpu,pmem,rss,stat,start,comm --sort=-pcpu | head -6 PID PPID USER %CPU %MEM RSS STAT STARTED COMMAND 1 0 root 0.1 0.4 17280 Ss 08:24:48 systemd 20709 1 root 0.1 1.4 49708 Ssl 09:31:43 fwupd 32778 1 root 0.1 0.2 7784 Ss 09:34:07 sshd 65645 1 root 0.0 0.6 23036 Ssl 09:42:34 packagekitd 49720 2 root 0.0 0.0 0 I 09:41:05 kworker/u8:4-writeback
Domain 3 - Users and Groups (10%)
-
useradd -m -c "<comment>" <user>`-m` creates the home directory and is NOT the default on every distribution. Without it the account exists and cannot log in usefully.
bash Example session sudo useradd -m -c "LFCS demo user" lfcsa && getent passwd lfcsa; echo "---"; getent group lfcsa; echo "---"; id lfcsalfcsa:x:1001:1001:LFCS demo user:/home/lfcsa:/bin/sh---lfcsa:x:1001:---uid=1001(lfcsa) gid=1001(lfcsa) groups=1001(lfcsa) -
getent passwd <user>Seven fields: name, password placeholder, UID, GID, comment, home, shell. `getent` reads every source, not just the file.
bash Example session getent passwd lfcsa | tr ':' '\n' | nl | sed 's/^/ field /' field 1 lfcsa field 2 x field 3 1001 field 4 1001 field 5 LFCS demo user field 6 /home/lfcsa field 7 /bin/sh -
chage -m 7 -M 90 -W 14 -I 30 <user>Minimum, maximum, warning, inactive. `chage -l` reads them back, and `-d 0` forces a change at next login.
bash Example session sudo chage -m 7 -M 90 -W 14 -I 30 lfcsage && sudo chage -l lfcsageLast password change : Aug 29, 2026Password expires : Nov 27, 2026Password inactive : Dec 27, 2026Account expires : neverMinimum number of days between password change : 7Maximum number of days between password change : 90Number of days of warning before password expires : 14 -
visudo -c -f <file>Check a sudoers fragment BEFORE installing it. A syntax error in `/etc/sudoers` locks everyone out of sudo, including you.
bash Example session sudo visudo -c -f /tmp/lfcsop.rule; echo "check exit: $?"/tmp/lfcsop.rule: parsed OKcheck exit: 0
Domain 4 - Networking (25%)
-
ip -brief addr showOne line per interface. `link` is the interface, `addr` is the IP on top of it - an interface can be UP with no address, which is a distinct fault.
bash Example session ip -brief addr show; echo "---"; ip -brief link show | head -4lo UNKNOWN 127.0.0.1/8 ::1/128eth0 UP 192.168.0.70/24 fe80::215:5dff:fe01:117a/64---lo UNKNOWN 00:00:00:00:00:00 <LOOPBACK,UP,LOWER_UP>eth0 UP 00:15:5d:01:11:7a <BROADCAST,MULTICAST,UP,LOWER_UP> -
ip route / ip route get <dest>`get` asks the kernel which line it would use, and sends nothing. Run it before ping - it separates "no route" from "route exists, path broken".
bash Example session ip route; echo "--- the host's real table"default via 192.168.0.1 dev eth0 proto static10.99.0.0/24 dev lfcs-veth0 proto kernel scope link src 10.99.0.1192.168.0.0/24 dev eth0 proto kernel scope link src 192.168.0.70--- the host's real table -
grep ^hosts: /etc/nsswitch.conf`files dns` is why `/etc/hosts` wins. This one line explains more resolution mysteries than any other file on the system.
bash Example session grep -E '^hosts:' /etc/nsswitch.conf; echo "--- this line decides the ORDER, and files comes first"hosts: files dns--- this line decides the ORDER, and files comes first -
getent hosts <name>What a PROGRAM would get, via nsswitch. `dig` skips nsswitch entirely and never reads `/etc/hosts` - which is why the two disagree.
bash Example session getent hosts archive.ubuntu.com 2>&1 | head -2; echo "---"; dig +short archive.ubuntu.com 2>/dev/null | head -32620:2d:4002:1::101 archive.ubuntu.com2620:2d:4000:1::101 archive.ubuntu.com---185.125.190.83185.125.190.8291.189.92.24 -
ss -lntplistening, numeric, tcp, process. Always `-n` - without it ss reverse-resolves every address and hangs on the very host you are debugging.
bash Example session sudo ss -lntp | head -8State Recv-Q Send-Q Local Address:Port Peer Address:PortProcessLISTEN 0 4096 127.0.0.53%lo:53 0.0.0.0:* users:(("systemd-resolve",pid=611,fd=17))LISTEN 0 4096 0.0.0.0:22 0.0.0.0:* users:(("sshd",pid=75118,fd=3),("systemd",pid=1,fd=220))LISTEN 0 4096 127.0.0.54:53 0.0.0.0:* users:(("systemd-resolve",pid=611,fd=19))LISTEN 0 4096 [::]:22 [::]:* users:(("sshd",pid=75118,fd=4),("systemd",pid=1,fd=221)) -
sshd -t / sshd -T`-t` checks syntax before a restart; `-T` prints the EFFECTIVE config after every include. Read `-T`, never the file.
bash Example session sudo sshd -t && echo "syntax OK, exit 0"; echo "--- always run sshd -t BEFORE restarting sshd"syntax OK, exit 0--- always run sshd -t BEFORE restarting sshd -
firewall-cmd --list-allZone, interfaces, services and ports at once. Run it FIRST - a rule added to the wrong zone has no effect and no error.
bash Example session sudo firewall-cmd --list-all 2>&1 | head -12public (default, active) target: default ingress-priority: 0 egress-priority: 0 icmp-block-inversion: no interfaces: eth0 sources: services: cockpit dhcpv6-client ssh ports: protocols: forward: yes masquerade: no -
firewall-cmd --add-port=8080/tcp --permanent && firewall-cmd --reloadRuntime and permanent are separate stores. Neither flag does both, and `--reload` discards unsaved runtime rules. `--runtime-to-permanent` commits a set you have already tested.
Domain 5 - Storage (20%)
-
blkid -s UUID -o value <dev>The UUID for the fstab line. Device names are assigned in discovery order and a `/dev/sdb1` in fstab is a machine that will eventually fail to boot.
bash Example session sudo blkid -s UUID -o value "$(cat /tmp/lfcsdev)" | sudo tee /tmp/lfcsuuid; echo "--- the UUID, which is the only stable name"86b78b95-d1b1-42d8-b7b2-c9f0b0c62f22--- the UUID, which is the only stable name -
findmnt --verifyValidates fstab WITHOUT mounting. Run it after every edit - it also catches the `systemctl daemon-reload` you have not done yet.
bash Example session sudo findmnt --verify --verbose 2>&1 | tail -6; echo "findmnt --verify exit above - run this BEFORE you reboot" [ ] userspace options: nofail [ ] UUID=86b78b95-d1b1-42d8-b7b2-c9f0b0c62f22 translated to /dev/loop0 [ ] source /dev/loop0 exists [ ] FS type is ext4 [W] your fstab has been modified, but systemd still uses the old version; use 'systemctl daemon-reload' to reloadfindmnt --verify exit above - run this BEFORE you reboot -
vgdisplay <vg>PE Size is 4 MiB by default and every logical volume is a whole number of extents. `-l 100%FREE` takes the rest with no arithmetic.
bash Example session sudo vgdisplay lfcsvg 2>/dev/null | grep -E 'VG Name|VG Size|PE Size|Total PE|Free PE|Alloc PE'; echo "--- the extent is the unit LVM actually allocates in" VG Name lfcsvg VG Size 1020.00 MiB PE Size 4.00 MiB Total PE 255 Alloc PE / Size 0 / 0 Free PE / Size 255 / 1020.00 MiB--- the extent is the unit LVM actually allocates in -
lvextend -r -L +<size> <lv>`-r` resizes the volume AND the filesystem, in the right order, calling the right tool. `+` is relative; without it you may be shrinking.
bash Example session sudo lvextend -r -L +900M /dev/lfcsvg/data 2>&1 | tail -4; df -h /mnt/lfcslv | tail -1; echo "--- -r grew the volume AND the filesystem in one command" resize2fs done Extended file system ext4 on lfcsvg/data. Logical volume lfcsvg/data successfully resized./dev/mapper/lfcsvg-data 1.5G 201M 1.3G 14% /mnt/lfcslv--- -r grew the volume AND the filesystem in one command -
fallocate -l 256M f && chmod 600 f && mkswap f && swapon fFour commands in that order. `fallocate` not `truncate` - swap on a sparse file loses machines. 600 before mkswap.
bash Example session sudo mkswap /swap.lfcs 2>&1 | tail -3Setting up swapspace version 1, size = 256 MiB (268431360 bytes)no label, UUID=ad6cedd6-6285-4439-9968-1e973f4b51b4 -
lsof +L1 <mountpoint> | grep <mountpoint>Deleted-but-open files - when `df` and `du` disagree. Grep the path: `+L1` alone also lists systemd memfds and hands you PID 1.
bash Example session sudo lsof +L1 /mnt/lfcsfull 2>/dev/null | grep lfcsfull; echo "--- grep for the mount point: +L1 alone also lists systemd memfds that have nothing to do with this disk"tail 50906 sysadmin 6r REG 7,0 314572800 0 13 /mnt/lfcsfull/held (deleted)--- grep for the mount point: +L1 alone also lists systemd memfds that have nothing to do with this disk -
df -i <mountpoint>Full with 99% of the space free means inodes. ext4 fixes the count at mkfs time and it cannot be changed afterwards; xfs has no such limit.
bash Example session sudo sh -c 'i=0; while [ $i -lt 600 ]; do echo hi > /mnt/lfcsfull/f$i 2>/dev/null || { echo "FAILED at file $i"; break; }; i=$((i+1)); done'sh: 1: cannot create /mnt/lfcsfull/f500: No space left on deviceFAILED at file 500 -
tune2fs -m 1 <dev>Reclaims most of ext4's 5% root reserve instantly, on a mounted filesystem. An emergency lever for a data volume - never for `/`.
bash Example session sudo tune2fs -m 1 "$(cat /tmp/fulldev)" 2>&1 | tail -1; df -h /mnt/lfcsfull | tail -1; echo "--- reserve cut to 1%, and the space appears without deleting anything"Setting reserved blocks percentage to 1% (1310 blocks)/dev/loop0 488M 452M 21M 96% /mnt/lfcsfull--- reserve cut to 1%, and the space appears without deleting anything
No command matches that search.