# Linux Commands Cheat Sheet for Server Admins

Source: https://srvscripts.com/guides/linux-commands-cheat-sheet/
Updated: 2026-10-06
Publisher: srvScripts (https://srvscripts.com/)

**Short answer:** The commands you will use most on a Linux server are `df -hT` and `du` for disk, `free -h`, `ps` and `top` for memory and processes, `systemctl` and `journalctl` for services and logs, `ip`, `ss -tulpn` and `dig` for networking, and `dnf` (AlmaLinux, Rocky, RHEL) or `apt` (Debian, Ubuntu) for packages. The tables below group them by task, with the flags that matter on a production box.

We ran these commands on our lab servers on 7 October 2026: AlmaLinux 9.8 with cPanel & WHM 11.138 (dnf, systemd and general commands) and Debian 12.15 (apt and dpkg commands). Read-only commands ran as shown. `tar`, `rsync`, `sed -i`, `find -delete` and `kill` ran only on test files we created and then removed. Commands that change the system (service restarts, `useradd`, `passwd -l`, package installs, `set-timezone`) were checked against each tool’s `--help` output on the same servers, but not run, because our lab rules forbid changes.

## Files and disk space

| Command | What it does |
| --- | --- |
| df -hT | Free space per filesystem, human sizes, with filesystem type |
| df -i / | Inode usage. A disk can be “full” with free GB left if inodes run out |
| du -xh --max-depth=1 /var | sort -rh | head | Biggest directories one level down, staying on one filesystem (-x) |
| ncdu -x / | Interactive disk browser. Not installed by default: EPEL on AlmaLinux (we saw ncdu 1.22 there), main repo on Debian |
| find /home -xdev -type f -size +100M | Files larger than 100 MB |
| find /var/log -type f -name "*.gz" -mtime +30 | Compressed logs older than 30 days |
| lsof +L1 | Deleted files still held open. Their space is not freed until the process restarts |
| lsof -i :443 -sTCP:LISTEN | Which process listens on a port |

Real output from our AlmaLinux lab (the `-x tmpfs -x devtmpfs` options hide memory-backed filesystems):

```
# df -hT -x tmpfs -x devtmpfs
Filesystem     Type  Size  Used Avail Use% Mounted on
/dev/vda1      ext4   79G   13G   62G  18% /
/dev/loop0     ext4  3.4G   68M  3.1G   3% /tmp
```

When `df` says the disk is full but `du` cannot find the space, run `lsof +L1`. A log file deleted while Apache or MariaDB still has it open keeps using space. Restart that service, or truncate the file through `/proc/<pid>/fd/`. On our lab, `lsof +L1` listed only small Dovecot and dbus files, which is normal.

Before you delete by age, run the same `find` with `-print`, read the list, then swap `-print` for `-delete`:

```
find /var/log/myapp -name "*.log" -mtime +30 -print    # review first
find /var/log/myapp -name "*.log" -mtime +30 -delete   # then delete
```

For a full cleanup procedure on a hosting server, see our [disk full runbook](/guides/runbook-disk-full/).

## Processes and memory

| Command | What it does |
| --- | --- |
| uptime | Load average for 1, 5 and 15 minutes. Compare with the CPU count from nproc |
| top / htop | Live view. In top, press M to sort by memory, P by CPU. htop was installed on our cPanel lab |
| top -b -n1 | head -15 | One snapshot, good for pasting into a ticket |
| ps aux --sort=-%mem | head | Processes using the most memory |
| ps -eo pid,user,%cpu,%mem,etime,cmd --sort=-%cpu | head | Custom columns, including how long each process has run |
| pgrep -a sshd | PIDs and command lines matching a name |
| free -h | RAM and swap. Read the available column, not free |
| vmstat 1 5 | Five one-second samples. High si/so means swapping; high wa means waiting on disk |
| kill PID | Ask a process to stop (SIGTERM) |
| kill -9 PID | Force-kill (SIGKILL). Last resort: the process cannot clean up |

```
# free -h
               total        used        free      shared  buff/cache   available
Mem:           3.8Gi       1.7Gi       313Mi        71Mi       1.9Gi       2.1Gi
Swap:          127Mi       127Mi       0.0Ki
```

On our 4 GB cPanel lab only 313 MB is “free”, but 2.1 GB is available, because the kernel drops cache when an application needs memory. The swap is full, which is worth a look, but it is not an emergency while `vmstat` shows `si` and `so` at 0.

## Services and logs (systemctl and journalctl)

| Command | What it does |
| --- | --- |
| systemctl status nginx | State, main PID, and the last log lines |
| systemctl restart nginx | Stop and start. reload rereads config without dropping connections, if the service supports it |
| systemctl enable --now nginx | Start now and at every boot |
| systemctl is-active httpd crond | One word per unit; handy in scripts |
| systemctl --failed | Every failed unit. Check this first after a reboot |
| systemctl list-timers | systemd timers, with next and last run times |
| systemctl cat crond | The unit file, including any drop-in overrides |
| systemctl daemon-reload | Required after you edit a unit file |
| journalctl -u sshd --since "1 hour ago" | Logs for one unit in a time window |
| journalctl -p err -b | Errors and worse since the last boot |
| journalctl -u nginx -f | Follow new lines live, like tail -f |
| journalctl -k | Kernel messages (OOM killer, disk errors) |
| journalctl -g "Failed password" -u sshd | Grep inside the journal |
| journalctl --disk-usage | Space used by the journal |
| journalctl --vacuum-time=14d | Delete archived journal files older than 14 days |

On our cPanel lab, `systemctl --failed` immediately showed a real problem:

```
# systemctl --failed
  UNIT                LOAD   ACTIVE SUB    DESCRIPTION
● cpgreylistd.service loaded failed failed cPanel Greylisting Daemon
```

On AlmaLinux 9 servers without rsyslog, `/var/log/secure` may be empty or missing. Our lab had no rsyslog package and a 0-byte `/var/log/secure`, yet the journal held over 1,000 failed SSH passwords from the last 24 hours. If a log file looks empty, ask `journalctl` instead.

The unit name for SSH is `sshd` on AlmaLinux and `ssh` on Debian and Ubuntu. Check with `systemctl list-unit-files | grep ssh`. For timer files, our [systemd unit generator](/tools/systemd-unit-generator/) writes them with safe defaults.

## Networking

| Command | What it does |
| --- | --- |
| ip -br addr | One line per interface with its addresses |
| ip route show default | Default gateway(s) |
| ss -tulpn | Listening TCP and UDP sockets with the owning process (replaces netstat -tulpn) |
| ss -tn state established "( dport = :443 or sport = :443 )" | Live connections on port 443 |
| ping -c 3 203.0.113.10 | Three pings and a loss summary |
| mtr -rwc 10 -n 203.0.113.10 | Report mode: loss and latency per hop, no DNS lookups |
| traceroute -n 203.0.113.10 | Path to a host |
| dig +short example.com A | DNS answer only |
| dig @1.1.1.1 example.com NS +short | Ask a specific resolver |
| dig -x 203.0.113.10 +short | Reverse DNS (PTR) |
| curl -I https://example.com | HTTP status and response headers only |
| curl -s -o /dev/null -w "%{http_code} %{time_total}s\n" https://example.com | Status code and total time, for quick checks |

In `mtr`, 100% loss on a middle hop that later hops do not show is usually a router that ignores ICMP, not a fault. We saw exactly that on hops 1 and 4 from our lab. Only loss that continues to the final hop matters. Our [online traceroute](/tools/traceroute-online/) runs the same test from other countries.

Packages on minimal installs: `dig` comes from `bind-utils` on AlmaLinux (`dnf provides /usr/bin/dig` told us) and from `bind9-dnsutils` on Debian 12.

## Users, permissions and sudo

| Command | What it does |
| --- | --- |
| id bob | UID, GID and groups |
| useradd -m -s /bin/bash -G wheel bob | Create a user with a home directory, bash, and the wheel group (sudo on AlmaLinux; use sudo on Debian) |
| usermod -aG wheel bob | Add to a group. Without -a, -G replaces all supplementary groups |
| passwd -l bob / passwd -u bob | Lock / unlock the password. SSH keys still work, so also expire the account or remove keys |
| usermod -L -e 1 bob | Lock the password and expire the account, which stops key logins too |
| passwd -S bob | Password status (locked, set, algorithm) |
| chage -l bob | Password and account expiry dates |
| chmod 640 file / chmod -R u+rwX dir | Set permissions (capital X adds execute only to directories) |
| chown -R bob:bob /home/bob/app | Change owner and group recursively |
| sudo -l | What the current user may run with sudo |

`chown -R` and `chmod -R` on the wrong path can break a whole server, for example on `/` or `/home`. Record the current state first with `getfacl -R dir > perms.acl` (restore with `setfacl --restore=perms.acl`), and double-check the path before you press Enter.

Need the octal value for a permission set? Use our [chmod calculator](/tools/chmod-calculator/).

## Packages: dnf and apt side by side

| Task | AlmaLinux / Rocky / RHEL (dnf) | Debian / Ubuntu (apt) |
| --- | --- | --- |
| Refresh package lists | automatic (force with dnf makecache --refresh) | apt update |
| List available updates | dnf check-update | apt list --upgradable |
| Security updates only | dnf updateinfo list --security | from the -security suite (shown by apt list) |
| Install updates | dnf upgrade | apt upgrade |
| Install a package | dnf install mtr | apt install mtr |
| Remove a package | dnf remove mtr | apt remove mtr |
| Is it installed? Which version? | rpm -q openssh-server | dpkg -l openssh-server |
| Which package owns a file? | rpm -qf /usr/sbin/sshd | dpkg -S /usr/sbin/sshd |
| Which package provides a command? | dnf provides /usr/bin/dig | apt-file search bin/dig (needs the apt-file package) |
| Package details | dnf info curl | apt show curl |
| Installed vs candidate version | dnf list --installed curl | apt-cache policy curl |
| History | dnf history list | /var/log/apt/history.log |

On our Debian 12 lab, `apt list --upgradable` showed pending security updates for `libpng16-16` and `linux-image-amd64`, and the suite shows as `oldstable-security` because Debian 13 is now the stable release. On AlmaLinux, `dnf updateinfo list --security` listed the kernel advisory ALSA-2026:74438. Add `-C` to dnf commands to read the local cache without contacting the mirrors.

On cPanel servers, do not remove or downgrade packages that cPanel manages (EA4, MariaDB, cpanel-*). Let `upcp` handle them, and see our [upcp failed guide](/guides/cpanel-upcp-failed-upgrade-blocked/) if updates stop.

## Archives and file transfer

| Command | What it does |
| --- | --- |
| tar -czf site.tar.gz -C /srv site | Create a gzip archive of /srv/site with relative paths |
| tar -tzf site.tar.gz | List the contents without extracting |
| tar -xzf site.tar.gz -C /restore | Extract into a chosen directory |
| rsync -avhn --delete src/ dst/ | Dry run (-n) that shows what a mirror would change |
| rsync -avh -e "ssh -p 2222" src/ bob@203.0.113.10:/backup/ | Copy over SSH on a custom port |
| scp -P 2222 file bob@203.0.113.10:/tmp/ | Single file over SSH. Note capital -P for the port in scp |

The trailing slash matters in rsync: `src/` copies the contents of src, while `src` creates `dst/src`. We tested this flow on scratch data:

```
rsync -a src/ mirror/            # first copy
echo change >> src/f1.txt
rsync -avhn --delete src/ mirror/  # dry run: lists only f1.txt
rsync -avh --delete src/ mirror/   # real run after you read the list
```

`--delete` removes files in the destination that are not in the source. Swapping source and destination by mistake wipes your data, so always run with `-n` first.

## Text processing: grep, awk, sed, sort | uniq -c

| Command | What it does |
| --- | --- |
| grep -rn "DB_HOST" /var/www/ | Recursive search with line numbers |
| grep -rl "eval(base64" /home/*/public_html | Only the names of files that match |
| awk '{print $9}' access_log | sort | uniq -c | sort -rn | Count HTTP status codes in a combined-format log |
| awk '{s+=$10} END {print s/1024/1024 " MB"}' access_log | Sum bytes sent |
| awk -F: '$3>=1000 {print $1}' /etc/passwd | Normal (non-system) users |
| sed -n '100,120p' file | Print lines 100 to 120 |
| sed -i.bak 's/old/new/' file | Edit in place and keep file.bak |

Top sources of failed SSH passwords in the last 24 hours, straight from the journal:

```
journalctl -u sshd --since "24 hours ago" --no-pager \
  | grep "Failed password" | grep -oE "from [0-9.]+" \
  | sort | uniq -c | sort -rn | head
```

```
     55 from x.x.x.x
     46 from x.x.x.x
     46 from x.x.x.x
```

Swap the pattern for `grep -oP "Invalid user \K\S+"` to see which usernames bots try. On our lab, the top guesses were `admin` and `ubuntu`.

## Cron and time

| Command | What it does |
| --- | --- |
| crontab -l | Current user’s cron jobs (crontab -l -u bob for another user, as root) |
| crontab -e | Edit them safely (syntax is checked on save) |
| ls /etc/cron.d /etc/cron.daily | System-wide jobs that crontab -l does not show |
| journalctl -u crond --since today | Did the job run? (unit is cron on Debian) |
| timedatectl | Time zone, UTC time and whether the clock is synced |
| timedatectl set-timezone UTC | Change the time zone |
| chronyc tracking | NTP offset and stratum (chrony is the default on AlmaLinux) |

Build schedules without guessing fields with our [cron expression helper](/tools/cron-expression-helper/).

## Security quick checks

| Command | What it shows |
| --- | --- |
| last -a -n 20 | Recent logins and reboots, with source host |
| lastb -n 20 | Recent failed logins (root only; reads /var/log/btmp) |
| w | Who is logged in right now, and what they are running |
| ss -tulpn | Every listening port. Anything you cannot explain needs a look |
| systemctl list-unit-files --state=enabled | Everything that starts at boot |
| find / -xdev -perm -4000 -type f | SUID binaries; compare with a known-good list |
| rpm -Va / debsums -c | Package files whose checksum changed (debsums is a separate package; it was not installed on our Debian lab) |

These are triage commands, not an audit. For a structured check, run our [server security audit script](/scripts/server-security-audit/). If you think the server is already compromised, follow the [incident response runbook](/guides/runbook-server-compromised/) and do not reboot first.

**Official documentation:** [journalctl man page](https://man7.org/linux/man-pages/man1/journalctl.1.html) · [ss man page](https://man7.org/linux/man-pages/man8/ss.8.html) · [RHEL 9: Managing software with DNF](https://docs.redhat.com/en/documentation/red_hat_enterprise_linux/9/html/managing_software_with_the_dnf_tool/index) · [Debian Reference: package management](https://www.debian.org/doc/manuals/debian-reference/ch02.en.html)

**Related:** [Disk full on a production server: recovery runbook](/guides/runbook-disk-full/) · [Harden SSH AlmaLinux 9: Secure Setup in 15 Minutes](/guides/harden-ssh-almalinux-9/) · [CSF Commands Cheat Sheet: Allow, Deny, Ports and Tempbans](/guides/csf-commands-cheat-sheet/) · [Multi-Server Health Check over SSH](/scripts/multi-server-health-check/) · [AI Command Explainer and Risk Checker for Linux and PowerShell](/tools/ai-command-explainer/)

## Frequently asked questions

### What replaced netstat on modern Linux?

ss, which is part of iproute2, the same package as the ip command. ss -tulpn gives the same listening-port view as netstat -tulpn. netstat comes from the older net-tools package; it was installed on both our labs, but you cannot count on it everywhere.

### Why does df show a full disk when du shows free space?

Usually a deleted file is still held open by a running process. lsof +L1 lists those files; restart the process that holds them and the space is released.

### Where are the SSH login logs on AlmaLinux 9?

In the systemd journal. /var/log/secure only fills up when rsyslog is installed and running. Use journalctl -u sshd to read them either way.

### How do I lock a Linux user without deleting it?

passwd -l bob locks the password only, so SSH keys still work. usermod -L -e 1 bob locks the password and expires the account, which blocks key logins too.

### What is the dnf equivalent of apt update?

dnf refreshes its metadata automatically when it is older than the configured expiry, so there is no separate step. dnf makecache –refresh forces a refresh, and dnf check-update lists available updates.
