🐧 Latest Edition
📖 Beginner to Advanced
⏱️ 50 min read
🎯 20+ Sections

⏱️ Estimated reading time: 45-50 minutes

📋 Quick Summary: Linux powers 96% of the world’s servers, 90% of the cloud, and every Android phone. If you work in tech, you need Linux command line skills. By the end of this course, you will navigate the filesystem, manage files and processes, edit files with Vim, write shell scripts, manage users and permissions, handle networking, and administer a Linux server — all from the command line.

(Table of Contents)

🐧 What Is Linux?

Linux is a family of open-source Unix-like operating systems based on the Linux kernel, created by Linus Torvalds in 1991. It runs everywhere: servers, desktops, embedded devices, supercomputers (100% of the top 500), Android phones (which is Linux), and even Mars rovers.

Linux Distributions

Linux comes in different “distributions” (distros) — think of them as different flavors:

Distro Package Manager Best For
Ubuntu apt (DEB) Beginners, desktops, servers
Debian apt (DEB) Stable servers
CentOS/RHEL dnf/yum (RPM) Enterprise servers
Fedora dnf (RPM) Cutting-edge features
Arch pacman Customization enthusiasts
Alpine apk Docker containers (tiny)

🔧 Getting Started

Accessing Linux

# If Windows: Install WSL2 (Windows Subsystem for Linux)
wsl --install -d Ubuntu

# If macOS: Terminal is Unix-based — most commands work
# If you have a Linux desktop: Ctrl+Alt+T opens terminal

# If you want to practice online (no install needed):
#   Web: https://bellard.org/jslinux/
#   Docker: docker run -it ubuntu bash

The Shell

# The shell is your command interpreter. Default is bash.
# Prompt usually looks like: user@hostname:~$

echo $SHELL        # See which shell you're using
/bin/bash --version # Check bash version

# Anatomy of a command:
#   command [options] [arguments]
#   ls      -la       /home

# Getting help:
command --help      # Quick summary
man command         # Full manual (press q to quit)
info command        # Alternative documentation

📁 Filesystem Navigation

The Linux filesystem is a single tree starting at /. Everything — files, devices, network sockets — is a file.

Filesystem Hierarchy

/              # Root — the top of the tree
├── bin/       # Essential user binaries (ls, cp, mv)
├── boot/      # Boot loader files (kernel, initrd)
├── dev/       # Device files (sda, tty, null)
├── etc/       # Configuration files (passwd, nginx.conf)
├── home/      # User home directories (/home/user)
├── lib/       # System libraries
├── media/     # Mount point for removable media
├── mnt/       # Temporary mount points
├── opt/       # Optional third-party software
├── proc/      # Virtual filesystem for process info
├── root/      # Root user's home directory
├── run/       # Runtime variable data
├── sbin/      # System binaries (fdisk, mkfs)
├── srv/       # Service data (web servers, FTP)
├── sys/       # Virtual filesystem for system info
├── tmp/       # Temporary files (cleared on reboot)
├── usr/       # User system resources (bin, lib, share)
└── var/       # Variable data (logs, databases, mail)

Navigation Commands

pwd                  # Print Working Directory — where am I?

ls                   # List files in current directory
ls -l                # Long format (permissions, size, date)
ls -a                # Show hidden files (starting with .)
ls -la               # Long format + hidden
ls -lh               # Human-readable sizes (1K, 234M)
ls -ltr              # Sort by time, reversed (newest at bottom)
ls -R                # Recursive (all subdirectories)

cd                   # Go to home directory
cd /etc              # Go to /etc (absolute path)
cd documents         # Go to documents/ (relative path)
cd ..                # Go up one directory
cd ../..             # Go up two directories
cd -                 # Go back to previous directory
cd ~                 # Go to home directory

tree                 # Show directory tree (install: apt install tree)
tree -L 2            # Limit to 2 levels deep

Path Types

# Absolute path — starts from root /
/home/user/documents/file.txt
/etc/nginx/nginx.conf

# Relative path — relative to current directory
documents/file.txt    # If I'm in /home/user
../other/file.txt     # Go up, then into other/

# Special directories
.    # Current directory
..   # Parent directory
~    # Home directory
-    # Previous directory

📄 File Operations

Create, Copy, Move, Delete

# Create
touch file.txt          # Create empty file (or update timestamp)
mkdir new_dir           # Create directory
mkdir -p a/b/c/d        # Create nested directories (parents too)

# Copy
cp file.txt copy.txt    # Copy file
cp -r dir/ backup/      # Copy directory (recursive)
cp -a src/ dst/         # Archive mode (preserve permissions, links)

# Move / Rename
mv file.txt newname.txt # Rename
mv file.txt dir/        # Move file into directory
mv dir/ /other/location # Move directory

# Delete
rm file.txt             # Delete file (⚠️ no trash bin!)
rm -f file.txt          # Force delete (no prompt)
rm -rf dir/             # Delete directory + contents (⚠️ dangerous!)
rmdir empty_dir         # Remove empty directory (only empty dirs)
rm -rf /                # ⚠️ NEVER DO THIS — wipes your entire system!

Viewing Files

cat file.txt            # Display entire file (good for short files)
less file.txt           # Paginated view (scroll with arrows, q to quit)
head file.txt           # First 10 lines
head -n 20 file.txt     # First 20 lines
tail file.txt           # Last 10 lines
tail -n 50 file.txt     # Last 50 lines
tail -f file.txt        # Follow mode (like tail -f, for logs)

nl file.txt             # Numbered lines
wc file.txt             # Lines, words, characters
wc -l file.txt          # Line count only
wc -w file.txt          # Word count only
wc -c file.txt          # Byte/character count

Finding Files

# find — powerful file search
find . -name "*.txt"                # By name
find /var -size +100M               # Files larger than 100MB
find . -mtime -7                    # Modified in last 7 days
find . -type f -name "*.log"        # Only files (not directories)
find . -type d -name "uploads"      # Only directories

