Linux runs most of the servers on the internet, and its command line appears constantly in security guides, hosting tutorials, and troubleshooting articles — including elsewhere on this site (the Hosting & Deployment course connects to a server over SSH and uses exactly these commands). This lesson is a long, practical tour, deliberately going further than a typical "basics" chapter — the more of this that feels familiar, the less intimidating a real server becomes.
# Show the current folder
pwd
# List files and folders here
ls -la
# Move into a folder
cd Downloads
# Go back up one level
cd ..
# Go straight to the home folder
cd ~ls -la specifically — the -a flag shows hidden files (names starting with a dot, like .ssh or .bashrc), which regular ls quietly skips. A surprising amount of security-relevant configuration lives in hidden files.
Unlike Windows' separate drive letters, Linux has one single folder tree starting at / (the root) — everything, including other disks, gets mounted somewhere inside it.
| Folder | What lives there |
|---|---|
| /home | Each user's personal files (e.g. /home/sam) |
| /etc | System-wide configuration files |
| /var | Data that changes often — logs, caches, mail |
| /usr | Installed programs and their supporting files |
| /bin, /usr/bin | Common command-line programs |
| /tmp | Temporary files, usually cleared on reboot |
| /root | The root (administrator) user's home folder |
| /dev | Device files representing hardware |
# Create an empty file
touch notes.txt
# Create a folder
mkdir project
# Copy a file
cp notes.txt backup-notes.txt
# Copy an entire folder
cp -r project project-backup
# Move or rename (same command does both)
mv notes.txt archive/notes.txt
mv old-name.txt new-name.txt
# Delete a file
rm notes.txt
# Delete a folder and everything in it
rm -rf project-backupThe most dangerous common command
rm -rf deletes permanently — no Recycle Bin, no undo. Double-check the path before running it, especially with a wildcard (rm -rf *) or as root.
# Print a whole file to the screen
cat notes.txt
# Scroll through a long file (q to quit)
less server.log
# First 10 lines
head server.log
# Last 10 lines — great for watching a log grow
tail server.log
# Keep watching a file as new lines are added
tail -f server.logFor actually editing a file from the terminal, nano is the friendliest starting point — arrow keys work as expected, and the shortcuts are listed on screen.
nano config.txt
# Ctrl+O to save, Ctrl+X to exitvim is the other common option, far more powerful once learned but genuinely unintuitive at first — it opens in "normal mode," where typing doesn't insert text until i is pressed. Worth knowing at least the exit sequence, since it's a famous first stumbling block.
vim config.txt
# Press i to start typing (insert mode)
# Press Esc to leave insert mode
# Type :wq and press Enter to save and quit
# Type :q! and press Enter to quit WITHOUT savingEvery command has three data streams: stdin (input), stdout (normal output), and stderr (error output) — understanding these unlocks most of what makes the command line powerful.
| Symbol | What it does |
|---|---|
| > | Send stdout to a file, overwriting it |
| >> | Send stdout to a file, appending to it |
| 2> | Send stderr (only) to a file |
| < | Feed a file in as stdin |
| | | Pipe — send one command's stdout as the next command's stdin |
# Save output to a file
ls -la > filelist.txt
# Append instead of overwrite
echo "new entry" >> notes.txt
# Send errors to a separate file, keep normal output on screen
some-command 2> errors.log
# Chain commands — this pipeline is genuinely common in practice
ps aux | grep nginx | wc -l
# ps aux: list every process
# grep nginx: keep only lines mentioning nginx
# wc -l: count the remaining linesLinux's small, single-purpose text tools are designed to be piped together — this is the toolkit behind reading logs, filtering data, and quick one-off reports without writing a script.
| Command | What it does |
|---|---|
| grep "pattern" file | Prints lines matching a pattern |
| grep -i | Case-insensitive match |
| grep -r "pattern" . | Search recursively through every file in a folder |
| cut -d',' -f2 | Extract one column from delimited text (here, the 2nd, comma-separated) |
| sort | Sort lines alphabetically or numerically (-n) |
| uniq | Remove adjacent duplicate lines (usually paired with sort first) |
| wc -l | Count lines (also -w for words, -c for characters) |
| tr 'a-z' 'A-Z' | Translate characters — here, lowercase to uppercase |
# Find every failed login attempt in an auth log
grep "Failed password" /var/log/auth.log
# Get a sorted, de-duplicated list of IPs that tried
grep "Failed password" /var/log/auth.log | awk '{print $(NF-3)}' | sort | uniq -c | sort -rn
# awk pulls out one field per line, sort+uniq -c counts how often
# each IP appears, the final sort -rn ranks the worst offenders firstawk and sed are both full text-processing languages on their own — the single most useful pattern to remember from each: awk '{print $N}' to grab column N of space-separated text, and sed 's/old/new/g' to find-and-replace text in a stream.
# Replace every occurrence of "staging" with "production" and print the result
sed 's/staging/production/g' config.txtEvery file on Linux has permissions controlling who can read, write, or execute it — this is not a formality, it's an actual access-control mechanism. A world-writable config file or an overly permissive SSH key is a genuine, common vulnerability.
# Check permissions on a file
ls -l script.sh
# -rwxr-xr-- 1 sam staff 220 Sep 3 10:00 script.shThat first block of ten characters breaks into: the file type, then three permission triplets (owner, group, everyone else) — each triplet is read (r), write (w), execute (x), or a dash for "not permitted."
| Symbol | Numeric value |
|---|---|
| r (read) | 4 |
| w (write) | 2 |
| x (execute) | 1 |
# Give the owner read+write+execute, group read+execute, others nothing
chmod 750 script.sh
# The same change, written symbolically
chmod u=rwx,g=rx,o= script.sh
# Make a file only the owner can read and write (common for SSH keys)
chmod 600 id_rsa
# Change who owns a file
chown sam script.sh
# Change owner and group together
chown sam:staff script.sh# Bundle a folder into one .tar file
tar -cvf backup.tar project/
# Same, but gzip-compressed (.tar.gz)
tar -czvf backup.tar.gz project/
# Unpack a .tar.gz
tar -xzvf backup.tar.gz
# Zip / unzip, if that format is needed instead
zip -r backup.zip project/
unzip backup.zipc = create, x = extract, z = gzip, v = verbose (show progress), f = the filename follows.
# Search by name, from the current folder down
find . -name "*.log"
# Search the whole system for a file modified in the last day
find / -name "config.php" -mtime -1
# Fast search using a pre-built index (usually faster, may be slightly stale)
locate nginx.conf# List every running process
ps aux
# Live, auto-refreshing view of processes and resource use
top
# End a process by its process ID (find the ID from ps aux first)
kill 4821
# Force-kill a process that ignores a normal kill
kill -9 4821Know before you kill
Ending an unfamiliar process ID can break something else that depends on it. Confirm what a process is (via ps aux or a search on its name) before ending it.
# Start a long-running command in the background
long-task &
# List the current background jobs
jobs
# Bring a background job back to the foreground
fg %1
# A command that keeps running even after the terminal closes
nohup long-task &Every file, process, and permission ultimately belongs to a user — and every user belongs to one or more groups, which is how group-level permissions from the earlier section actually get applied.
# Add a new user
sudo useradd -m newuser # -m also creates their home folder
# Set (or change) that user's password
sudo passwd newuser
# Add an existing user to a group
sudo usermod -aG developers newuser
# See which groups the current user belongs to
groups
# Delete a user (and optionally their home folder with -r)
sudo userdel -r newusersudo runs a single command with administrator (root) privileges, rather than logging in as root directly — the safer, standard approach, since it's scoped to one command and logged.
sudo apt update
# Run a shell as root (use sparingly)
sudo -iInstalling software on Linux almost never means downloading an installer — a package manager handles finding, installing, updating, and removing software from a trusted repository.
| Distro family | Package manager | Install / update |
|---|---|---|
| Debian, Ubuntu | apt | sudo apt install |
| Fedora, RHEL, CentOS | dnf (or the older yum) | sudo dnf install |
| Arch | pacman | sudo pacman -S |
# Update the local list of available packages
sudo apt update
# Install a package
sudo apt install htop
# Remove a package
sudo apt remove htop
# List installed packages
apt list --installed
# Upgrade every installed package
sudo apt upgradeMost modern Linux distributions manage background services (a web server, a database, an SSH server) with systemd, via the systemctl command.
# Check whether a service is running
sudo systemctl status nginx
# Start / stop / restart a service
sudo systemctl start nginx
sudo systemctl stop nginx
sudo systemctl restart nginx
# Make a service start automatically on boot
sudo systemctl enable nginx
# Read a service's recent logs
journalctl -u nginx --since todayAn environment variable is a named value available to every program run in that session — PATH is the most important one, since it's the list of folders the shell searches when a command is typed without a full path.
# Show every environment variable
env
# Show one specific variable
echo $HOME
echo $PATH
# Set one for the current session only
export API_KEY=abc123
# Set one permanently — added to ~/.bashrc (or ~/.zshrc), then re-loaded
echo 'export API_KEY=abc123' >> ~/.bashrc
source ~/.bashrc# Show this machine's IP address
ip a
# Test whether a host is reachable
ping -c 4 google.com
# Trace the network hops to a host
traceroute google.com
# List active network connections and the process using each
ss -tulnp
# The older equivalent, still common in guides
netstat -tulnp
# Download a file or check an API from the command line
curl -I https://example.com # -I: headers only
wget https://example.com/file.zip
# Look up a domain's DNS records
dig example.com
nslookup example.comss -tulnp is worth remembering on its own — it lists every port a program is listening on, which is exactly what to check when trying to work out whether something unexpected is running a server on a machine.
# Show disk space used per mounted filesystem
df -h
# Show how much space a specific folder is using
du -sh /var/log
# List the block devices (drives and partitions) attached
lsblk
# Show what's currently mounted where
mountAny sequence of commands can be saved into a file and run as a script — the same commands covered throughout this lesson, just automated.
#!/bin/bash
# The line above is the "shebang" — tells the system which
# interpreter to run this file with
name="World"
echo "Hello, $name!"chmod +x greet.sh # make it executable
./greet.sh # run it# A variable
count=5
# A conditional
if [ "$count" -gt 3 ]; then
echo "More than 3"
else
echo "3 or fewer"
fi
# A loop
for file in *.txt; do
echo "Found: $file"
doneA quick, standard set of checks for "what's going on with this machine" — worth knowing as a sequence, not just individually.
# How long has this system been up, and how loaded is it?
uptime
# Who is (or has recently been) logged in?
who
last
# What does the system log say happened recently?
tail -50 /var/log/syslog # Debian/Ubuntu
journalctl -n 50 # systemd-based systems
# The most recent kernel/hardware messages
dmesg | tail -50
# How much memory is free?
free -h| Question | Command |
|---|---|
| Is the system overloaded? | uptime (check the load average) |
| Is a specific service actually running? | systemctl status |
| Is the disk full? | df -h |
| What's using all the memory? | top or free -h |
| What just happened, system-wide? | journalctl -n 50 or tail -f /var/log/syslog |
| Command | What it does |
|---|---|
| pwd | Show the current folder |
| ls -la | List files and folders, including hidden ones |
| cd | Change folder |
| cp / mv / rm | Copy / move-rename / delete |
| mkdir / rmdir | Create / remove an empty folder |
| cat / less / head / tail | View a file — all at once, scrollable, first lines, last lines |
| grep / awk / sed / cut / sort / uniq | Search and process text |
| chmod / chown | Change permissions / ownership |
| tar / zip | Archive and compress files |
| find / locate | Search for files |
| ps aux / top / kill | List, monitor, and end processes |
| useradd / usermod / passwd | Manage user accounts |
| sudo apt install / update / upgrade | Manage packages (Debian/Ubuntu) |
| systemctl start / stop / status | Manage background services |
| ip a / ping / curl / ss -tulnp | Network configuration, connectivity, requests, open ports |
| df -h / du -sh / lsblk | Disk space, folder size, attached drives |
| uptime / free -h / journalctl | System load, memory, logs |
What this deliberately leaves out
Deliberately left out of this lesson: containers (Docker), advanced storage (LVM), deep networking internals (the full TCP/IP stack, Netfilter/iptables rule-writing), and boot process internals — genuinely useful, but DevOps/sysadmin-specialist territory rather than the security-relevant CLI literacy this course is scoped for.