Administering Linux isn’t just about memorizing commands. Many of the differences between resolving an issue in ten minutes or spending an hour testing things often come down to small habits: checking before touching, verifying what has changed, saving evidence before restarting, and confirming the outcome of each action. These simple practices are useful whether managing a home server or overseeing production systems.
The keys to good Linux habits in 20 seconds
- Before restarting a service, it’s wise to review its status and recent logs.
journalctl,ss,findmnt, orvmstathelp to understand what’s actually happening.- Destructive commands should be tested with options like
--dry-runfirst. - In automation, errors should be checked, and reliance on the terminal environment should be minimized.
- Documenting incidents prevents investigating the same problem twice.
Applying these practices doesn’t require installing an observability platform; many of the necessary tools are included in any modern distribution.
The core idea is to change a very human tendency: stop testing solutions before understanding the problem.
Before fixing Linux, ask it what’s happening
When a website stops responding, a database appears locked, or a service crashes, rebooting often seems like the quickest fix.
For example:
systemctl restart nginxSometimes it works.
The issue is that this also changes system state and may cause useful information to disappear—details that help identify the root cause.
Before rebooting, it’s much more informative to run:
systemctl status nginxThen, review recent messages:
journalctl -u nginx --since "-15 min"And check if any process is actively listening on the expected ports:
ss -lntpA quick look at storage and memory completes an initial diagnosis:
df -hfree -hWithin less than a minute, you can gather a substantial amount of information.
This approach introduces a simple rule: observe first, then intervene.
Asking what changed often saves a lot of time
A server that worked yesterday and doesn’t today rarely changed by magic.
Likely causes include an update, deployment, certificate change, configuration modification, or firewall rule.
So, start with:
git statusgit diffIf configuration is under version control, review recent commits:
git log --since="2 days ago" --onelineOn Debian or Ubuntu servers, also check APT logs and dpkg; RPM-based distributions have similar histories.
In professional environments, deployment histories via CI/CD, Ansible, or other automation platforms can be even more revealing.
Asking “what has changed?” is often a better strategy than immediately searching for a complex cause.
journalctl is much more useful when filtered
A common mistake is running:
journalctl -xeand encountering hundreds or thousands of lines.
The issue might be present but hidden.
It’s more effective to narrow the search.
Only logs for nginx, for example:
journalctl -u nginxThe last twenty minutes:
journalctl -u nginx --since "-20 min"Current boot errors:
journalctl -p err -bKernel messages:
journalctl -k -bAnd there’s a particularly useful option right after a server has rebooted:
journalctl -b -1This allows examining the previous boot, helping to understand what was occurring before the system restarted.
Checking failed services takes seconds
Another small command that can reveal hidden issues is:
systemctl --failedIt shows systemd units that have failed.
This might include auxiliary services, mounts, startup tasks, or components that haven’t yet indicated failure to users.
Investigate before resetting their status with:
systemctl reset-failedAgain, don’t erase a clue before understanding it.
Network, disks, and performance: check what’s really happening
Application configuration indicates how it should behave.
Linux can show how it is actually functioning.
This difference is crucial.
ss confirms which ports are listening
If an app supposed to run on port 443, verify with:
ss -lntpThis displays TCP sockets in listening state and, with sufficient permissions, their related processes.
For UDP:
ss -lunpAnd for active TCP connections:
ss -tnpThis helps identify various issues.
If nothing appears on :443, the service isn’t listening.
If it appears as:
127.0.0.1:443but should be accessible from another machine, it might be bound only to localhost.
Before suspecting routers, external firewalls, or cloud providers, it’s wise to verify what’s happening directly on the server itself.
df doesn’t tell the whole storage story
Almost any sysadmin knows:
df -hIt’s excellent for checking space usage.
But modern systems can have partitions, LVM volumes, cloud disks, NFS, bind mounts, or container storage.
To inspect devices:
lsblkTo examine mounts:
findmntAnd to answer specific questions like “Where is /var/lib/docker really located?”:
findmnt --target /var/lib/dockerThis combination helps distinguish between physical disk, partition, filesystem, and mount point, related but not identical concepts.
It also avoids dangerous errors when multiple disks share similar names.
A snapshot of CPU usage doesn’t always explain a problem
top shows what’s happening right now.
But a machine can have an issue that occurs for five seconds every minute.
Tools like:
vmstat 1provide, each second, data on CPU, memory, processes, swap, and I/O activity.
If sysstat is installed, another helpful tool is:
iostat -xz 1which offers detailed info on storage device activity.
The difference is straightforward:
top indicates what’s happening now.
A series of measurements can reveal the pattern causing the problem.
When the application doesn’t explain the failure, check the kernel
Some failures only report that something went wrong.
The kernel can provide the missing piece.
For example:
journalctl -k -bmay reveal issues with disks, memory, drivers, or network interfaces.
If a process disappears without explanation, it’s also worth checking for signs of memory pressure or the OOM killer.
A problem seemingly caused by an application might actually be due to the operating system.
The most important habits happen before pressing Enter
Linux allows doing a lot with a single line.
That’s an advantage but also a risk.
For example:
find /backup -type f -mtime +30 -deletethis deletes all matching files directly.
It’s better to test the selection without deleting anything first:
find /backup -type f -mtime +30 -printOnce confirmed, add -delete.
Similarly with rsync:
rsync -a --delete /source/ /destination/It’s wise to run a dry run first:
rsync -a --delete --dry-run /source/ /destination/--dry-run shows what would happen without making actual changes.
This small habit can prevent significant data loss.
Validate configuration before restarting
Suppose nginx has been modified.
Instead of editing and restarting directly, test first:
nginx -tThen, if everything checks out, reload:
systemctl reload nginxThis prompts a better workflow sequence:
edit
validate
compare
reload
verifyrather than:
edit
restart
waitWhenever a service supports reload, prefer it over a full restart when possible.
kill -9 should be the last resort
When a process seems stuck, it might be tempting to just do:
kill -9 PIDBut SIGKILL terminates immediately, without cleanup.
Start with:
kill PIDwhich sends SIGTERM.
Before using either, confirm which process you’re dealing with:
ps -fp PIDAdditional info can be retrieved from:
cat /proc/PID/statusSometimes, kill -9 is genuinely necessary.
The habit is to avoid using the most aggressive intervention as the first choice.
Good automation involves more than just scripting
Many scripts work fine when run manually but fail in cron or systemd.
The typical cause is the environment.
An interactive terminal can have a PATH, environment variables, SSH keys, or a working directory that doesn’t exist when run automatically.
Instead of:
python backup.pyuse:
/usr/bin/python3 /opt/scripts/backup.pyand explicitly define the environment needed by the script, avoiding reliance on personal aliases.
Check if a command succeeded
Bash uses exit codes.
After a command, check its exit status with:
echo $?A 0 usually indicates success.
In scripts, it’s better to check the command directly:
if rsync -a /data/ /backup/data/; then
echo "Backup completed"
else
echo "Backup failed" &&2
exit 1
fiThis integrates the result into the script’s logic.
A backup shouldn’t be considered successful just because the script finished.
set -e doesn’t automatically fix all errors
Many scripts include:
set -eto stop execution upon failure.
It can be helpful but Bash has several exceptions.
A common configuration is:
set -Eeuo pipefailpipefail is especially useful in pipelines.
For example:
grep "error" archivo-inexistente | sortWithout pipefail, errors in the first command might go unnoticed, and the pipeline could return the result of sort.
Still, no set of options replaces explicit error handling in important automation.
Better to automate checks than fixes
Not all automation is about corrections.
Sometimes, simple notifications are enough.
For example:
systemctl is-active --quiet nginx || echo "nginx is not active"This can be extended to automatically verify:
- free disk space;
- recent backups;
- expiring certificates;
- essential mounts;
- failing services;
- listening ports;
- RAID status;
- time synchronization.
Automatically restarting a service whenever a problem appears can hide issues for months.
Detecting and logging the state helps investigate the root cause.
Save a snapshot of the system before making changes
A diagnostic script can quickly gather essential data:
date
hostname
uptime
free -h
df -h
lsblk
systemctl --failed
ss -lntp
journalctl -p err -b --no-pagerAnd save it with:
/opt/tools/capture-state.sh > "/var/tmp/state-$(date +%Y%m%d-%H%M%S).log" 2>&1If a restart is needed later, you still have a record of the previous state.
This is extremely useful in complex incidents.
The habit that doesn’t require a terminal: document what you’ve learned
Every solved problem becomes a piece of reusable knowledge.
A simple record should include:
- what happened;
- when it started;
- what changed;
- which logs were reviewed;
- which commands helped;
- the root cause;
- how it was fixed;
- how to detect a similar issue earlier.
No need for a special platform.
A private Git repository with Markdown documents can over time become a mini knowledge base about real infrastructure problems.
An important advantage is that six months later, no one has to rediscover the same solution exactly.
A good administrator’s experience isn’t just in their memory; it’s also in the procedures they’ve documented.
Linux values method over speed
Two people may know the exact same commands.
One approach:
restart
test
change
test againThe other:
observe
save evidence
define boundaries
form hypotheses
test
make minimal changes
verifyThe second doesn’t necessarily know more Linux, but works with a better method.
This way of managing systems remains useful even with Prometheus, Grafana, OpenTelemetry, Kubernetes, or sophisticated observability platforms behind the scenes.
When something fails, there’s always a point where you need to ask concrete questions: which process exists, what port it listens on, what changed, which filesystem is full, or what the kernel logs just before failure.
Commands help to find those answers.
Good habits determine whether you ask the right questions before modifying the system.
Frequently asked questions
What should be checked first when a Linux server fails?
Depending on the issue, reviewing systemctl status, journalctl, systemctl --failed, ss, df, free, and findmnt provides a quick initial snapshot of the system’s state.
Why shouldn’t a service be immediately restarted?
Because restarting might change system state and add new logs, making it harder to identify the original cause. It’s better to gather evidence first.
What is the purpose of --dry-run?
It simulates certain operations without applying changes, helping to see what would happen. Tools like rsync use it to show files that would be copied or deleted before executing.
Is set -e enough to make Bash scripts safe?
No. It can help stop scripts on certain errors, but Bash has exceptions. For critical automation, explicitly checking results and understanding options like pipefail is recommended.
Sources:
- Official systemd documentation:
systemctl,journalctl,systemd-analyze. - GNU Bash Reference Manual.
- Util-linux project: documentation for
lsblkandfindmnt. - iproute2: documentation for
ss. - procps-ng and sysstat: diagnostic and performance tools.

