DEV Community

Cover image for Best Linux Commands for Developers and Sysadmins
devTalk
devTalk

Posted on Originally published at dev-talk.com

Best Linux Commands for Developers and Sysadmins

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
Enter fullscreen mode Exit fullscreen mode

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)
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

-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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

-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
Enter fullscreen mode Exit fullscreen mode

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'
Enter fullscreen mode Exit fullscreen mode

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)
Enter fullscreen mode Exit fullscreen mode

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/
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

10. "What is eating memory?": ps

ps aux --sort=-%mem | head -5
free -h
Enter fullscreen mode Exit fullscreen mode

--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)