# locate — faster but uses a database (needs updatedb)
locate nginx.conf                    # Find file quickly
sudo updatedb                       # Update the database first

# which — find where a command is installed
which python3                       # /usr/bin/python3
which nginx                         # /usr/sbin/nginx

# whereis — find binaries, source, man pages
whereis python

File Content Search

# grep — THE text search tool
grep "error" log.txt                # Find lines containing "error"
grep -i "error" log.txt             # Case-insensitive
grep -r "TODO" src/                 # Recursive in directory
grep -l "main" *.py                 # List FILENAMES that match
grep -n "function" app.py           # Show line numbers
grep -c "ERROR" log.txt             # Count matches
grep -v "debug" log.txt             # Invert match (NOT debug)
grep -A 3 "exception" log.txt       # Show 3 lines AFTER match
grep -B 2 "error" log.txt           # Show 2 lines BEFORE match
grep -C 3 "warning" log.txt         # Show 3 lines around match

# Common grep patterns
grep "^error" log.txt               # Lines STARTING with "error"
grep "error$" log.txt               # Lines ENDING with "error"
grep "^[0-9]" log.txt               # Lines starting with number
grep "error\|warning" log.txt       # OR condition
grep -E "error|warning" log.txt     # Extended regex (same as above)

🔐 Permissions & Ownership

Linux is multi-user by design. Every file has an owner, a group, and permission levels.

Understanding Permissions

ls -l
# Output: -rwxr-xr--  1 user group  1024 Jun 1 10:00 file.txt
#          ^^^^^^^^^   ^^^^  ^^^^^
#          |           |     |
#          |           |     +-- Group owner
#          |           +-------- File owner
#          +-------------------- Permission string

# Permission string: 10 characters
# Position 1: Type (- file, d directory, l link)
# Positions 2-4: Owner permissions (rwx)
# Positions 5-7: Group permissions (r-x)
# Positions 8-10: Others permissions (r--)

# r = read (4), w = write (2), x = execute (1)
# -rwxr-xr-- means:
#   Owner:  rwx = 4+2+1 = 7 (read, write, execute)
#   Group:  r-x = 4+0+1 = 5 (read, execute)
#   Others: r-- = 4+0+0 = 4 (read only)

Changing Permissions

# Symbolic mode
chmod u+x file.sh           # Add execute for user (owner)
chmod g-w file.sh           # Remove write for group
chmod o+r file.sh           # Add read for others
chmod a+x file.sh           # Add execute for ALL (ugo)

# Numeric mode (octal)
chmod 755 file.sh           # rwxr-xr-x (standard scripts)
chmod 644 file.txt          # rw-r--r-- (standard files)
chmod 600 private.key       # rw------- (SSH keys!)
chmod 700 private_dir/      # rwx------ (private directory)
chmod 777 file              # ⚠️ NEVER — world-writable

# Commonly needed:
chmod +x script.sh          # Make script executable
chmod -R 755 dir/           # Change directory + all contents recursively

Changing Ownership

# Change owner (only root can do this)
sudo chown username file.txt        # Change owner
sudo chown username:group file.txt  # Change owner AND group
sudo chown -R username:group dir/   # Recursive

# Change group only
sudo chgrp groupname file.txt

# Default permissions for new files (umask)
umask                    # Show current umask (022 = default)
umask 027                # Set umask (new files: 750 for dirs, 640 for files)

👥 Users & Groups

# Who am I?
whoami                   # Current username
id                       # User ID, group ID, groups
id username              # Info about another user

# List users
cat /etc/passwd          # All users (system + human)
cat /etc/group           # All groups

# Managing users (needs root)
sudo useradd newuser                # Create user
sudo useradd -m -s /bin/bash newuser # Create with home dir + bash
sudo passwd newuser                 # Set password
sudo usermod -aG sudo newuser       # Add user to sudo group
sudo userdel -r newuser             # Delete user + home dir

# Managing groups
sudo groupadd devops                # Create group
sudo groupadd -r appgroup           # -r = system group (GID < 1000)
sudo gpasswd -a username devops     # Add user to group
sudo gpasswd -d username devops     # Remove user from group
groups username                     # Show user's groups

# Switch user
su - username            # Switch to another user (needs password)
sudo su -                # Switch to root
sudo -i                  # Also root shell

# Run command as another user
sudo -u www-data whoami  # Run command as www-data user

Sudo Access

# sudo = "superuser do" — execute command as root
sudo apt update
sudo systemctl restart nginx

# sudoers file: /etc/sudoers (edit with visudo, never manually)
# Common config:
#   username ALL=(ALL:ALL) ALL       # Full sudo access
#   %admin  ALL=(ALL) ALL            # Group can sudo
#   %sudo   ALL=(ALL:ALL) ALL        # Ubuntu default sudo group

# Run last command as sudo
sudo !!                  # !!

# Edit protected files
sudo vim /etc/hosts
sudo nano /etc/nginx/nginx.conf

⚙️ Processes & System Monitoring

Process Management

# View processes
ps                       # Your processes only
ps aux                   # All processes (detailed)
ps aux | grep nginx      # Find specific process
ps -ef                   # Full format listing
ps -eo pid,ppid,cmd,%mem,%cpu --sort=-%mem  # Custom format

top                      # Interactive process viewer
htop                     # Better interactive viewer (install: apt install htop)

# Process states:
# R = Running, S = Sleeping, D = Uninterruptible sleep
# Z = Zombie, T = Stopped, X = Dead

# Foreground/background
ctrl+z                   # Suspend foreground process (stop)
bg                       # Resume suspended job in background
fg                       # Bring background job to foreground
jobs                     # List background jobs

# Run in background
long_running_cmd &       # Run in background

