Most "top Linux commands" lists give you ls, cd and pwd and call it a day. You already know those. This list is organised by the problems you actually hit on a server: the disk is full, something is using your port, one endpoint is slow, a log has a million lines. Every command below was run on Ubuntu 24.04 with GNU coreutils, and the outputs are from those runs, using a small sandbox with a fake Laravel-style folder and a generated access log.
1. "The disk is filling up": du and find
du -h --max-depth=1 app | sort -h
# 12K app/public
# 792K app/storage
# 2.9M app/vendor
# 3.7M app
find app -type f -size +500k -printf '%s %p\n' | sort -rn
# 3000000 app/vendor/big.bin
# 800000 app/storage/logs/laravel.log
The first command sizes each folder one level deep, and sort -h understands K, M and G suffixes so the biggest is last. The second lists individual large files. Run the first one at /var or your project root and drill down. (--max-depth is the GNU spelling; on macOS use -d 1.)
2. "I deleted the log but the space did not come back": lsof +L1
If a process still has a file open when you delete it, the disk space stays allocated until that process closes it or exits. This is a classic cause of a full disk that du cannot explain. List open files that have been unlinked:
lsof -nP +L1
# tail 260 root 3r REG 254,0 20000000 0 1001125 /path/to/big.log (deleted)
I created a 20 MB file, kept it open with tail -f, deleted it, and lsof showed it with a link count of 0 and the word (deleted). The fix is to restart or signal the owning process (for a log, ask it to reopen its files). At 20 MB the change was too small to show in df -h, so I am not claiming a number there, but the mechanism is the one that bites on production servers with multi-gigabyte logs.
3. "What is using this port?": ss
ss -ltnp | grep 8765
# LISTEN 0 5 127.0.0.1:8765 0.0.0.0:* users:(("python3",pid=252,fd=3))
lsof -nP -iTCP:8765 -sTCP:LISTEN
-l listening, -t TCP, -n no name lookups, -p show the process. You usually need sudo to see processes owned by other users. ss replaces the older netstat and is installed by default on current Ubuntu.
4. "Who is hitting my server?": awk, sort, uniq
awk '{print $9}' access.log | sort | uniq -c | sort -rn
# 794 200
# 113 404
# 52 301
# 41 500
awk '{print $1}' access.log | sort | uniq -c | sort -rn | head -3
# 539 10.0.0.1
# 192 10.0.0.2
# 125 10.0.0.3
awk '$9 ~ /^5/ {print $7}' access.log | sort | uniq -c | sort -rn | head -3
# 8 /p3
# 7 /p1
# 7 /p0
This is the pattern worth memorising: extract a field, sort, uniq -c to count, sort -rn to rank. The field numbers ($9 is the status code, $7 the path, $1 the client IP) are for the standard combined log format, so check your own format first. Always sort before uniq, because uniq only collapses adjacent duplicates.
5. "Where is this string used?": grep
grep -rn "TODO" app --include='*.php'
# app/public/b.php:1:<?php // TODO fix
-r recurses, -n prints line numbers, and --include limits the search to the file types you care about so you do not grep through vendor binaries. If you have ripgrep (rg) installed, it is faster and skips ignored files by default, but plain grep is on every server.
6. "Clean up old files without regret": find with -print first
find app/storage/logs -name '*.log' -mtime +7 -print # look first
find app/storage/logs -name '*.log' -mtime +7 -delete # then delete
In the test, the first command listed old1.log and old2.log (back-dated 10 days) and left laravel.log alone; the second removed only those two. Run the exact same expression with -print before you swap in -delete. Put -delete last, because find evaluates the expression left to right.
7. "Do this to 1,000 files, faster": xargs -P
find imgs -name '*.txt' -print0 | xargs -0 -n1 -P4 sh -c 'sleep 0.5'
Eight tasks that each take half a second ran in about 1.0 seconds with -P4 and 4.0 seconds serially. -print0 with -0 keeps filenames with spaces intact, -n1 passes one file per command, and -P4 runs four at a time. Use it for image conversion, compression, or any CPU-bound per-file job, and keep -P near your core count.
8. "Copy this safely": rsync --dry-run
rsync -avh --delete --dry-run src/ dst/
# deleting old
# a
# b
# (DRY RUN)
With --delete, rsync removes files in the destination that are not in the source. The dry run shows exactly that, deleting old, before anything happens. Drop --dry-run only when the list looks right. The trailing slash on src/ matters: it means "the contents of src", not the folder itself.
9. "Why is this endpoint slow?": curl -w
curl -sS -o /dev/null -w 'code=%{http_code} connect=%{time_connect}s ttfb=%{time_starttransfer}s total=%{time_total}s\n' https://example.com/
Against a local test server this printed code=200 connect=0.000518s ttfb=0.005061s total=0.005155s. Against a real site, a large gap between connect and ttfb means the server is slow to respond; a slow connect points at the network. Pipe JSON APIs through jq next:
echo '{"items":[{"name":"a","ok":true},{"name":"b","ok":false}]}' | jq -r '.items[] | select(.ok==false) | .name'
# b
10. "What is eating memory?": ps
ps aux --sort=-%mem | head -5
free -h
--sort=-%mem puts the biggest memory user first. The columns RSS (resident memory in KB) and %MEM are the ones to read.
Frequently asked questions
Should I learn grep or ripgrep?
Learn grep first because it exists on every server. Add rg on your own machine for speed.
Why does uniq -c show the same line twice?
Because the input was not sorted. uniq only merges adjacent duplicates, so put sort in front of it.
Are these commands the same on macOS?
Mostly, but some flags are GNU-specific, such as du --max-depth, find -printf and sort -h on older systems. On macOS use du -d 1 or install GNU coreutils.
Originally published on DEV Talk.
Top comments (0)