Useful Linux commands I actually use (and why)
Linux is one of those things that feels "basic"... until you're on call, production is on fire, and you need one command to confirm a hypothesis right now.
This post is not a random cheatsheet. It's a small list of commands I keep coming back to when I'm debugging systems, migrations, data pipelines, and "why is this service slow?" situations.
Rule of thumb: start with observation, not with changing stuff. These commands help you observe fast.
watch — when you need a live view (without writing code)
Sometimes there's no async way to get state (no events, no UI, no metrics you trust yet) and you end up polling: progress endpoints, counters, queue sizes, replication lag, etc.
watch runs a command every n seconds and refreshes the output.
watch -n 1 'curl -s localhost:27182/api/v1/progress -X GET | jq .'
Why it's useful
- quick "poor man's dashboard"
- great for long-running operations (migrations, backfills, rebalances)
Pro tips
- Add
-dto highlight diffs between refreshes:watch -n 1 -d 'curl -s localhost:27182/api/v1/progress | jq .' - If the output is JSON, pipe through
jqand keep the filter simple (start with.).
(If you forget the filter,jqwon't behave how you expect.)
scp — quick file copy over SSH (when you can't be bothered with S3)
Copy a file from a remote VM to your laptop:
scp -i "david-sanchez-key.pem" ec2-user@ec2-1-10-15-121.eu-west-1.compute.amazonaws.com:/home/ec2-user/logs.log /Users/user/Downloads/
Copy a file from your laptop to the VM:
scp -i "david-sanchez-key.pem" /Users/folder1/logs.log ec2-user@ec2-1-10-15-121.eu-west-1.compute.amazonaws.com:/home/ec2-user/
Replace:
- path to the key
- VM username
- VM hostname
- remote path
- local destination path
Pro tips
- Copy a whole folder (recursive):
-r - If SSH is on a non-standard port:
-P 2222 - If you're copying big files regularly, use
rsync(below).scpis fine for "get me that log now".
rsync — scp, but grown up (fast + resumable)
rsync is my default when:
- files are large
- connections are flaky
- I want progress + resume
- I'm syncing directories
rsync -avP -e "ssh -i david-sanchez-key.pem" ec2-user@ec2-1-10-15-121.eu-west-1.compute.amazonaws.com:/home/ec2-user/exports/ ./exports/
Flags I use:
-aarchive mode (preserves permissions/timestamps)-vverbose-Pprogress + partial (resume-friendly)
tail + grep — the "I need the signal, not the noise" combo
Follow logs live:
tail -f /var/log/syslog
Follow logs and filter:
tail -f /var/log/syslog | grep -i error
Pro tip: show context lines around matches:
grep -i -n -C 2 "timeout" /var/log/syslog
-nline numbers-C 2two lines of context above and below
journalctl — systemd logs without guessing where the file is
On many modern Linux distros, services log to systemd.
journalctl -u myservice -f
Useful variations:
journalctl -u myservice --since "1 hour ago"
journalctl -u myservice -n 200
ss — what's listening on this box? (and who owns it)
When someone says "the port is open" and you don't trust them:
ss -lntp
-llistening-nnumeric (no DNS)-tTCP-pprocess info
If you want to focus on a port:
ss -lntp | grep ":27017"
lsof — "who is using this file/port?"
Classic "why can't I delete this file?" or "who has this port?"
lsof -i :27017
lsof /path/to/file
curl — when you need to test a service like a machine would
Two patterns I use constantly:
1) show timing breakdown
curl -s -o /dev/null -w "dns:%{time_namelookup} connect:%{time_connect} ttfb:%{time_starttransfer} total:%{time_total}\n" https://example.com
2) fail fast (so scripts don't pretend everything is OK)
curl -fsS https://example.com/health
-ffail on HTTP errors-sSsilent, but still show errors
jq — JSON sanity without opening a browser
Pretty print:
curl -s https://api.example.com/status | jq .
Extract only what you care about:
curl -s https://api.example.com/status | jq -r '.progress.percentage'
find — locate files fast (and safely)
Find big log files:
find /var/log -type f -size +100M -print
Find and delete (careful):
find /tmp -type f -name "*.tmp" -mtime +7 -print
# if it looks correct, then:
# find /tmp -type f -name "*.tmp" -mtime +7 -delete
I always run the -print version first. Always.
Tiny checklist: what I run first in a "something is slow" incident
- Is the service even up?
curl -fsS http://localhost:8080/health
- Are we CPU/mem bound?
top
- Are we network/ports bound?
ss -lntp
- Do logs show errors/timeouts?
journalctl -u myservice --since "30 min ago"
That sequence alone finds a surprising amount of issues.