# Kill processes
kill PID                 # Send SIGTERM (graceful stop)
kill -9 PID              # Send SIGKILL (force kill — use sparingly)
kill -15 PID             # Same as default (SIGTERM)
killall process_name     # Kill all by name
pkill -f "pattern"       # Kill by pattern (careful!)

# Find and kill
kill $(pgrep nginx)      # Get PID and kill
pkill nginx              # Simpler

# Background persistence
nohup command &          # Run immune to hangups (survives logout)
disown                   # Remove job from shell's job table
tmux or screen           # Full terminal multiplexers

System Monitoring

# System info
uname -a                 # Full system info
uname -r                 # Kernel version
hostname                 # System hostname
hostname -I              # IP addresses
uptime                   # How long running + load

# Disk usage
df -h                    # Disk free (human readable)
df -h /dev/sda1          # Specific partition
du -sh *                 # Disk usage of current directory
du -sh /var/log          # Disk usage of specific directory
du -h --max-depth=1      # One level deep

# Memory
free -h                  # Memory usage (human readable)
free -m                  # In megabytes
vmstat 2                 # Virtual memory stats (every 2s)

# CPU
lscpu                    # CPU info
nproc                    # Number of CPU cores
uptime                   # Load average (1min, 5min, 15min)

💡 Did You Know? The kill command name is misleading — by default it sends SIGTERM (signal 15), which asks the process to terminate gracefully. SIGKILL (signal 9) should be the last resort. Always try kill PID first before kill -9 PID.

📝 Vim Text Editor

Vim is the most powerful terminal text editor. You can't avoid it on Linux — it's everywhere.

Vim Modes

# Vim has modes — this confuses beginners but makes it powerful
# NORMAL mode: default, for navigation and commands
# INSERT mode: for typing text
# VISUAL mode: for selecting text
# COMMAND mode: for saving, quitting, searching

# Start Vim
vim file.txt
# You start in NORMAL mode

Essential Vim Commands

# ----- NAVIGATION (NORMAL mode) -----
h j k l              # Left, Down, Up, Right (arrows also work)
w                    # Next word
b                    # Previous word
0                    # Start of line
$                    # End of line
gg                   # First line of file
G                    # Last line of file
:42                  # Go to line 42
ctrl+d               # Page down
ctrl+u               # Page up
%                    # Matching bracket

# ----- INSERT (typing) -----
i                    # Insert before cursor
a                    # Insert after cursor
I                    # Insert at beginning of line
A                    # Insert at end of line
o                    # New line below
O                    # New line above
s                    # Delete character and insert
S                    # Delete line and insert
Esc                  # Back to NORMAL mode

# ----- EDITING (NORMAL mode) -----
x                    # Delete character under cursor
dd                   # Delete (cut) line
5dd                  # Delete 5 lines
dw                   # Delete word
yy                   # Copy (yank) line
5yy                  # Copy 5 lines
p                    # Paste below
P                    # Paste above
u                    # Undo
ctrl+r               # Redo
.                    # Repeat last change

# ----- VISUAL MODE -----
v                    # Start visual selection
V                    # Select entire lines
ctrl+v               # Block selection
y                    # Copy selected
d                    # Delete selected
>                    # Indent right
<                    # Indent left

# ----- SEARCH & REPLACE -----
/pattern             # Search forward
?pattern             # Search backward
n                    # Next match
N                    # Previous match
:%s/old/new/g        # Replace all 'old' with 'new' in file
:%s/old/new/gc       # Replace with confirmation

# ----- SAVE & QUIT -----
:w                   # Save
:q                   # Quit
:q!                  # Quit without saving (force)
:wq                  # Save and quit
😡                   # Save and quit (same, shorter)
:w file2.txt         # Save as (write to new file)

# ----- MISC -----
:set number          # Show line numbers
:set nonumber        # Hide line numbers
:set paste           # Paste mode (no auto-indent)
:help                # Vim help
:!command            # Run shell command from vim (e.g., :!python test.py)

Nano — Simpler Alternative

# Nano is beginner-friendly — no modes, always typing
nano file.txt
ctrl+o    # Save (write out)
ctrl+x    # Exit
ctrl+w    # Search
ctrl+k    # Cut line
ctrl+u    # Paste
ctrl+g    # Help

🌐 Networking

Network Diagnostics

# Connectivity
ping google.com          # Test connectivity (ctrl+c to stop)
ping -c 4 google.com     # Send 4 pings and stop
ping -4 google.com       # Force IPv4

# DNS
nslookup google.com      # DNS lookup
dig google.com           # Detailed DNS info
dig google.com A         # Only A records
dig google.com MX        # Mail exchange records
host google.com          # Simple DNS lookup

# Routing
traceroute google.com    # Show route to host
tracepath google.com     # Simpler traceroute (no root needed)
ip route                 # Show routing table
route -n                 # Old way, still works

# Port scanning
nc -zv host.com 80       # Check if port is open
nc -zv host.com 1-1000   # Scan port range
nmap -sT host.com        # Full port scan (install: apt install nmap)

# Connection info
ss -tulpn                # Show listening ports (modern)
netstat -tulpn           # Show listening ports (old)
ss -tupn                 # Show active connections

Configuring Network

# Interface info
ip addr                  # Show IP addresses (modern)
ifconfig                 # Show IP addresses (old)

# Enable/disable interfaces
sudo ip link set eth0 up
sudo ip link set eth0 down

# Static IP (Ubuntu/Debian) — edit /etc/netplan/*.yaml
# Or use nmcli
nmcli dev status                    # List devices
nmcli con show                      # List connections
nmcli con mod "Wired" ipv4.address 192.168.1.100/24

# Hostname
hostnamectl set-hostname myserver
cat /etc/hostname

# Hosts file
cat /etc/hosts          # Local DNS resolution
# Format: IP_ADDRESS HOSTNAME [alias]
# 127.0.0.1   localhost
# 192.168.1.10  myserver

