CoursesLinux essentialsSystem info & monitoring

System info & monitoring

df, du, free, uname, uptime, date, who.

Beginner14 min · lesson 9 of 25

You log into a server over SSH (secure shell, the encrypted way you reach a remote machine's command line). You have never seen this box before. It could be running anything, doing anything, with other people logged in beside you. Before you touch a single service, you want the lay of the land: what is this machine, how hard is it working, and who else is here? A small set of commands answers all three. They are the light switch you hit when you walk into a dark room, and the first things you reach for when a box is slow, full, or acting strange.

Disk Space: df And du

A disk is like a filing cabinet with several drawers. df (short for "disk free") tells you how full each drawer is. du ("disk usage") tells you which folders inside a drawer got fat. You almost always run df first, because it is quick and it points you at the drawer that is about to overflow. Add -h for "human-readable" so you get 47G instead of a raw block count nobody can read at a glance.

~/secopslog — bash
$ df -h
Filesystem Size Used Avail Use% Mounted on tmpfs 794M 1.7M 792M 1% /run /dev/sda1 49G 46G 1.1G 98% / tmpfs 3.9G 0 3.9G 0% /dev/shm tmpfs 5.0M 0 5.0M 0% /run/lock /dev/sda15 105M 6.1M 99M 6% /boot/efi

Each row is one filesystem (one drawer). The column you read is Use%, and the row that usually bites you is the one mounted on / (the root of everything). Here it sits at 98%, with 1.1G to spare, so this box is minutes away from trouble. The tmpfs rows are storage that lives in memory rather than on the physical disk, so ignore those for now. When / hits 100%, programs can no longer write files, services start crashing, and, cruelly, the system may not even be able to log the errors it is throwing.

Once df names a full partition, du hunts down what is eating it. du -sh * summarizes each item in the current directory (-s for a single summed total per item, -h for human units). The one-liner engineers keep in muscle memory pipes that through a sort so the biggest offenders float to the top:

~/secopslog — bash
$ sudo du -sh /var/log/* | sort -rh | head
2.4G /var/log/journal 1.1G /var/log/nginx 412M /var/log/syslog 88M /var/log/auth.log 21M /var/log/dpkg.log

sort -rh means sort in reverse (-r, biggest first) by human-readable numbers (-h, so 2.4G outranks 412M correctly), and head shows the top few. Notice where the space went: /var/log, the folder where the system writes its diary. That folder matters for more than tidiness. When the disk fills, the diary stops, and during a break-in the diary is exactly what you want. A full /var (whether from a runaway process spewing gigabytes of errors, or filled on purpose to go quiet) is a cheap way for an attacker to blind you. Watching Use% on / and /var is plain hygiene, and it is worth a scheduled alert.

df Says Full, du Says Empty
A classic head-scratcher: df swears the disk is 100% full, but du adds up everything and finds nowhere near enough to explain it. The usual cause is a file that was deleted while a running process still had it open. On Linux the space is not returned until that process lets go, so the bytes are gone from du's view but still counted by df. Find the culprit with sudo lsof +L1 (or sudo lsof | grep deleted), then restart the process holding it (often a service still writing to a log file that someone rm'd). The space frees the instant the process closes the handle.

Memory: free

RAM (random-access memory, the fast working memory the machine uses for whatever it is doing right this second) is like your kitchen counter. Free counter space lets you start a new dish. Linux, being frugal, does not leave the counter bare: it spreads out ingredients it might reuse soon (recently read files) so nothing sits idle. That habit is why the "free" number looks alarmingly small on a healthy server, and why the column that actually answers "can I run more?" is "available".

~/secopslog — bash
$ free -h
total used free shared buff/cache available Mem: 7.7Gi 2.1Gi 231Mi 112Mi 5.4Gi 5.3Gi Swap: 2.0Gi 0B 2.0Gi

Read it left to right. used is memory held by running programs. free is memory nobody has touched at all. buff/cache (buffers and cache, memory the kernel borrowed to keep recently used files handy) is that counter full of reusable ingredients, and the kernel hands it straight back the moment a program asks. available is the honest estimate of what a new program could grab, roughly free plus the reclaimable cache. So 231Mi free looks scary, but 5.3Gi available is the truth: this box is fine. Swap is overflow space on disk; when real RAM runs out, the kernel spills memory pages there, and everything slows to a crawl because disk is far slower than RAM. If RAM is genuinely exhausted with swap also full, the kernel's OOM killer (out-of-memory killer) picks a process and kills it to keep the system alive, which is how a database quietly dies at 3am. A memory leak or a fork bomb shows its face right here first.

What It Is And How Long: uname, uptime, date

uname -a is the machine's ID card. In one line it prints the kernel name, the hostname, the kernel version and build, and the CPU architecture (the kernel is the core of the operating system, the part that talks directly to the hardware). For DevSecOps work the kernel version is the interesting field. Local privilege-escalation exploits (tricks that turn an ordinary user into the all-powerful root account) are written against specific kernel versions, and each known hole gets a CVE number (common vulnerabilities and exposures, the industry's catalog of publicly tracked bugs). Knowing you are on 5.15.0-89 tells you exactly what to look up and what to patch. For the distribution name and release, read /etc/os-release.

~/secopslog — bash
$ uname -a uname -r
Linux web-01 5.15.0-89-generic #99-Ubuntu SMP Mon Oct 30 18:18:09 UTC 2023 x86_64 x86_64 x86_64 GNU/Linux 5.15.0-89-generic
/etc/os-release
PRETTY_NAME="Ubuntu 22.04.3 LTS"
NAME="Ubuntu"
VERSION_ID="22.04"
VERSION="22.04.3 LTS (Jammy Jellyfish)"
VERSION_CODENAME=jammy
ID=ubuntu
ID_LIKE=debian
HOME_URL="https://www.ubuntu.com/"
SUPPORT_URL="https://help.ubuntu.com/"

uptime tells you how long since the last boot, and how hard the CPU (central processing unit, the chip that runs the work) is being pushed. Thirty-seven days of uptime can mean rock-solid stability, or it can mean the box has missed a month of kernel security fixes, because a new kernel only takes effect after a reboot. The three numbers at the end are the load average: the average number of processes that were either running on the CPU or waiting in line for it, measured over the last 1, 5, and 15 minutes. One wrinkle worth knowing: on Linux that count also folds in processes stuck waiting on the disk, so a box with idle CPU cores can still show a high load when slow storage is the real bottleneck. Think of checkout lanes at a store. Compare the load to how many lanes you have (run nproc to count CPU cores). On a 4-core box, 4.0 means every lane busy with no queue; 8.0 means a line is forming and things feel slow; and reading the three numbers together tells you whether it is getting worse or recovering.

~/secopslog — bash
$ uptime nproc
10:42:15 up 37 days, 4:20, 2 users, load average: 0.15, 0.22, 0.19 4

date prints the clock, which sounds too trivial to matter. It is not. A wrong clock quietly breaks security. TLS certificates (transport layer security, the padlock behind https) are only valid inside a date range, so a machine with a skewed clock will reject good certificates or trust expired ones. Logs from ten servers cannot be lined up into a single timeline if their clocks disagree, and lining up a timeline is exactly what you do during an incident. TOTP codes (time-based one-time password, the rotating 6-digit numbers) stop matching. That is why servers sync to NTP (network time protocol), and you check the sync with timedatectl.

~/secopslog — bash
$ date timedatectl
Fri Jul 3 10:42:15 UTC 2026 Local time: Fri 2026-07-03 10:42:15 UTC Universal time: Fri 2026-07-03 10:42:15 UTC RTC time: Fri 2026-07-03 10:42:15 Time zone: Etc/UTC (UTC, +0000) System clock synchronized: yes NTP service: active RTC in local TZ: no

Who Is On The Box: who, w, id, history

who and w are like walking into an office and glancing around to see who is at their desk. who lists the logged-in users, which terminal each is on (pts/0 means pseudo-terminal zero, a remote login session), when they logged in, and the address they came from. w adds what each person is doing right now. id is your own badge: it prints your UID (user ID, the number that actually decides your permissions), your GID (group ID), and every group you belong to.

~/secopslog — bash
$ whoami id who w
deploy uid=1000(deploy) gid=1000(deploy) groups=1000(deploy),27(sudo),988(docker) deploy pts/0 2026-07-03 10:14 (10.0.1.5) admin pts/1 2026-07-03 10:40 (10.0.1.9) 10:42:15 up 37 days, 4:20, 2 users, load average: 0.15, 0.22, 0.19 USER TTY FROM LOGIN@ IDLE JCPU PCPU WHAT deploy pts/0 10.0.1.5 10:14 0.00s 0.35s 0.03s w admin pts/1 10.0.1.9 10:40 2:15 0.10s 0.10s -bash

With id, the groups matter more than the username. Membership in the sudo group (called wheel on some systems) means this account can become root, the administrator that can do anything. The docker group is effectively root too, because anyone who can start containers can mount the host's whole disk. So id is the first thing you check to understand what you are allowed to do here, and, when you are auditing an account, whether it carries powers it has no business holding. The deploy user above is in both sudo and docker, which is a lot of trust for a name that sounds like a service account.

who and its cousin last are your early-warning system. On an unfamiliar or possibly-compromised box, a session in who coming from an IP address you do not recognize is a smoke alarm going off. last reads the login history (who logged in, from where, when, and whether they are still on), and lastb shows the failed attempts, which is where a brute-force attack against SSH leaves its fingerprints.

~/secopslog — bash
$ last -a | head -4 sudo lastb -a | head -3
admin pts/1 Fri Jul 3 10:40 still logged in 10.0.1.9 deploy pts/0 Fri Jul 3 10:14 still logged in 10.0.1.5 admin pts/0 Thu Jul 2 22:03 - 23:15 (01:12) 10.0.1.9 reboot system boot Wed May 27 06:22 still running 5.15.0-89-generic root ssh:notty Fri Jul 3 09:58 - 09:58 (00:00) 203.0.113.44 root ssh:notty Fri Jul 3 09:57 - 09:57 (00:00) 203.0.113.44 admin ssh:notty Fri Jul 3 09:41 - 09:41 (00:00) 198.51.100.7

Those failed logins for root from a couple of random addresses are exactly what an automated password-guessing sweep looks like. One last tool: history prints the commands run from your own shell, saved in a hidden file called ~/.bash_history. It is a memory aid for recalling that long command from Tuesday, and it doubles as evidence, because an attacker's commands land there too, right up until they wipe it (a common move is pointing HISTFILE at /dev/null or running history -c). An empty or oddly short history on a shared account is itself a small red flag. Do not treat it as a trustworthy audit trail, though; the system's own auth.log and auditd (the Linux audit daemon, which records security events to a separate, harder-to-tamper log) are the record that holds up.

~/secopslog — bash
$ history | tail -5
510 free -h 511 df -h 512 sudo du -sh /var/log/* | sort -rh | head 513 sudo lsof +L1 514 systemctl restart nginx
Your First Two Minutes On A Strange Box
What is it
uname -a
kernel version + architecture
/etc/os-release
distro name + release
uptime
days since last boot
How is it doing
df -h
disk full? read Use% on /
free -h
memory? read 'available'
uptime + nproc
load vs core count
Who is here
id
your UID, GID, groups
who / w
live sessions + source IPs
last / lastb
login history + failed tries
Three questions, and the commands that answer each. Run the sweep every time you land somewhere new.
Quick check
01A server feels sluggish. free -h shows total 7.7Gi, free 231Mi, but available 5.3Gi. Are you out of memory?
Correct — 'available' is the honest figure, and the kernel hands cache back the moment a program needs it.
Incorrect — 'free' ignores reclaimable cache; the number that counts is 'available', and it is high.
Incorrect — The output shows 0B of swap in use, and available memory is large, so nothing points to swap.
Incorrect — df measures disk, not memory. free already answers the memory question on its own.
02You are auditing an account and id prints groups=1000(deploy),27(sudo),988(docker). Beyond sudo, why does the docker membership deserve equal scrutiny?
Incorrect — the docker group can start containers, which is far more than reading logs.
Correct — container access to the host filesystem makes docker-group membership equivalent to root.
Incorrect — group membership does not block running commands; it grants use of the Docker daemon.
Incorrect — it is not mandatory, and it grants powerful, root-equivalent access to the container runtime.
03df -h says / is 100% full, but adding up du -sh across the filesystem accounts for far less than the disk's size. What is the most likely cause and fix?
Incorrect — du is fine; it simply cannot see space held by a file that has already been unlinked.
Incorrect — the two numbers disagreeing is a normal accounting effect, not a sign of failing hardware.
Correct — space for a deleted-but-open file still counts in df but not du until the holder closes the handle.
Incorrect — df measures disk usage, the same resource du sums; they should roughly agree when nothing is held open.

One habit is worth burning in: on a box you think has been tampered with, run last and lastb before you touch anything else. The moment you start restarting services and clearing disk space to make the box healthy again, you begin overwriting the very evidence of what went wrong, the login records, the open files, the shell history. Look before you fix. Capture what the machine is telling you, then go clean it up.

Try this

Work through “Who Is On The Box: who, w, id, history” yourself on a sandbox you can throw away, following the commands above in order. Then break one step deliberately and re-run, so you have seen the failure before it finds you.

Takeaway

The trap worth remembering here: df Says Full, du Says Empty. Check that on your own systems before you need to, because it is cheaper to find on a quiet afternoon than during an incident.

Related