Cheat Sheets / Linux & Scripting

Linux cheat sheet

198 commands from every lesson of Linux — Level by Level, on one page.

01 · Your first terminal session

Where am I, who am I?

whoamiYour username
hostnameThe machine's name
pwdPrint working directory (where you are)
uname -aKernel and architecture
cat /etc/os-releaseWhich Linux distribution and version

Getting help

man lsThe manual page for ls (q to quit, / to search)
ls --helpShort built-in help for most commands
type cdIs it a built-in, an alias, or a program?
apropos networkSearch manual page descriptions

Save typing

Tab / Tab TabComplete a name / list the options
↑ / ↓Previous / next command
Ctrl+RSearch your command history
history | tail -20Your last 20 commands
Ctrl+C / Ctrl+LCancel the running command / clear the screen

02 · Files & directories

Move around

ls -lahList all files, long format, human-readable sizes
cd /var/logGo to an absolute path
cd .. / cd - / cdUp one level / previous directory / home
tree -L 2Directory tree two levels deep (may need installing)

Create, copy, move, delete

mkdir -p app/config/devCreate nested directories
touch notes.txtCreate an empty file (or update its timestamp)
cp -r src/ backup/Copy a directory recursively
mv old.txt new.txtRename (or move) a file
rm -i file.txtDelete, asking first
rm -r dir/Delete a directory and its contents (no undo!)

Find things

find /etc -name '*.conf'Files by name pattern
find /var/log -size +100MFiles larger than 100 MB
find . -mtime -1Modified in the last 24 hours
ln -s /opt/app/current appCreate a symbolic link

03 · Reading & searching text

Read

less /var/log/syslogPage through a file (/ search, n next, G end, q quit)
head -20 fileFirst 20 lines
tail -50 fileLast 50 lines
tail -f /var/log/syslogFollow a file as it grows (Ctrl+C to stop)

Search

grep -i error app.logLines containing 'error', any case
grep -rn 'listen' /etc/nginx/Search recursively, show file and line number
grep -v DEBUG app.logLines NOT matching
grep -C 3 'Traceback' app.log3 lines of context around each match

Pipes & redirection

cmd | grep x | wc -lCount lines matching x in cmd's output
cmd > out.txt / cmd >> out.txtWrite / append output to a file
cmd 2> errors.txtSend only errors to a file
cmd > all.txt 2>&1Output and errors to one file
sort | uniq -c | sort -rn | headCount and rank repeated lines

04 · Users, groups & permissions

Who am I?

idYour user ID, group ID and all groups
groups ashaGroups a user belongs to
getent passwd ashaA user's account entry

Change permissions and owners

chmod 640 app.envrw- for owner, r-- for group, --- for others
chmod u+x deploy.shAdd execute for the owner
chmod -R g+w shared/Recursively add group write
sudo chown app:app /srv/appChange owner and group

Users and sudo

sudo adduser deployCreate a user (Debian/Ubuntu helper)
sudo usermod -aG docker deployAdd a user to a group (-a = append!)
sudo -lWhat am I allowed to run with sudo?
sudo -u app whoamiRun a command as another user

05 · Processes, services & packages

Processes

ps aux --sort=-%mem | headTop memory users
ps -ef --forestProcesses with parent/child tree
top (or htop)Live view; press M (memory), P (CPU), q to quit
pgrep -a nginxFind processes by name
kill <pid> / kill -9 <pid>Ask to stop (SIGTERM) / force kill (SIGKILL)

Services (systemd)

systemctl status nginxRunning? Since when? Last log lines
sudo systemctl restart nginxRestart a service
sudo systemctl enable --now nginxStart now AND at every boot
systemctl list-units --type=service --state=failedServices that failed

Packages

sudo apt update && sudo apt install -y nginxDebian/Ubuntu
sudo dnf install -y nginxRHEL/Rocky/Alma/Fedora
apt list --installed | grep nginxIs it installed? (Debian/Ubuntu)
dpkg -L nginx / rpm -ql nginxFiles a package installed

06 · Checkpoint: a day on a server

Commands you'll use

systemctl status nginxIs it running? What went wrong?
sudo nginx -tCheck nginx config syntax, with file and line number
journalctl -u nginx --since '10 min ago'The service's recent logs
sudo ss -ltnpWhich process listens on which TCP port
curl -I http://localhostHTTP status code only
sudo du -ah /var/log | sort -rh | headLargest files and folders under /var/log

07 · systemd & journald in depth

Units

systemctl cat nginxShow the unit file(s) actually in use
sudo systemctl edit nginxCreate a drop-in override (survives package upgrades)
sudo systemctl daemon-reloadReload unit files after changing them
systemctl list-dependencies multi-user.targetWhat starts at boot
systemctl --failedEverything that failed

Journal