# Resolv.conf (DNS servers)
cat /etc/resolv.conf
# nameserver 8.8.8.8
# nameserver 1.1.1.1

File Transfer

# SCP — Secure Copy (over SSH)
scp file.txt user@host:/path/              # Copy TO server
scp user@host:/path/file.txt .             # Copy FROM server
scp -r dir/ user@host:/path/               # Copy directory
scp -P 2222 file.txt user@host:/path/      # Custom port

# RSYNC — Sync (smart: only sends changes)
rsync -avz source/ user@host:/dest/        # Sync to server
rsync -avz --delete source/ user@host:/dest/  # Remove extra files
rsync -avz -e "ssh -p 2222" source/ user@host:/dest/  # Custom port

# wget — Download from web
wget https://example.com/file.zip
wget -O output.zip https://example.com/file.zip  # Custom filename
wget -c https://example.com/large.zip            # Continue interrupted download
wget -r https://example.com/                     # Recursive download

# curl — Transfer data (more features than wget)
curl https://api.github.com/users/octocat        # Get URL
curl -o file.zip https://example.com/file.zip    # Download
curl -O https://example.com/file.zip             # Download (keep name)
curl -I https://example.com                      # Show headers only
curl -X POST -d '{"key":"value"}' -H "Content-Type: application/json" https://api.example.com/data

📦 Package Management

APT (Debian/Ubuntu)

sudo apt update               # Update package list
sudo apt upgrade              # Upgrade all packages
sudo apt full-upgrade         # Upgrade with dependency changes
sudo apt install nginx        # Install a package
sudo apt install -y nginx     # Install without prompts
sudo apt remove nginx         # Remove package (keeps config)
sudo apt purge nginx          # Remove package + config files
sudo apt autoremove           # Remove unused dependencies
sudo apt clean                # Clean downloaded .deb cache
apt list --installed          # List installed packages
apt search "keyword"          # Search for packages
apt show nginx                # Package details
apt policy nginx              # Available versions

DNF/YUM (RHEL/CentOS/Fedora)

sudo dnf check-update         # Check for updates
sudo dnf update               # Update all packages
sudo dnf install nginx        # Install
sudo dnf remove nginx         # Remove
sudo dnf autoremove           # Clean up
sudo dnf clean all            # Clean cache
dnf list installed            # List installed
dnf search "keyword"          # Search
dnf info nginx                # Package info

Snap & Flatpak

# Snap (Ubuntu)
sudo snap install lxd
sudo snap list
sudo snap remove lxd

# Flatpak (cross-distro)
flatpak install flathub org.gimp.GIMP
flatpak list
flatpak run org.gimp.GIMP

📜 Shell Scripting

Shell scripts are how you automate everything in Linux. A script is just a text file with commands.

Your First Script

#!/bin/bash
# This is a comment
echo "Hello, World!"
echo "Today is $(date)"
echo "You are logged in as $(whoami)"
# Save as hello.sh, then:
chmod +x hello.sh
./hello.sh

Variables

#!/bin/bash
name="Alice"
age=25
echo "My name is $name and I am $age years old."
echo "I am ${name}son"  # Curly braces to separate: "Aliceson"

# Command substitution
current_dir=$(pwd)
echo "You are in: $current_dir"

# Special variables
echo "Script name: $0"
echo "First argument: $1"
echo "All arguments: $@"
echo "Number of args: $#"
echo "Exit code of last command: $?"
echo "Process ID: $$"

Conditionals

#!/bin/bash
# File tests
if [ -f "$1" ]; then
    echo "$1 is a file"
elif [ -d "$1" ]; then
    echo "$1 is a directory"
else
    echo "$1 does not exist"
fi

# String comparison
if [ "$name" = "Alice" ]; then
    echo "Hello Alice!"
fi

# Numeric comparison
age=25
if [ "$age" -ge 18 ]; then
    echo "Adult"
else
    echo "Minor"
fi

# Common test operators:
# -f file     File exists
# -d dir      Directory exists
# -e path     Path exists (file or dir)
# -z string   String is empty
# -n string   String is not empty
# string1 = string2    Equal
# num1 -eq num2        Equal (-ne, -gt, -ge, -lt, -le)

# AND / OR
if [ -f "$1" ] && [ "$2" = "yes" ]; then
    echo "File exists AND flag is yes"
fi
if [ -f "$1" ] || [ -d "$1" ]; then
    echo "File or directory exists"
fi

Loops

#!/bin/bash
# For loop
for i in 1 2 3 4 5; do
    echo "Number: $i"
done

# Range
for i in {1..10}; do
    echo "Count: $i"
done

# For files
for file in *.txt; do
    echo "Processing: $file"
    wc -l "$file"
done

# While loop
count=0
while [ "$count" -lt 5 ]; do
    echo "Count: $count"
    ((count++))
done

# Loop through command output
for user in $(cat /etc/passwd | cut -d: -f1); do
    echo "User: $user"
done

Functions

#!/bin/bash
function greet() {
    local name="$1"   # local scope
    echo "Hello, $name!"
}

greet "Alice"

# Return values
function add() {
    local sum=$(( $1 + $2 ))
    echo "$sum"  # Captured with $()
}

result=$(add 5 3)
echo "5 + 3 = $result"

Practical Script Examples

#!/bin/bash
# backup.sh — Backup a directory with timestamp
src="$1"
dest="$2"

if [ -z "$src" ] || [ -z "$dest" ]; then
    echo "Usage: $0 <source_dir> <dest_dir>"
    exit 1
fi

if [ ! -d "$src" ]; then
    echo "Error: Source directory not found"
    exit 1
fi

timestamp=$(date +%Y%m%d_%H%M%S)
backup_name="backup_$(basename $src)_$timestamp.tar.gz"

