Linux System Administration Cheatsheet
Quick reference for Linux sysadmin tasks — filesystem, processes, networking, text processing, storage, systemd, and security hardening.
Quick Reference
File System
# List files with details
ls -la
ls -lhS # Sort by size (human readable)
ls -ltr # Sort by time, reverse
# Find files
find /var/log -name "*.log" -mtime +7
find /tmp -size +100M -type f
find /etc -name "*.conf" -user root
find . -type f -newer reference.txt
# Disk usage
du -sh /var/log/* # Summary per item
du -sh * | sort -h # Sort by size
df -h # Filesystem usage
df -i # Inode usage
# File info and permissions
stat filename
chmod 755 script.sh
chmod -R 644 /var/www/html
chown -R www-data:www-data /var/www
ln -s /path/to/target /path/to/link
cp -r src/ dest/
rsync -avz src/ user@host:/dest/
Process Management
# List processes
ps aux
ps aux | grep nginx
ps -ef --forest # Show process tree
# Interactive monitoring
top # Press 1 for per-CPU, M for memory sort
htop # Enhanced top (install separately)
# Kill processes
kill -9 PID
kill -15 PID # SIGTERM (graceful)
killall nginx
pkill -f "python app.py"
# Priority management
nice -n 10 command # Start with priority
renice -n 5 -p PID # Change running process
# Background jobs
nohup ./script.sh > out.log 2>&1 &
jobs -l
fg %1
bg %2
disown -h %1 # Detach from shell
systemctl Service Management
# Service control
systemctl start nginx
systemctl stop nginx
systemctl restart nginx
systemctl reload nginx # Reload config without restart
systemctl status nginx
# Enable/disable at boot
systemctl enable nginx
systemctl disable nginx
systemctl enable --now nginx # Enable and start
# List services
systemctl list-units --type=service
systemctl list-units --failed
# Journal logs
journalctl -u nginx
journalctl -u nginx --since "1 hour ago"
journalctl -u nginx -n 100 --no-pager
journalctl -f # Follow (like tail -f)
journalctl -p err # Only errors
journalctl --disk-usage
User & Groups
# User management
useradd -m -s /bin/bash username
usermod -aG docker username # Add to group
usermod -L username # Lock account
userdel -r username # Remove user + home
# Password management
passwd username
chage -l username # Show password aging
chage -M 90 username # Max 90 days
chage -E 2026-12-31 username # Expire on date
# Group management
groupadd devteam
groupmod -n newname oldname
gpasswd -a user group
gpasswd -d user group
# Show info
id username
groups username
who # Logged in users
last -n 20 # Login history
lastb -n 10 # Failed logins
# Sudo management
visudo # Edit sudoers safely
# Add to sudoers: username ALL=(ALL) NOPASSWD: ALL
su - username # Switch user
Networking
# IP address and routing
ip addr show
ip addr show eth0
ip route show
ip route add 10.0.0.0/8 via 192.168.1.1
ip link set eth0 up/down
# Active connections
ss -tlnp # TCP listening with process
ss -tunp # TCP+UDP with process
ss -s # Summary statistics
netstat -tlnp # Older alternative
# Connectivity
ping -c 4 google.com
traceroute -n 8.8.8.8
mtr 8.8.8.8 # Combined ping+traceroute
# DNS
nslookup domain.com 8.8.8.8
dig domain.com A
dig domain.com MX
dig @8.8.8.8 domain.com
# Download / test
curl -I https://example.com # Headers only
curl -O https://example.com/file.tar
wget -q --show-progress https://...
nc -zv host 443 # Port check
nmap -p 22,80,443 192.168.1.1
# Packet capture
tcpdump -i eth0 -n port 443
tcpdump -i any -w capture.pcap
Text Processing
# grep
grep -rn "error" /var/log/
grep -i "warning" app.log # Case insensitive
grep -v "DEBUG" app.log # Invert match
grep -E "error|fail" app.log # Regex OR
grep -c "200" access.log # Count matches
# awk
awk '{print $1, $7}' access.log # Print columns 1 and 7
awk -F: '{print $1}' /etc/passwd # Custom delimiter
awk '$3 > 500 {print}' file # Conditional
awk 'NR>=10 && NR<=20' file # Line range
# sed
sed 's/old/new/g' file # Replace all occurrences
sed -i 's/old/new/g' file # In-place edit
sed -n '10,20p' file # Print lines 10-20
sed '/^#/d' config.conf # Delete comment lines
# Other tools
cut -d: -f1,3 /etc/passwd # Cut by delimiter
sort -k3 -n file # Sort by 3rd column numerically
sort -u file # Sort + deduplicate
uniq -c | sort -rn # Count + sort by frequency
wc -l file # Count lines
jq '.items[].name' data.json # Parse JSON
column -t -s, file.csv # Format CSV as table
Archive & Compression
# tar
tar -czf archive.tar.gz dir/ # Create gzip archive
tar -cjf archive.tar.bz2 dir/ # Create bzip2 archive
tar -xzf archive.tar.gz # Extract gzip
tar -xzf archive.tar.gz -C /dest/ # Extract to dir
tar -tzf archive.tar.gz # List contents
tar -czf - dir/ | ssh host "cat > backup.tar.gz"
# gzip / bzip2
gzip file # Compress (replaces file)
gzip -d file.gz # Decompress
gzip -k file # Keep original
bzip2 -k file # bzip2 compress
# zip
zip -r archive.zip dir/
zip -e secure.zip file # Encrypt
unzip archive.zip -d /dest/
unzip -l archive.zip # List contents
# rsync (preferred for large transfers)
rsync -avz --progress src/ dest/
rsync -avz --delete src/ user@host:/dest/
rsync -avz --exclude="*.log" src/ dest/
rsync -n src/ dest/ # Dry run
Performance Monitoring
# CPU and memory
vmstat 2 10 # 10 samples every 2s
free -m # Memory in MB
free -h # Human readable
lscpu # CPU topology
uptime # Load average
# Disk I/O
iostat -x 2 5 # Extended I/O stats
iotop # Per-process I/O (requires root)
lsblk # Block devices tree
lsblk -f # With filesystem info
# System messages
dmesg | tail -50
dmesg -T | grep -i error
dmesg -T --level=err,warn
# Network performance
sar -n DEV 1 5 # Network stats (sysstat)
iftop # Per-connection bandwidth
nethogs # Per-process bandwidth
# Advanced
sar -u 1 10 # CPU utilization history
sar -r 1 5 # Memory utilization
sar -b 1 5 # I/O stats
Storage & LVM
# Block device management
lsblk
fdisk -l
fdisk /dev/sdb # Interactive partition
parted /dev/sdb # GPT-friendly alternative
# Filesystem
mkfs.ext4 /dev/sdb1
mkfs.xfs /dev/sdb1
mount /dev/sdb1 /mnt/data
umount /mnt/data
mount -a # Mount all in /etc/fstab
# /etc/fstab entry format:
# /dev/sdb1 /mnt/data ext4 defaults 0 2
# LVM basics
pvcreate /dev/sdb
vgcreate datavg /dev/sdb
lvcreate -L 50G -n datalv datavg
mkfs.ext4 /dev/datavg/datalv
# Extend LVM
lvextend -L +20G /dev/datavg/datalv
resize2fs /dev/datavg/datalv # For ext4
xfs_growfs /mnt/data # For xfs
# LVM status
pvs; vgs; lvs
pvdisplay; vgdisplay; lvdisplay
systemd: Service & Timer Units
Custom Service Unit
# /etc/systemd/system/myapp.service
[Unit]
Description=My Application
After=network.target
Requires=network.target
[Service]
Type=simple
User=myapp
Group=myapp
WorkingDirectory=/opt/myapp
ExecStart=/usr/bin/python3 /opt/myapp/app.py
ExecReload=/bin/kill -HUP $MAINPID
Restart=always
RestartSec=5
StandardOutput=journal
StandardError=journal
SyslogIdentifier=myapp
Environment=APP_ENV=production
EnvironmentFile=/etc/myapp/environment
[Install]
WantedBy=multi-user.target
# Reload systemd and enable
systemctl daemon-reload
systemctl enable --now myapp
Timer Unit (Cron Replacement)
# /etc/systemd/system/backup.service
[Unit]
Description=Database Backup
[Service]
Type=oneshot
ExecStart=/usr/local/bin/backup.sh
User=backup
# /etc/systemd/system/backup.timer
[Unit]
Description=Run backup daily at 2am
[Timer]
OnCalendar=*-*-* 02:00:00
Persistent=true # Run if missed (e.g., server was off)
[Install]
WantedBy=timers.target
# Enable timer
systemctl enable --now backup.timer
systemctl list-timers # Show all timers and next run time
journalctl Queries
# Time-based filtering
journalctl --since "2026-01-01 00:00:00" --until "2026-01-02 00:00:00"
journalctl --since "yesterday"
journalctl --since "2 hours ago"
# Severity levels (0=emerg to 7=debug)
journalctl -p err # Error and above
journalctl -p warning..err # Warning to error
journalctl -p 0..3 # emerg, alert, crit, err
# Unit and boot
journalctl -u nginx -u php-fpm # Multiple units
journalctl -b # Current boot
journalctl -b -1 # Previous boot
journalctl --list-boots
# Useful combinations
journalctl -u nginx -f -p err # Follow errors for nginx
journalctl --no-pager -u myapp --since "1 hour ago" | grep -i "exception"
journalctl -k # Kernel messages only
# Disk usage
journalctl --disk-usage
journalctl --vacuum-time=30d # Keep only last 30 days
journalctl --vacuum-size=500M # Keep only 500MB
Shell Productivity
Bash Shortcuts & History
# Navigation shortcuts
Ctrl+A Move to start of line
Ctrl+E Move to end of line
Ctrl+W Delete word before cursor
Ctrl+K Delete from cursor to end of line
Ctrl+U Delete from cursor to start of line
Ctrl+R Reverse history search
Ctrl+L Clear screen
Alt+. Insert last argument of previous command
# History
history | grep docker
!42 # Run command #42 from history
!! # Repeat last command
!ssh # Repeat last command starting with 'ssh'
history -c # Clear history
# Useful aliases
alias ll='ls -lah'
alias k='kubectl'
alias tf='terraform'
alias ..='cd ..'
alias ...='cd ../..'
alias grep='grep --color=auto'
alias ports='ss -tlnp'
# Export environment variables
export PATH="$HOME/.local/bin:$PATH"
export KUBECONFIG="$HOME/.kube/config"
export AWS_PROFILE=production
# Add to ~/.bashrc or ~/.zshrc to persist
Shell Scripting Essentials
#!/usr/bin/env bash
set -euo pipefail # Exit on error, undefined vars, pipe failures
IFS=$'\n\t' # Safe word splitting
# Variables and arguments
NAME="${1:-default}" # First arg with default
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
# If / elif / else
if [[ -f /etc/nginx/nginx.conf ]]; then
echo "nginx config exists"
elif [[ -d /etc/nginx ]]; then
echo "nginx dir exists but no config"
else
echo "nginx not found"
fi
# For loops
for file in /var/log/*.log; do
echo "Processing: $file"
done
for i in {1..5}; do echo "Iteration $i"; done
# While loop
while IFS= read -r line; do
echo "Line: $line"
done < input.txt
# Case statement
case "$ENVIRONMENT" in
production) echo "Prod mode" ;;
staging) echo "Staging mode" ;;
*) echo "Unknown: $ENVIRONMENT" ;;
esac
# Functions
log() { echo "[$(date '+%Y-%m-%d %H:%M:%S')] $*"; }
die() { log "ERROR: $*" >&2; exit 1; }
# Trap for cleanup
cleanup() { rm -f /tmp/lockfile; }
trap cleanup EXIT
# Command substitution and arithmetic
COUNT=$(ls /var/log | wc -l)
SIZE=$(( COUNT * 2 ))
Performance Troubleshooting
Load Average Interpretation
# uptime output: 10:00:00 up 5 days, load average: 1.50, 1.20, 0.90
# Load averages are for: last 1 min, 5 min, 15 min
# Rule of thumb: load > number_of_CPUs = overloaded
nproc # Number of CPU cores
lscpu | grep "CPU(s):"
# If load is 4.0 on a 4-core system = 100% utilized
# If load is 4.0 on a 8-core system = 50% utilized
# Identify load source:
# High CPU: top (check %CPU column)
# High I/O wait: iostat -x (check %iowait)
# Many processes: ps aux | wc -l
Memory & OOM Killer
# Check memory
free -h
cat /proc/meminfo
# Check OOM kills
dmesg | grep -i "out of memory"
dmesg | grep -i "oom"
journalctl -k | grep -i oom
# Find memory-hungry processes
ps aux --sort=-%mem | head -20
# Check OOM score (higher = more likely to be killed)
cat /proc/PID/oom_score
cat /proc/PID/oom_adj
# Protect a process from OOM killer
echo -1000 > /proc/PID/oom_score_adj # -1000 = never kill
Disk I/O Bottleneck
# Check disk I/O
iostat -x 2 5
# Look for: %util > 80%, await > 10ms, r/s or w/s spikes
# Find processes causing I/O
iotop -o # Show only active I/O processes
iotop -ao # Accumulated totals
# Find files being written to
lsof +D /var/log # Open files in directory
inotifywait -m -r /path/to/dir # Watch file system events
Security Hardening
SSH Configuration
# /etc/ssh/sshd_config hardening
Port 2222 # Non-standard port
ListenAddress 0.0.0.0
Protocol 2
PermitRootLogin no
PasswordAuthentication no
PubkeyAuthentication yes
AuthorizedKeysFile .ssh/authorized_keys
MaxAuthTries 3
LoginGraceTime 30
AllowUsers deploy admin
AllowGroups sshusers
ClientAliveInterval 300
ClientAliveCountMax 2
X11Forwarding no
AllowTcpForwarding no
PrintMotd yes
Banner /etc/issue.net
# Restart after changes
systemctl restart sshd
Firewall: firewalld / ufw
# firewalld (RHEL/CentOS/Fedora)
firewall-cmd --state
firewall-cmd --list-all
firewall-cmd --permanent --add-service=https
firewall-cmd --permanent --add-port=8080/tcp
firewall-cmd --permanent --remove-service=telnet
firewall-cmd --reload
# Rich rules
firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="10.0.0.0/8" service name="ssh" accept'
firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="1.2.3.4" drop'
# ufw (Debian/Ubuntu)
ufw status verbose
ufw allow 22/tcp
ufw allow from 10.0.0.0/8 to any port 5432
ufw deny 23
ufw enable
ufw reload
sysctl Security Parameters
# /etc/sysctl.d/99-security.conf
# Network hardening
net.ipv4.ip_forward = 0 # Disable IP forwarding (unless router)
net.ipv4.conf.all.send_redirects = 0
net.ipv4.conf.default.send_redirects = 0
net.ipv4.conf.all.accept_redirects = 0
net.ipv4.conf.all.accept_source_route = 0
net.ipv4.conf.all.log_martians = 1
net.ipv4.tcp_syncookies = 1 # SYN flood protection
net.ipv6.conf.all.accept_redirects = 0
# Kernel hardening
kernel.dmesg_restrict = 1 # Restrict dmesg to root
kernel.kptr_restrict = 2 # Hide kernel pointers
kernel.randomize_va_space = 2 # ASLR full
fs.suid_dumpable = 0 # Disable SUID core dumps
# Apply immediately
sysctl -p /etc/sysctl.d/99-security.conf
sysctl --system # Apply all
Tip — auditd: Enable
auditd for compliance and forensics. Key rules: -w /etc/passwd -p wa -k identity, -w /etc/sudoers -p rwa -k sudoers. Use ausearch -k sudoers to query audit logs.