contentintech
Learn/devops/Linux Fundamentals
Beginner~20 min read

Linux Fundamentals

The filesystem hierarchy, file permissions and ownership, users and groups, process and service management, package managers, networking tools, text processing, pipes and redirection, bash scripting, environment variables, and SSH.

PermissionsProcessesShellNetworking

Linux powers the vast majority of servers, containers, and cloud infrastructure. Whether you SSH into a production box, build a Docker image, or debug a failing service, you are speaking to a Linux kernel through a shell. This guide covers the core skills every engineer needs: navigating the filesystem, controlling permissions, managing processes and services, installing software, working with the network, and automating tasks with bash.

The Filesystem Hierarchy

Linux organizes everything under a single root directory /. There are no drive letters. The Filesystem Hierarchy Standard (FHS) defines what lives where, so you can find configuration and binaries on any distribution.

PathPurpose
/etcSystem-wide configuration files
/homePer-user home directories
/varVariable data: logs, spools, caches
/usrUser-space programs and libraries
/tmpTemporary files, cleared on reboot
/proc, /sysVirtual filesystems exposing kernel and process state
/optOptional third-party software
bash
pwd                      # print working directory
ls -lah                  # long listing, all files, human-readable sizes
cd /var/log              # change directory
cd -                     # jump back to previous directory
tree -L 2                # show two levels of the tree
stat /etc/hostname       # detailed metadata about a file

File Permissions and Ownership

Every file has an owner, a group, and three permission sets: user, group, and others. Each set grants read (r=4), write (w=2), and execute (x=1). Add the numbers to build an octal mode.

bash
-rwxr-xr--  1 alice devs  2048 Jun 01 10:00 deploy.sh
 |└┬┘└┬┘└┬┘
 | │  │  └── others: r-- (read)
 | │  └───── group:  r-x (read, execute)
 | └──────── user:   rwx (read, write, execute)
 └────────── type:   - file, d directory, l symlink
bash
chmod 755 deploy.sh      # rwx r-x r-x -> owner full, others read+exec
chmod 644 config.yaml    # rw- r-- r-- -> common for config files
chmod +x script.sh       # add execute bit for everyone (symbolic)
chmod u+w,g-w file       # add write for user, remove for group
chown alice:devs file    # change owner and group
chown -R alice /srv/app  # recursive ownership change
umask 022                # default new files as 644, dirs as 755

Octal shortcut

Read=4, Write=2, Execute=1. Sum per role: 7=rwx, 6=rw-, 5=r-x, 4=r--. So chmod 640 means owner rw, group r, others none.

Users and Groups

User accounts live in /etc/passwd and groups in /etc/group. Use sudo to run a single command as another user (usually root) rather than logging in as root.

bash
whoami                       # current username
id                           # uid, gid, and group memberships
sudo useradd -m -s /bin/bash deploy   # create user with home + shell
sudo passwd deploy           # set a password
sudo usermod -aG docker deploy        # append user to the docker group
sudo userdel -r olduser      # delete user and their home
groups deploy                # list a user's groups
su - deploy                  # switch to another user's login shell

Processes and Services

A process is a running program with a numeric PID. Inspect them with ps and top, and stop them with kill. Long-running background services are managed by systemd through systemctl.

bash
ps aux                       # every process, with CPU and memory
ps -ef | grep nginx          # find a specific process
top                          # live process monitor (press q to quit)
htop                         # friendlier interactive monitor
kill 1234                    # send SIGTERM (graceful) to PID 1234
kill -9 1234                 # send SIGKILL (force)
pkill -f "python worker"     # kill by matching command line
jobs; bg; fg                 # manage shell background jobs
bash
sudo systemctl status nginx      # is the service running?
sudo systemctl start nginx       # start now
sudo systemctl enable --now nginx  # start now and on boot
sudo systemctl restart nginx     # restart
sudo systemctl reload nginx      # reload config without downtime
journalctl -u nginx -f           # follow a service's logs live
journalctl -p err -b             # error-level logs since last boot

Package Managers

Debian and Ubuntu use apt; Fedora, RHEL, and Rocky use dnf. Both resolve dependencies for you.

Taskapt (Debian/Ubuntu)dnf (Fedora/RHEL)
Refresh indexsudo apt updatesudo dnf check-update
Installsudo apt install nginxsudo dnf install nginx
Upgrade allsudo apt upgradesudo dnf upgrade
Removesudo apt remove nginxsudo dnf remove nginx
Searchapt search curldnf search curl

Networking

The modern toolkit is ip (replaces ifconfig) and ss (replaces netstat). Use curl to talk to HTTP services.