echo "Creating backup..."
tar czf "$dest/$backup_name" "$src"
echo "✅ Backup saved: $dest/$backup_name"
#!/bin/bash
# monitor.sh — Monitor disk usage and alert
threshold="${1:-80}"  # Default 80%

df -h | grep -v "tmpfs\|loop" | awk '{print $5, $6}' | while read usage mount; do
    percent="${usage%\%}"
    if [ "$percent" -gt "$threshold" ]; then
        echo "⚠️  WARNING: $mount is at ${usage}!"
    fi
done

🔗 Pipes & Redirection

The pipe (|) is the most powerful concept in Linux. It connects the output of one command to the input of another.

Pipes

# Basic pipe — combine commands
ls -la | grep ".txt"                  # Find .txt files in ls output
ps aux | grep nginx                    # Find nginx processes
cat log.txt | grep "ERROR" | head     # Errors, first 10
cat log.txt | grep "ERROR" | wc -l    # Count errors
dmesg | tail -20                       # Last 20 kernel messages
history | grep "docker"                # Find docker commands in history

# Useful pipe chains
ls -ltr | tail -5                      # 5 newest files
du -sh * | sort -rh | head -10         # 10 largest items
cat /var/log/syslog | grep -i "error" | awk '{print $1, $2, $NF}' | sort | uniq -c | sort -rn | head -10
# Reads syslog, finds errors, prints date/time + last field, counts unique

Redirection

# Output redirection (>)
echo "Hello" > file.txt       # Write to file (overwrites!)
echo "World" >> file.txt      # Append to file

# Input redirection (<)
sort < file.txt               # Read from file

# Error redirection (2>)
command 2> error.log          # Redirect errors to file
command 2>> error.log         # Append errors
command > output.log 2>&1     # Both stdout and stderr
command &> output.log         # Same as above (bash 4+)
command &>> output.log        # Append both

# Discard output
command > /dev/null           # Throw away stdout
command 2> /dev/null          # Throw away stderr
command &> /dev/null          # Throw away both

# Here document (inline file)
cat << EOF > config.txt
server {
    listen 80;
    server_name example.com;
}
EOF

🗜️ Archives & Compression

# tar — Tape archive (combines files, optionally compresses)
tar cvf archive.tar dir/            # Create (c) verbose (v) file (f)
tar xvf archive.tar                 # Extract (x)
tar tvf archive.tar                 # List contents (t)

# tar + gzip (most common)
tar czvf archive.tar.gz dir/        # Create compressed
tar xzvf archive.tar.gz             # Extract
tar tzvf archive.tar.gz             # List

# tar + bzip2 (slower, smaller)
tar cjvf archive.tar.bz2 dir/       # Create
tar xjvf archive.tar.bz2            # Extract

# ZIP (cross-platform)
zip -r archive.zip dir/             # Create
unzip archive.zip                   # Extract
unzip -l archive.zip                # List contents

# gzip single file
gzip file.txt               # Compress → file.txt.gz
gunzip file.txt.gz          # Decompress → file.txt
gzip -d file.txt.gz         # Same as gunzip
gzip -k file.txt            # Keep original file

# Other
bzip2 file.txt              # Better compression, slower
xz file.txt                 # Best compression, slowest
7z a archive.7z dir/        # 7-Zip (install: apt install p7zip-full)

🔑 SSH — Secure Shell

SSH is how you connect to remote servers. It's the backbone of Linux administration.

Basic SSH

# Connect to a remote server
ssh user@192.168.1.100               # Basic
ssh user@hostname.com                # Use hostname
ssh -p 2222 user@host.com            # Custom port
ssh -i ~/.ssh/key.pem user@host.com  # Use specific key

# Execute command remotely
ssh user@host "uptime"
ssh user@host "df -h" | grep sda1

# SSH config (create ~/.ssh/config)
Host myserver
    HostName 192.168.1.100
    User admin
    Port 2222
    IdentityFile ~/.ssh/mykey

# Then just: ssh myserver

# Copy SSH key (passwordless login)
ssh-copy-id user@host                # Copy your public key
# Now: ssh user@host — no password! (key-based auth)

SSH Keys

# Generate SSH key pair
ssh-keygen -t ed25519 -C "your@email.com"   # Modern (Ed25519)
ssh-keygen -t rsa -b 4096 -C "your@email.com"  # Compatible

# Files created:
# ~/.ssh/id_ed25519       — PRIVATE KEY (never share!)
# ~/.ssh/id_ed25519.pub   — PUBLIC KEY (share freely)

# Key permissions (MUST be correct)
chmod 700 ~/.ssh
chmod 600 ~/.ssh/id_ed25519
chmod 644 ~/.ssh/id_ed25519.pub

# SSH agent (so you don't type passphrase repeatedly)
eval "$(ssh-agent -s)"
ssh-add ~/.ssh/id_ed25519

# Key management
ssh-keygen -p             # Change passphrase
ssh-keygen -l -f ~/.ssh/id_ed25519  # Show fingerprint

SSH Tunneling

# Local port forwarding (access remote service locally)
ssh -L 8080:localhost:80 user@host
# Now http://localhost:8080 → remote host's port 80

# Remote port forwarding (expose local service remotely)
ssh -R 8080:localhost:3000 user@host
# Remote: http://localhost:8080 → your local port 3000

# SOCKS proxy (secure browsing through server)
ssh -D 1080 user@host
# Configure browser to use SOCKS5 proxy on localhost:1080

# Jump host (connect through a bastion)
ssh -J jumpuser@bastion.com targetuser@target.internal

🛠️ systemd — Service Management

systemd is the init system used by most Linux distributions. It manages services, sockets, timers, and more.

# Service management
sudo systemctl start nginx          # Start service
sudo systemctl stop nginx           # Stop service
sudo systemctl restart nginx        # Restart service
sudo systemctl reload nginx         # Reload config (no downtime)
sudo systemctl enable nginx         # Start on boot
sudo systemctl disable nginx        # Don't start on boot
sudo systemctl enable --now nginx   # Enable AND start

