Cloud Tech by Victor
DevOpsBeginner

Linux Fundamentals

The core command-line building blocks - navigation, permissions, processes, networking, and services - that every other Linux topic on this site (filesystem hierarchy, storage, users, networking) assumes you already have.

Updated 2026-07-247 min read

Overview

Almost everything distinctive about working with Linux happens through a small set of composable command-line building blocks: navigating and manipulating files, understanding the permission model that decides who can do what to them, inspecting and controlling running processes, and configuring the networking and background services a machine actually runs. Every other Linux topic on this site - the Filesystem Hierarchy Standard, process management internals, storage, networking, users and groups, logging - goes deep on one of these areas. This one is the map: the everyday commands from each area, in the shape you'll actually reach for them, before you need the deeper dive.

Quick Reference

ConceptWhat it isNote
ShellThe interactive command interpreter running the commands belowbash is the most common default, zsh is common on macOS
KernelThe core process managing hardware, memory, and processesEverything else, including the shell, runs as a process on top of it
ProcessA running instance of a program, identified by a PIDInspected and controlled with ps, top, kill
Filesystem Hierarchy StandardThe standardized directory layout (/etc, /var, /usr...)Full breakdown in Linux Filesystem Hierarchy & Permissions
systemd unitA managed, restartable background serviceControlled with systemctl, logged via journalctl

The commands below are grouped by task, not alphabetically - not exhaustive (see the GNU Coreutils manual for every flag), but the set that covers almost all daily shell work.

CommandDescriptionCopy
pwdPrint the current working directory.
ls -laList every file in the current directory, including hidden ones, in long format.
cd <dir>Change the current directory.
mkdir -p <path>Create a directory, including any missing parent directories.
cp -r <src> <dst>Copy a file or directory recursively.
mv <src> <dst>Move or rename a file or directory.
rm -rf <dir>Remove a directory and its contents recursively, without confirmation.
cat <file>Print a file's entire contents to standard output.
less <file>View a file's contents one screen at a time.

Syntax

bash
command [options] [arguments]
# e.g.
grep -r --include="*.log" "ERROR" /var/log/app
bash
# Chaining: pipe output from one command into the next
# The [n]ode bracket trick keeps grep's own process out of its own match
ps aux | grep [n]ode | awk '{print $2}'

Examples

bash
find /var/log -name "*.log" -mtime -1
grep -c "ERROR" /var/log/app/current.log
journalctl -u nginx.service --since '1 hour ago'

Filter a systemd service's logs to a relative time window, far faster than scrolling a full log file looking for when something started.

journalctl -u nginx.service --since '1 hour ago'

Visual Diagram

Common Mistakes

  • Running rm -rf with a mistyped or unset variable in the path, deleting far more than intended; there is no undo, so double-check any command with -rf before running it.
  • Reaching for kill -9 as the default, skipping the graceful SIGTERM shutdown that lets a process close files and finish in-flight work cleanly.
  • Editing a config file directly as root over SSH without a backup, discovering a syntax error only after the service that depends on it fails to restart.
  • Assuming ping succeeding means an application is reachable; it only confirms network-layer connectivity, not that any specific service is listening or healthy.
  • Forgetting systemctl enable, so a manually started service works fine until the next reboot, when it silently doesn't come back.

Performance

  • grep -r on a very large directory tree is far slower than a tool that respects .gitignore-style excludes; scope searches to the smallest relevant directory when possible.
  • find walks the filesystem tree directly and can be slow across network mounts or very large directories; narrowing with -maxdepth or a more specific starting path helps significantly.
  • Piping large outputs through several processes (ps aux | grep ... | awk ...) is usually fine, but each pipe stage is its own process; for performance-sensitive scripts, a single awk or grep invocation with the right flags often replaces a whole pipeline.

Best Practices

  • Prefer systemctl enable --now over separate start/enable calls when bringing a new service into permanent use, so you never forget the reboot half of the equation.
  • Use journalctl -u <service> and --since/--until filters instead of grepping through raw log files by hand.
  • Reach for SIGTERM (kill, not kill -9) first, and only escalate to SIGKILL if a process genuinely won't respond after a reasonable wait.
  • Test connectivity at the layer you actually care about - ss -tulpn or curl for "is this application reachable," not just ping.
  • Keep destructive commands (rm -rf, chmod -R, chown -R) deliberate: confirm the target path with pwd/ls immediately before running them, especially over SSH on a remote host.

Interview questions

What is the difference between killing a process with SIGTERM and SIGKILL?

`kill <pid>` sends SIGTERM by default, a request asking the process to shut down, which well-behaved programs catch to close files, finish in-flight work, and exit cleanly. `kill -9 <pid>` sends SIGKILL, which the kernel delivers directly and a process cannot catch, ignore, or clean up after; it is terminated immediately, mid-instruction if necessary. SIGKILL is a last resort for a genuinely hung process; reaching for it by default risks corrupted files or orphaned resources that a graceful SIGTERM shutdown would have avoided.

Why does `ping` succeeding not guarantee an application on that host is reachable?

ping tests only ICMP echo reachability at the network layer; it confirms a host responds to the network, nothing about any specific service running on it. An application listening on a TCP port can be down, crashed, or blocked by a firewall rule that specifically targets that port while still allowing ICMP through, or conversely ICMP itself can be blocked while the actual service is reachable. Confirming an application is actually up requires testing the application layer directly, e.g. `curl` against its port or `ss -tulpn` to confirm something is listening at all.

What does `systemctl enable` actually do, and how is it different from `systemctl start`?

`systemctl start <service>` runs the service right now, in the current boot session only; it will not come back after a reboot. `systemctl enable <service>` creates the symlinks systemd uses to decide what to launch automatically during the boot sequence, so the service starts on every future boot, but does not start it immediately. The two are independent and commonly used together (`systemctl enable --now <service>`) precisely because neither one implies the other.

References

ShareXLinkedInReddit
Was this page helpful?
Suggest an improvement