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.

Back to Documents