🐧 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.
🐧 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
killcommand 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 trykill PIDfirst beforekill -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
- What does
chmod 755 script.shdo?
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. - 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. - Which command shows running processes in real-time?
A)ps
B)top
C)ls
D)df
Answer: B —top(orhtop) shows real-time process listing. - 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 —-rmakes grep search recursively through directories. - 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 +xadds 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
- 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.
- Use history effectively.
historyshows your command history.!!repeats the last command.!$repeats the last argument.!dockerruns the last docker command.ctrl+rsearches history interactively. - 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 forchmod -R 777 /. - Use
aliasfor common commands. Add to~/.bashrc:alias ll='ls -la',alias gs='git status',alias ..='cd ..',alias please='sudo $(history -p !!)'. - Learn to read
manpages. The manual is always more accurate than Google.man lstells you everythinglscan do. Press/to search within a man page,nfor next match. - Use
watchto run commands periodically.watch -n 2 df -hshows disk usage every 2 seconds.watch 'ps aux | sort -nrk 3 | head'shows top CPU processes updating live. - Customize your prompt.
PS1='\u@\h:\w\$ 'in~/.bashrcshows user@host:path$. Add colors, git branch, timestamps — make it work for you. - Use
screenortmuxfor remote sessions. If your SSH connection drops, the session survives. Reconnect withtmux attach. Critical for long-running tasks on remote servers. - Master
awkandsed.awk '{print $1}'prints the first column of any output.sed 's/old/new/g'replaces text. Combined with pipes, they're unstoppable. - 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
- File Operations — ls, cp, mv, rm, mkdir, chmod, chown. You'll use these 100 times a day.
- Pipes & Grep —
command | grep patternsolves most problems. Master this. - Vim Basics — i (insert), Esc, :wq (save & quit), dd (delete line), /search. That's 90% of what you need.
- Process Management — ps aux, kill, systemctl, journalctl. Know how to find and fix problems.
- Networking — ssh, scp, curl, ping, ss -tulpn. Essential for remote work.
More Free Courses on TricksPage
- Git & GitHub Course — Master Git from basics to collaboration workflows.
- Docker & Swarm Course — Containers, Dockerfiles, Compose, Swarm.
- n8n Automation Course — Workflow automation with 400+ integrations.
- Python Course — Master Python from beginner to pro.
- Agentic AI Course — Build intelligent AI agents.
💭 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
- Git & GitHub Course — Master Git from basics to collaboration workflows.
- Docker & Swarm Course — Containers, Dockerfiles, Compose, Swarm.
- n8n Automation Course — Workflow automation with 400+ integrations.
- Python Course — Master Python from beginner to pro.
- Agentic AI Course — Build intelligent AI agents.
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