// eknathalabs.com · linux lab
Structured hands-on Linux learning — LFCS exam domains, 8 interactive offline tools, 250+ commands, 10-question quiz, and full lab walkthroughs. Built by a Platform Engineer.
// LFCS Exam Blueprint
Every module, quiz question, and lab maps to an official LFCS domain.
// Learning Path
14 modules from essential commands to advanced security. Click any to explore.
// Interactive Tools
8 fully offline interactive tools — no API, no internet, works anywhere.
// Quick Reference
250+ commands — searchable, click any row to copy to clipboard.
// Practice Questions
36 scenario-based questions mapped to official LFCS domains.
// Hands-on Scenarios
25 step-by-step labs modelled on real production incidents and LFCS exam tasks.
ls (hd0,1)/ until you see etc/.set root=(hd0,1) then set prefix=(hd0,1)/boot/grubinsmod normal then normalsudo grub-install /dev/sda && sudo update-grubcat /boot/grub/grub.cfg | grep menuentrydf -h /dev/mapper/vg0-data — confirm 100% usage.sudo pvcreate /dev/sdbsudo vgextend vg0 /dev/sdbsudo lvextend -L +20G /dev/vg0/datasudo resize2fs /dev/vg0/datadf -h /dev/mapper/vg0-data — confirm new size.sudo systemctl status nginx — note "Address already in use".ss -tlnp | grep :80 or sudo fuser 80/tcpps aux | grep <PID>sudo systemctl stop apache2sudo systemctl start nginx && sudo systemctl enable nginxcurl -I http://localhost — expect HTTP/1.1 200 OK.ssh-keygen -t ed25519 -C "admin@server"ssh-copy-id -i ~/.ssh/id_ed25519.pub user@hostPasswordAuthentication no, PermitRootLogin no, Port 2222sudo systemctl reload sshd — test new key login first!sudo apt install fail2ban, configure /etc/fail2ban/jail.localsudo fail2ban-client status sshdsudo iptables -F && sudo iptables -Xsudo iptables -P INPUT DROP && sudo iptables -P OUTPUT DROPsudo iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPTsudo iptables -A INPUT -p tcp --dport 443 -j ACCEPTsudo iptables -A OUTPUT -p udp --dport 53 -j ACCEPTsudo iptables-save > /etc/iptables/rules.v4sestatus — ensure Enforcing mode.ausearch -m avc -ts recent | audit2whygetsebool -a | grep httpd then setsebool -P httpd_can_network_connect onrestorecon -Rv /var/www/html/ausearch -m avc | audit2allow -M mypol && semodule -i mypol.ppsestatus | grep mode — still enforcing.top -b -n1 | head -20 — sort by %CPU, note the PID.ps aux --sort=-%cpu | head -5cat /proc/<PID>/cmdline | tr ' ' ' 'kill -15 <PID> — wait 10 seconds.kill -9 <PID>ps aux | grep <PID> — should show no results.df -h — identify the full partition.du -sh /* 2>/dev/null | sort -rh | head -15du -sh /var/log/* | sort -rh | head -10sudo lsof | grep deleted | sort -k7 -rn | head -10sudo truncate -s 0 /var/log/app/debug.logdf -i then find inode hogs: find /var -xdev -printf '%h
' | sort | uniq -c | sort -rn | headsudo useradd -r -s /sbin/nologin myapp/etc/systemd/system/myapp.service with [Unit], [Service], [Install] sections.User=myapp, Restart=on-failure, RestartSec=5s, NoNewPrivileges=yes.sudo systemctl daemon-reloadsudo systemctl enable --now myappjournalctl -u myapp -f — confirm service is running and logging.nmcli connection show — note the interface name.nmcli con mod ens3 ipv4.method manual ipv4.addresses 10.0.1.50/24 ipv4.gateway 10.0.1.1nmcli con mod ens3 ipv4.dns "1.1.1.1 8.8.8.8" ipv4.dns-search "internal.lab"nmcli con mod ens3 +ipv4.routes "172.16.0.0/12 10.0.1.254"nmcli con up ens3ip addr show ens3, ip route show, resolvectl statusrd.break to kernel parameters.mount -o remount,rw /sysroot then chroot /sysrootusermod -aG wheel usernamevisudo — verify %wheel ALL=(ALL) ALL line exists.exit then reboot -fsudo -l -U username — confirm wheel group is listed.ss -s, sar -n TCP 1 5 — record current connection stats.tuned-adm profile throughput-performancesysctl -w net.core.somaxconn=65535 and net.ipv4.tcp_max_syn_backlog=65535sysctl -w net.core.rmem_max=134217728 net.core.wmem_max=134217728modprobe tcp_bbr then sysctl -w net.ipv4.tcp_congestion_control=bbr/etc/sysctl.d/99-webserver.conf then sysctl --systemvgs — need at least 10% free for CoW data.sudo lvcreate -L 5G -s -n lv_app-snap /dev/vg_data/lv_applvs -a — confirm snapshot with origin shown.sudo umount /opt/appsudo lvconvert --merge /dev/vg_data/lv_app-snap then reboot.watch -n 5 'ps aux --sort=-%mem | head -10'journalctl -k | grep -i oomsmem -r -k | head -15while true; do ps -o rss= -p <PID>; sleep 30; donesystemctl edit myapp — add MemoryMax=512M and MemoryHigh=400Msystemctl show myapp | grep Memory — confirm limits applied.ls -lh /var/log/myapp/sudo tee /etc/logrotate.d/myapp with path, daily, rotate 30, compress, missingok.systemctl reload myapp in a postrotate/endscript block.sudo logrotate --debug /etc/logrotate.d/myappsudo logrotate -f /etc/logrotate.d/myappls -lh /var/log/myapp/ — check .gz files created, old logs removed.sudo dnf install nfs-utils -ysudo mount -t nfs nas.local:/exports/data /mnt/nfs — verify access.nas.local:/exports/data /mnt/nfs nfs rw,hard,timeo=600,_netdev,nofail 0 0sudo findmnt --verifyTimeoutIdleSec=600 to unmount after 10 min idle.mkdir /shared/project && groupadd devteamchmod 2770 /shared/project && chgrp devteam /shared/projectsetfacl -m g:devteam:rwx /shared/projectsetfacl -d -m g:devteam:rwx /shared/projectsetfacl -m g:ops:rx /shared/projectgetfacl /shared/project — confirm all entries including default ACL.crontab -l — identify the job to migrate.sudo tee /etc/systemd/system/backup.service with Type=oneshot and ExecStart.sudo tee /etc/systemd/system/backup.timer with OnCalendar=daily and RandomizedDelaySec=30min.sudo systemctl enable --now backup.timersystemctl list-timers and systemd-analyze calendar dailyjournalctl -u backup.service -n 20 — confirm output captured.nmcli con add type bond con-name bond0 ifname bond0 bond.options "mode=active-backup,miimon=100"nmcli con add type ethernet con-name bond0-slave1 ifname ens3 master bond0nmcli con add type ethernet con-name bond0-slave2 ifname ens4 master bond0nmcli con mod bond0 ipv4.method manual ipv4.addresses 192.168.1.100/24 ipv4.gateway 192.168.1.1nmcli con up bond0 — verify with cat /proc/net/bonding/bond0ip link set ens3 down — ping should continue; verify active slave changed in bonding file.openssl x509 -in /etc/ssl/certs/myapp.crt -noout -datesopenssl req -new -key /etc/ssl/private/myapp.key -out /tmp/myapp.csrcp newcert.crt /etc/ssl/certs/myapp.crtsudo nginx -t — must pass before any reload.sudo systemctl reload nginx — NOT restart.openssl s_client -connect myapp.example.com:443 -brief 2>/dev/null | grep -i expireiostat -xz 2 5 — look for %util near 100% or await > 20ms.sudo iotop -o -d 1 — sort by I/O bandwidth.pidstat -d 2 5 — match PID to service name.cat /sys/block/sda/queue/schedulerecho mq-deadline > /sys/block/sda/queue/scheduler/etc/udev/rules.d/60-scheduler.rules then udevadm triggervim /opt/scripts/disk-alert.sh — start with #!/usr/bin/env bash and set -euo pipefail.log() { echo "[$(date '+%Y-%m-%d %H:%M:%S')] $*" | tee -a /var/log/disk-alert.log; }mkdir /var/run/disk-alert.lock to prevent concurrent runs.df -h with awk to parse usage %, compare against threshold variable.echo "$MSG" | mail -s "[DISK ALERT] $(hostname)" [email protected]bash -n disk-alert.sh then shellcheck disk-alert.sh — fix all warnings before deploying.free -h and swapon --showsudo fallocate -l 4G /swapfilesudo chmod 600 /swapfilesudo mkswap /swapfile && sudo swapon /swapfileecho '/swapfile none swap sw 0 0' | sudo tee -a /etc/fstabsysctl -w vm.swappiness=10 and persist in /etc/sysctl.d/99-swap.confsudo dnf install audit -y && sudo systemctl enable --now auditdsudo auditctl -w /etc/passwd -p wa -k passwd-changes/etc/audit/rules.d/99-critical.rules then augenrules --loadausearch -k passwd-changes -ts recent — find UID, command, and timestamp.ausearch -k passwd-changes -ts recent -i | grep -i auidrpm -q nginxsudo dnf install python3-dnf-plugin-versionlock && sudo dnf versionlock add nginxsudo dnf versionlock list — confirm nginx is pinned.sudo dnf versionlock delete nginx && sudo dnf update nginxsudo dnf history undo lastrpm -q nginx — confirm previous version is restored.// Error Encyclopedia
Common Linux errors — root cause, fix commands, and prevention. Click to expand.
The nginx process failed to start — usually a config syntax error, port conflict, or missing file.
Always run nginx -t before reloading. Use systemctl --failed to catch issues early.
Another process is bound to port 80. Common culprits: apache2, another nginx instance, or a Node.js app.
Use ss -tlnp before starting services. Only one service should own each port.
GRUB cannot find or read the boot partition — caused by disk change, wrong partition table, or GRUB misconfiguration.
After changing disk layout, always run update-grub. Keep a live USB available.
Either disk space is exhausted, or inode count is depleted (you can have free blocks but no free inodes).
Set up disk usage alerts at 80%. Rotate logs with logrotate. Monitor inodes.
SELinux is blocking nginx from reading a file — the file has an incorrect security context label.
Always use restorecon after moving files. Never use setenforce 0 as a fix.
SSH daemon is not running, bound to a different port, or firewall is blocking port 22.
Enable sshd with systemctl enable sshd. Open firewall port before changing SSH port.
The user account is not in the sudo group or lacks a sudoers entry.
Add users to the sudo/wheel group during provisioning.
Another apt/dpkg process is running (e.g. unattended-upgrades, another terminal).
Never force-kill apt without running dpkg --configure -a afterward.
// RHEL Deep-Dive Guides
12 complete RHEL-based tutorials with real examples, Do's & Don'ts — read everything right here, no GitHub needed.