journalctl -u nginx -fFollow one service's logs
journalctl -u nginx --since '1 hour ago' -p warningWarnings and worse, last hour
journalctl -b -1 -p errErrors from the previous boot
journalctl -kKernel messages (like dmesg)
journalctl --disk-usage / sudo journalctl --vacuum-size=500MJournal size / shrink it

Boot

systemd-analyze blame | headSlowest units at boot
systemd-analyze critical-chainThe chain that delayed boot

08 · Disks & filesystems

Where did the space go?

df -hFree space per mounted filesystem
df -iFree inodes (file slots) per filesystem
sudo du -xh --max-depth=1 / | sort -rh | headBiggest top-level directories on the root filesystem
sudo lsof +L1Deleted files still held open (space not yet freed)
sudo find / -xdev -size +1G -type f 2>/dev/nullFiles over 1 GB on this filesystem

Disks & mounts

lsblk -fDisks, partitions, filesystems, mount points
findmnt /var/libWhich filesystem a path lives on
sudo mount -aMount everything in /etc/fstab (test after editing it!)

LVM grow

sudo pvs; sudo vgs; sudo lvsPhysical volumes, volume groups, logical volumes
sudo lvextend -r -L +10G /dev/vg0/dataGrow a logical volume AND its filesystem

09 · Networking from the host

Interfaces & routes

ip -br addrInterfaces and IPs, one line each
ip routeRouting table (look for 'default via')
ip route get 8.8.8.8Which interface and gateway a destination would use
ip -s link show eth0Packet and error counters

Sockets & connectivity

sudo ss -ltnpListening TCP ports and their processes
ss -tn state establishedCurrent TCP connections
nc -vz db.internal 5432Can I open a TCP connection to this port?
curl -v https://api.example.com/healthFull HTTP/TLS exchange

DNS & packets

dig +short api.example.comResolve a name
resolvectl statusWhich DNS servers this host uses (systemd-resolved)
sudo tcpdump -ni any port 5432Watch packets to/from port 5432
sudo nft list ruleset / sudo iptables -SFirewall rules

10 · Performance triage

The 60-second checklist

uptimeLoad averages: 1, 5, 15 minutes
sudo dmesg -T | tailKernel errors: OOM kills, disk or network errors
vmstat 1 5Run queue, memory, swap, I/O wait, context switches
mpstat -P ALL 1 3Per-CPU usage: one hot CPU?
pidstat 1 3Which processes use CPU
iostat -xz 1 3Per-disk utilisation and latency (await)
free -hMemory: look at 'available'
sar -n DEV 1 3Network throughput per interface
top (or htop)Everything live

Install the tools

sudo apt install -y sysstat / sudo dnf install -y sysstatProvides iostat, mpstat, pidstat, sar

11 · SSH, keys & remote work

Keys

ssh-keygen -t ed25519 -C 'asha@laptop'Create a key pair (protect it with a passphrase)
ssh-copy-id asha@web-01Install your public key on a server
ssh-add ~/.ssh/id_ed25519Load the key into the agent (type the passphrase once)
ssh -v asha@web-01Verbose: see why a login fails

Getting around

ssh -J bastion.example.com asha@10.0.5.20Jump through a bastion host
ssh -L 8080:localhost:80 asha@web-01Local port forward: laptop:8080 → web-01:80
rsync -avz --progress ./site/ asha@web-01:/srv/site/Sync a directory (only changed files)
scp backup.tar.gz asha@web-01:/tmp/Copy one file

tmux

tmux new -s workStart a named session
Ctrl+b dDetach (the session keeps running)
tmux attach -t workRe-attach later
Ctrl+b % / Ctrl+b "Split pane vertically / horizontally

12 · Checkpoint: five broken servers

Your first five commands on any sick server

uptime; free -h; df -h; df -iLoad, memory, space and inodes at a glance
systemctl --failedFailed services
journalctl -p err -b --no-pager | tail -30Recent errors this boot
sudo ss -ltnpWhat's listening
sudo dmesg -T | tail -20Kernel complaints (OOM, disk, network)

13 · Kernel, modules & sysctl

Kernel & modules

uname -rRunning kernel version
lsmod | grep br_netfilterIs a module loaded?
modinfo overlayModule details and parameters
sudo modprobe br_netfilterLoad a module now
echo br_netfilter | sudo tee /etc/modules-load.d/k8s.confLoad it at every boot

sysctl

sysctl net.ipv4.ip_forwardRead one parameter
sudo sysctl -w vm.swappiness=10Change it now (lost at reboot)
sudo sysctl --systemApply all files in /etc/sysctl.d/
cat /proc/cmdlineParameters the kernel was booted with

14 · cgroups & namespaces

Namespaces

lsnsList namespaces on the host
sudo unshare --pid --fork --mount-proc bashA shell in a new PID namespace (it becomes PID 1)
sudo unshare --net bashA shell with its own, empty network stack
sudo nsenter -t <pid> -n ip addrRun a command inside another process's network namespace
ls -l /proc/<pid>/nsWhich namespaces a process belongs to