# Status
systemctl status nginx              # Status + recent logs
systemctl is-active nginx           # active/inactive
systemctl is-enabled nginx          # enabled/disabled

# List services
systemctl list-units --type=service         # Running services
systemctl list-unit-files --type=service    # All installed
systemctl list-units --type=service --state=failed  # Failed services

# Journalctl — view system logs
journalctl -u nginx                 # Logs for nginx service
journalctl -u nginx -f              # Follow logs
journalctl -u nginx --since "1 hour ago"
journalctl -u nginx --until "yesterday"
journalctl -k                       # Kernel logs
journalctl -p err                   # Error level and above
journalctl --disk-usage             # Log size
journalctl --vacuum-size=500M       # Limit log size

Creating a Systemd Service

# /etc/systemd/system/myapp.service
[Unit]
Description=My Python Application
After=network.target postgresql.service
Wants=postgresql.service

[Service]
Type=simple
User=appuser
WorkingDirectory=/opt/myapp
ExecStart=/usr/bin/python3 /opt/myapp/app.py
Restart=on-failure
RestartSec=5
EnvironmentFile=/opt/myapp/.env
StandardOutput=journal
StandardError=journal

[Install]
WantedBy=multi-user.target

# Enable and start
sudo systemctl daemon-reload         # Reload after creating service
sudo systemctl enable --now myapp
sudo systemctl status myapp

⏰ Cron & Task Scheduling

# Crontab format: minute hour day month weekday command
#   * = any, */5 = every 5, 1-5 = range, 1,3,5 = list

# Edit your crontab
crontab -e

# Examples:
# ┌── minute (0-59)
# │ ┌── hour (0-23)
# │ │ ┌── day of month (1-31)
# │ │ │ ┌── month (1-12)
# │ │ │ │ ┌── day of week (0-7, 0=Sun)
# │ │ │ │ │
# * * * * * command_to_run

# Common schedules
*/5 * * * * /opt/scripts/check.sh       # Every 5 minutes
0 * * * * /opt/scripts/hourly.sh        # Every hour
0 9 * * * /opt/scripts/daily.sh         # Daily at 9 AM
0 2 * * 1 /opt/scripts/weekly.sh        # Monday at 2 AM
0 0 1 * * /opt/scripts/monthly.sh       # 1st of month at midnight
0 9 * * 1-5 /opt/scripts/workday.sh     # Weekdays at 9 AM

# List cron jobs
crontab -l

# Remove all cron jobs
crontab -r

# System-wide cron (root)
sudo crontab -e -u root

# Special directories (run scripts from here)
/etc/cron.hourly/          # Scripts run hourly
/etc/cron.daily/           # Scripts run daily
/etc/cron.weekly/          # Scripts run weekly
/etc/cron.monthly/         # Scripts run monthly

# at — one-time scheduled task
echo "backup.sh" | at 2:00 PM tomorrow
at 10:00 PM next week
    > /opt/scripts/cleanup.sh
    > Ctrl+D
atq                         # List pending
atrm 5                      # Remove job #5

🏗️ Real-World Project: Linux Server Setup

Let's apply everything to set up a production web server from scratch.

Step 1: Initial Server Access

# SSH in
ssh root@your-server-ip

# Create a normal user (never work as root!)
useradd -m -s /bin/bash deploy
passwd deploy
usermod -aG sudo deploy

# Copy SSH key for the new user
rsync --chown=deploy:deploy ~/.ssh /home/deploy/

# Now ssh deploy@your-server (not root!)
ssh deploy@your-server-ip

Step 2: System Updates & Security

# Update everything
sudo apt update && sudo apt upgrade -y

# Install essential tools
sudo apt install -y \
    nginx \
    certbot \
    python3-certbot-nginx \
    ufw \
    fail2ban \
    htop \
    git \
    curl \
    wget \
    vim

# Configure firewall
sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw allow ssh
sudo ufw allow http
sudo ufw allow https
sudo ufw enable
sudo ufw status verbose

# Configure SSH security
sudo vim /etc/ssh/sshd_config
# Set:
#   Port 2222                    # Change from default 22
#   PermitRootLogin no           # Disable root login
#   PasswordAuthentication no    # Key-only auth
#   MaxAuthTries 3               # Limit attempts
sudo systemctl restart sshd

# Install fail2ban (blocks brute-force)
sudo systemctl enable --now fail2ban

Step 3: Deploy Application

# Clone your app
sudo mkdir -p /opt/apps
sudo chown deploy:deploy /opt/apps
cd /opt/apps
git clone https://github.com/yourusername/your-app.git myapp
cd myapp

# Set up Python virtual environment
python3 -m venv venv
source venv/bin/activate
pip install -r requirements.txt

# Set up systemd service (as shown above)
sudo vim /etc/systemd/system/myapp.service
sudo systemctl daemon-reload
sudo systemctl enable --now myapp

# Set up Nginx reverse proxy
sudo vim /etc/nginx/sites-available/myapp
# server {
#     listen 80;
#     server_name yourdomain.com;
#     location / {
#         proxy_pass http://127.0.0.1:8000;
#         proxy_set_header Host $host;
#     }
# }
sudo ln -s /etc/nginx/sites-available/myapp /etc/nginx/sites-enabled/
sudo nginx -t               # Test config
sudo systemctl reload nginx

# Set up HTTPS (Let's Encrypt)
sudo certbot --nginx -d yourdomain.com

# Set up automatic renewal
sudo certbot renew --dry-run

Step 4: Monitoring & Logging

# Set up log rotation
sudo vim /etc/logrotate.d/myapp
# /var/log/myapp/*.log {
#     daily
#     rotate 7
#     compress
#     delaycompress
#     missingok
#     notifempty
#     create 0640 deploy deploy
#     sharedscripts
#     postrotate
#         systemctl reload myapp
#     endscript
# }