bash
ip addr                      # show interfaces and IP addresses
ip route                     # routing table (find your default gateway)
ss -tulpn                    # listening TCP/UDP sockets with process names
ping -c 4 1.1.1.1            # test connectivity
dig example.com +short       # DNS lookup
curl -sSL https://api.example.com/health   # fetch a URL (silent, follow redirects)
curl -X POST -d '{"k":"v"}' -H 'Content-Type: application/json' URL
nc -zv host 5432             # check if a TCP port is open

Text Processing

Filtering and reshaping text is a daily task: parsing logs, extracting fields, and editing config files. grep searches, sed edits streams, awk works with columns, and find locates files.

bash
grep -rn "ERROR" /var/log/app/       # recursive, with line numbers
grep -i -A3 "timeout" app.log        # case-insensitive, 3 lines after match
sed 's/localhost/prod-db/g' cfg.conf # substitute all occurrences
sed -i '/^#/d' config.ini            # delete comment lines in place
awk '{print $1, $9}' access.log      # print columns 1 and 9
awk -F: '$3 >= 1000 {print $1}' /etc/passwd   # regular user accounts
find /var/log -name "*.log" -mtime +7 -delete # remove logs older than 7 days
find . -type f -size +100M           # large files

Pipes and Redirection

The Unix philosophy is small tools composed with pipes. | sends one command's stdout to the next command's stdin. Redirection sends output to files or discards it.

bash
cat access.log | grep 500 | wc -l    # count HTTP 500 responses
command > out.txt                     # stdout to file (overwrite)
command >> out.txt                    # stdout to file (append)
command 2> err.txt                    # stderr to file
command > all.txt 2>&1                # merge stderr into stdout
command > /dev/null 2>&1              # discard all output
sort access.log | uniq -c | sort -rn # top repeated lines
ps aux | sort -k3 -rn | head         # top CPU consumers

Environment Variables

Environment variables configure programs and the shell. PATH lists directories searched for commands; export makes a variable available to child processes.

bash
echo $PATH                   # inspect the search path
export API_KEY="secret123"   # set for this shell and children
printenv | sort              # list all environment variables
DB_HOST=localhost node app.js  # set a var for one command only
# Persist across sessions by adding to ~/.bashrc:
echo 'export EDITOR=vim' >> ~/.bashrc && source ~/.bashrc

Bash Scripting Basics

A script is a text file of commands starting with a shebang. Always begin production scripts with set -euo pipefail so they exit on errors and undefined variables.

bash
#!/usr/bin/env bash
set -euo pipefail

# variables and arguments
NAME="${1:-world}"        # first arg, default "world"
echo "Hello, ${NAME}"

# conditionals
if [[ -f /etc/os-release ]]; then
  echo "Found OS release file"
fi

# loops
for svc in nginx redis postgres; do
  systemctl is-active --quiet "$svc" && echo "$svc up" || echo "$svc down"
done

# functions
backup() {
  local src="$1" dst="$2"
  tar -czf "$dst" "$src"
}
backup /srv/app "/backups/app-$(date +%F).tar.gz"

Quote your variables

Always wrap variable expansions in double quotes like "$file". Unquoted variables break on spaces and are the single most common source of script bugs. Run shellcheck to catch these automatically.

SSH

SSH gives you an encrypted shell on a remote machine. Prefer key-based authentication over passwords, and use ~/.ssh/config to save host aliases.

bash
ssh-keygen -t ed25519 -C "you@example.com"   # generate a modern key
ssh-copy-id deploy@server.example.com         # install your public key
ssh deploy@server.example.com                 # connect
scp file.tar.gz deploy@server:/srv/           # copy a file over SSH
rsync -avz --progress ./dist/ deploy@server:/srv/app/  # efficient sync

# ~/.ssh/config
# Host prod
#   HostName 203.0.113.10
#   User deploy
#   IdentityFile ~/.ssh/id_ed25519
# Then just: ssh prod

Practice Exercises

  1. Create a directory /srv/app, give it owner deploy:devs and mode 750, then verify with ls -ld and stat.
  2. Write a one-liner that finds the ten most frequent client IPs in an nginx access log using awk, sort, and uniq.
  3. Install nginx with your package manager, enable it to start on boot, then tail its logs live with journalctl.
  4. Use ss -tulpn to identify which process is listening on port 80, then find and stop it by PID.
  5. Write a bash script with set -euo pipefail that accepts a directory argument and creates a timestamped compressed tarball of it in /backups.
  6. Generate an ed25519 SSH key, copy it to a test host, add a Host alias in ~/.ssh/config, and confirm you can log in without a password.

Section navigation