cgroups v2

stat -fc %T /sys/fs/cgroupcgroup2fs = cgroup v2 in use
systemd-cglsThe cgroup tree
systemd-cgtopLive resource use per cgroup
sudo systemd-run --unit=demo -p MemoryMax=64M -p CPUQuota=20% sleep 600Run something in a limited cgroup
cat /sys/fs/cgroup/<path>/memory.maxA cgroup's memory limit

15 · NUMA, huge pages & CPU pinning

Inspect the hardware

lscpu | grep -i -E 'numa|socket|thread'Sockets, NUMA nodes, threads per core
numactl --hardwareNUMA nodes, their CPUs, memory and distances
lscpu -eEach CPU with its core, socket and NUMA node
grep -i huge /proc/meminfoHuge page totals and usage

Control placement

taskset -c 2,3 ./appRun on CPUs 2 and 3 only
numactl --cpunodebind=0 --membind=0 ./appRun and allocate memory on NUMA node 0
sudo sysctl -w vm.nr_hugepages=512Reserve 512 × 2 MiB huge pages
cat /sys/kernel/mm/transparent_hugepage/enabledTransparent huge pages mode

16 · Tracing with perf & eBPF

perf (CPU profiling)

sudo perf topLive view of the hottest functions system-wide
sudo perf record -F 99 -a -g -- sleep 30Sample all CPUs at 99 Hz for 30 s, with stacks
sudo perf report --stdio | head -50Where CPU time went
sudo perf record -F 99 -g -p <pid> -- sleep 30Profile one process

eBPF tools (bcc; Ubuntu names end in -bpfcc)

sudo execsnoop-bpfccEvery new process, as it starts
sudo opensnoop-bpfcc -p <pid>Files a process opens
sudo biolatency-bpfcc 10 1Disk I/O latency histogram over 10 s
sudo tcpconnect-bpfccOutgoing TCP connections as they happen
sudo runqlat-bpfcc 10 1How long tasks wait for a CPU

bpftrace one-liners

sudo bpftrace -e 'tracepoint:raw_syscalls:sys_enter { @[comm] = count(); }'System calls per process (Ctrl+C to print)
sudo bpftrace -e 'tracepoint:syscalls:sys_enter_execve { printf("%s\n", comm); }'Which programs call execve

17 · SELinux & AppArmor

SELinux (RHEL, Rocky, Alma, Fedora)

getenforce / sestatusMode: Enforcing, Permissive or Disabled
ls -Z /var/www/html / ps -eZ | grep nginxFile and process contexts (labels)
sudo ausearch -m AVC -ts recentRecent denials from the audit log
sudo restorecon -Rv /srv/wwwReset files to their policy-defined labels
sudo semanage fcontext -a -t httpd_sys_content_t '/srv/www(/.*)?'Teach the policy a new web content path
sudo setsebool -P httpd_can_network_connect onFlip a policy boolean permanently
sudo semanage port -a -t http_port_t -p tcp 8081Allow a service type to use another port

AppArmor (Ubuntu, Debian, SUSE)

sudo aa-statusLoaded profiles and their modes
sudo journalctl -k | grep -i apparmorDenials (apparmor="DENIED")
sudo aa-complain /etc/apparmor.d/<profile>Log instead of block (for debugging)
sudo aa-enforce /etc/apparmor.d/<profile>Enforce again

18 · Host hardening

Attack surface

sudo ss -ltnupEverything listening on TCP and UDP
systemctl list-unit-files --state=enabledServices that start at boot
sudo find / -xdev -perm -4000 -type f 2>/dev/nullsetuid programs

SSH & firewall

sudo sshd -tValidate sshd_config before reloading
sudo ufw default deny incoming && sudo ufw allow OpenSSH && sudo ufw enableDefault-deny firewall (Ubuntu)
sudo firewall-cmd --permanent --add-service=https && sudo firewall-cmd --reloadOpen HTTPS (RHEL family)

Updates & audit

sudo apt install unattended-upgradesAutomatic security updates (Ubuntu/Debian)
sudo systemctl enable --now dnf-automatic.timerAutomatic updates (RHEL family; configure apply_updates)
sudo auditctl -lActive audit rules
sudo ausearch -k identity -ts todayAudit events tagged 'identity'

19 · Capstone: harden & tune a host

Evidence to capture before and after

sudo ss -ltnup > listen.txtOpen ports
systemctl list-unit-files --state=enabled > enabled.txtEnabled services
sudo sysctl -a 2>/dev/null > sysctl.txtAll kernel parameters
vmstat 1 10 > vmstat.txt; iostat -xz 1 10 > iostat.txtPerformance baseline
diff before/listen.txt after/listen.txtWhat changed

Load test (from another machine)

ab -n 20000 -c 100 http://<server>/Apache Bench: requests/second and latency
wrk -t4 -c200 -d60s --latency http://<server>/wrk: throughput and latency percentiles