# Monitor with htop
htop

# Check logs
journalctl -u myapp -f
tail -f /var/log/nginx/access.log
tail -f /var/log/nginx/error.log

# Resource monitoring
watch -n 1 'ps aux | sort -nrk 3 | head -10'  # Top CPU processes
watch -n 1 'ps aux | sort -nrk 4 | head -10'  # Top memory processes

❌ Common Mistakes & How to Avoid Them

🔴 Mistake #1: rm -rf with Wrong Path

What happens: rm -rf / or rm -rf .* can destroy your entire system in milliseconds.

How to fix: Always double-check before running rm -rf. Use ls first. Consider trash-cli (safer alternative). And never run rm -rf /.

🔴 Mistake #2: Chmod 777

What happens: Every user on the system can read, write, and execute the file. Security nightmare.

How to fix: Use specific permissions. 755 for scripts, 644 for files, 600 for keys. Never 777.

🔴 Mistake #3: Working as Root

What happens: One wrong command as root can destroy the system. A typo in rm -rf /var becomes rm -rf / var.

How to fix: Create a normal user with sudo access. Use sudo for admin commands. sudo !! to re-run last command with sudo.

🔴 Mistake #4: Forgetting to Quote Variables

What happens: A filename with spaces becomes multiple arguments. rm $file with file="my document.txt" deletes two files.

How to fix: Always quote: "$file", "$@", "$(command)".

🔴 Mistake #5: Ignoring Exit Codes

What happens: A command fails silently and the next command runs on bad data. cd /nonexistent && rm -rf * runs rm in the wrong directory.

How to fix: Check $? after commands. Use set -e in scripts to exit on error. Use || for fallbacks.

🔴 Mistake #6: Not Using .gitignore for Secrets

What happens: API keys and passwords committed to Git and pushed to public repos.

How to fix: Use environment variables. Keep secrets in .env files (added to .gitignore). Use git-secrets to block accidental commits.

🧠 Test Your Knowledge

  1. What does chmod 755 script.sh do?

    A) Makes it world-writable

    B) Sets rwxr-xr-x permissions (owner all, group/others read+execute)

    C) Removes execute permission

    D) Changes the owner

    Answer: B — 755 = rwxr-xr-x. Owner has full access, others can read/execute.
  2. What's the difference between > and >>?

    A) Nothing

    B) > overwrites, >> appends

    C) > sends to stdout, >> to stderr

    D) > is for files, >> for directories

    Answer: B — > creates/overwrites the file. >> appends to the file.
  3. Which command shows running processes in real-time?

    A) ps

    B) top

    C) ls

    D) df

    Answer: B — top (or htop) shows real-time process listing.
  4. What does grep -r "TODO" . do?

    A) Searches for "TODO" in the current directory recursively

    B) Removes "TODO" from all files

    C) Counts "TODO" occurrences

    D) Creates a TODO list

    Answer: A — -r makes grep search recursively through directories.
  5. What's the correct way to make a script executable?

    A) run script.sh

    B) chmod +x script.sh

    C) execute script.sh

    D) bash script.sh

    Answer: B — chmod +x adds execute permission. (D works too but doesn't make it executable permanently.)

❓ Frequently Asked Questions (FAQ)

Q1: Which Linux distro should I start with?

Ubuntu is the best choice for beginners. It has the largest community (easiest to find help), best hardware support, and most documentation. For servers, Ubuntu LTS or Debian are standard. Once you're comfortable, try Fedora or Arch.

Q2: What's the best way to learn Linux?

Install it and use it daily. Start with WSL2 on Windows or a Raspberry Pi running Linux. Break things and fix them. Set up a personal server. The fastest way to learn is to have a problem you need to solve (host a website, set up a database, automate a backup).

Q3: How do I recover a deleted file?

There's no "trash" in the terminal — rm deletes immediately. If you're lucky, extundelete or testdisk might recover it if you act fast and unmount the filesystem. Prevention: use trash-cli instead of rm, or use version control (Git) for everything.

Q4: What's the difference between bash and sh?

bash (Bourne Again SHell) is the enhanced version of sh (Bourne shell). bash adds features like arrays, [[ ]] conditionals, function keyword, source, and more. On most modern Linux systems, /bin/sh is symlinked to bash or dash. Write scripts with #!/bin/bash for full features.

Q5: How do I check which port a process is using?

ss -tulpn shows all listening ports and the processes using them. lsof -i :80 shows what's using port 80. netstat -tulpn is the older command but still widely used.

Q6: How do I set up automatic security updates?

Install unattended-upgrades: sudo apt install unattended-upgrades. Configure in /etc/apt/apt.conf.d/50unattended-upgrades. Enable auto-reboot for kernel updates. This is standard for production servers.

Q7: What's the difference between soft and hard links?

Soft links (symlinks, ln -s) are shortcuts — they point to the filename. If the original is deleted, the link breaks. Hard links (ln) are additional directory entries pointing to the same inode (data). Deleting one leaves the data accessible through the other. Hard links can't cross filesystem boundaries.

Q8: How do I monitor network traffic?

iftop shows real-time bandwidth per connection. nethogs shows bandwidth per process. tcpdump captures packets for analysis. bmon shows overall bandwidth. vnstat keeps historical traffic data. Install with sudo apt install iftop nethogs tcpdump bmon vnstat.

Q9: Should I use swap space?

Yes, unless you have specific performance requirements. Swap acts as emergency memory when RAM runs out. Rule of thumb: if RAM < 2GB, swap = 2x RAM. If RAM 2-8GB, swap = RAM size. If RAM > 8GB, swap = 4-8GB. On servers with SSD, put swap on SSD.

Q10: How do I make a command run at startup?

Use systemd (create a .service file in /etc/systemd/system/), add to /etc/rc.local, use cron with @reboot, or add to /etc/init.d/. Systemd is the modern standard. Service files are more flexible and reliable than rc.local.

📖 Glossary

Term Definition
Kernel The core of Linux — manages hardware, processes, memory, and drivers
Shell Command interpreter — bash, zsh, fish, sh
Terminal The application window where you type commands
Pipe Connects stdout of one command to stdin of another (|)
Redirect Send output to a file (>) or read input from a file (<)
SUID Special permission that runs a program as the file owner, not the user
Inode Data structure storing metadata about a file (permissions, timestamps, location)
Symlink Symbolic link — a special file that points to another file or directory
Daemon A background process that runs without user interaction (e.g., nginx, sshd)
FHS Filesystem Hierarchy Standard — the directory structure Linux follows

✅ Do's & Don'ts

✅ Do ❌ Don't
Use a regular user with sudo Work as root all the time
Quote variables in scripts Leave $variables unquoted
Use SSH keys for auth Use password-based SSH
Double-check rm -rf paths Run rm -rf without verifying
Use version control for configs Edit live config files without backups
Keep your system updated Ignore security updates

💡 10 Pro Tips Learned the Hard Way

  1. Tab completion is your best friend. Press Tab to autocomplete commands, paths, and filenames. Press Tab twice to see all options. It saves keystrokes and prevents typos.
  2. Use history effectively. history shows your command history. !! repeats the last command. !$ repeats the last argument. !docker runs the last docker command. ctrl+r searches history interactively.
  3. Never run rm -rf / — even as a joke. On modern systems it requires --no-preserve-root, but older versions will wipe everything. The same goes for chmod -R 777 /.
  4. Use alias for common commands. Add to ~/.bashrc: alias ll='ls -la', alias gs='git status', alias ..='cd ..', alias please='sudo $(history -p !!)'.
  5. Learn to read man pages. The manual is always more accurate than Google. man ls tells you everything ls can do. Press / to search within a man page, n for next match.
  6. Use watch to run commands periodically. watch -n 2 df -h shows disk usage every 2 seconds. watch 'ps aux | sort -nrk 3 | head' shows top CPU processes updating live.
  7. Customize your prompt. PS1='\u@\h:\w\$ ' in ~/.bashrc shows user@host:path$. Add colors, git branch, timestamps — make it work for you.
  8. Use screen or tmux for remote sessions. If your SSH connection drops, the session survives. Reconnect with tmux attach. Critical for long-running tasks on remote servers.
  9. Master awk and sed. awk '{print $1}' prints the first column of any output. sed 's/old/new/g' replaces text. Combined with pipes, they're unstoppable.
  10. Backup before major changes. Before editing /etc/nginx/nginx.conf, copy it: cp /etc/nginx/nginx.conf{,.bak}. Before running a potentially destructive command, think "what's my rollback plan?"

🗺️ Learning Roadmap

Day Topic Goal ⏱️
1 Navigation & Files ls, cd, pwd, cp, mv, rm, mkdir, cat, less, head, tail 60 min
2 Permissions & Users chmod, chown, useradd, sudo, groups, umask 90 min
3 Search & Text Processing grep, find, locate, wc, sort, uniq, awk, sed 90 min
4 Pipes, Redirection & Vim |, >, >>, 2>, vim basics (edit files confidently) 120 min
5 Processes & Monitoring ps, top, kill, df, du, free, systemctl, journalctl 90 min
6 Networking & SSH ssh, scp, rsync, curl, wget, ping, ss, ufw 120 min
7 Shell Scripting & Automation Write scripts, cron jobs, systemd services, deploy a server 180 min

🔍 Troubleshooting

⚠️ Problem 🔍 Cause ✅ Solution
Command not found Package not installed or not in PATH apt install package_name or check PATH with echo $PATH
Permission denied File not executable or wrong owner chmod +x file or use sudo or chown
Disk full Logs, cache, or large files du -sh /* | sort -rh | head -10 — find the culprit
Can't connect SSH Firewall, wrong port, or SSH key issue Check ufw status, verify port (default 22), check ~/.ssh permissions
Service won't start Config error or missing dependency journalctl -u service -f for real-time logs. systemctl status service

💬 What's Your Experience?

What's your Linux story? First distro? Biggest disaster? Drop a comment — I read every one.

Quick questions:

  • What was the hardest Linux concept to learn?
  • What's your favorite Linux command?
  • Ubuntu vs Arch — which camp are you in?
  • What do you wish you knew when you started?

📌 TL;DR: If You Learn Nothing Else, Learn These 5

  1. File Operations — ls, cp, mv, rm, mkdir, chmod, chown. You'll use these 100 times a day.
  2. Pipes & Grepcommand | grep pattern solves most problems. Master this.
  3. Vim Basics — i (insert), Esc, :wq (save & quit), dd (delete line), /search. That's 90% of what you need.
  4. Process Management — ps aux, kill, systemctl, journalctl. Know how to find and fix problems.
  5. Networking — ssh, scp, curl, ping, ss -tulpn. Essential for remote work.

More Free Courses on TricksPage

💭 Final Thoughts

Learning Linux is a superpower. Every tech company runs on Linux. Every cloud runs on Linux. Every container is Linux. When you know the command line, you're not just using a computer — you're commanding it.

The commands you learned today haven't changed in 30 years. They won't change in the next 30. That's the beauty of Linux — it's a stable foundation that rewards deep learning. Every hour you invest in Linux skills pays dividends for your entire career.

🔥 Final Word: "Unix was not designed to stop its users from doing stupid things, because that would also stop them from doing clever things." — Doug Gwynn

The best time to start was yesterday. The second best time is now. 🐧

More Free Courses on TricksPage

If this course helped you:

  • 📌 Bookmark this page for future reference
  • 📤 Share it with someone who needs it
  • 💬 Leave a comment — I read every one
  • Follow the blog for more deep courses

Leave a Reply

Your email address will not be published. Required fields are marked *