Linux Commands Guide 2026 — Server Administration and Shell Scripting for Developers
Advertisement
Introduction
Why This Matters
Every production environment runs Linux. The ability to navigate, debug, and automate on a Linux server is the difference between resolving an incident in minutes or hours. Whether you are on a VPS, an EC2 instance, or a Kubernetes node, these skills are essential for any developer owning their infrastructure in 2026.
Essential Navigation and File Operations
# Navigation
pwd # Print working directory
ls -la # List with hidden files and details
cd /var/log # Change directory
cd ~ # Go to home
cd - # Go to previous directory
# File operations
cp -r src/ dest/ # Copy recursively
mv old.txt new.txt # Move or rename
rm -rf directory/ # Delete directory (be careful)
mkdir -p /path/to/dir # Create with parent directories
ln -s /actual/path link # Create symlink
# Finding files
find . -name "*.log" -newer /tmp/marker # Recently modified
find . -size +100M # Files larger than 100MB
find . -type f -name "*.ts" | wc -l # Count TypeScript files
# Search content
grep -r "TODO" src/ # Recursive search
grep -n "error" app.log # With line numbers
grep -E "ERROR|WARN" app.log # Regex alternation
grep -v "DEBUG" app.log # Exclude matchesFile Permissions
# Permission format: type + owner + group + others
# r=read(4), w=write(2), x=execute(1)
# ls output: -rw-r--r-- 1 ubuntu ubuntu 1234 app.js
chmod 755 script.sh # rwxr-xr-x
chmod 644 config.json # rw-r--r--
chmod +x deploy.sh # Add execute for all
chmod -R 755 public/ # Recursive
chown ubuntu:ubuntu file.txt
chown -R www-data:www-data /var/www/Process Management
# View processes
ps aux # All running processes
ps aux | grep node # Find Node.js processes
top # Real-time view (q to quit)
htop # Better TUI (if installed)
# Manage processes
kill 1234 # Terminate by PID
kill -9 1234 # Force kill
pkill node # Kill all matching name
lsof -i :3000 # What process is using port 3000
# Background processes
command & # Run in background
nohup command & # Continue after logout
jobs # List background jobs
fg %1 # Bring job 1 to foreground
# System resources
free -h # Memory usage (human-readable)
df -h # Disk usage
ss -tuln # Open ports (modern netstat)SSH and Secure Remote Access
# Connect
ssh ubuntu@192.168.1.100
ssh -i ~/.ssh/key.pem ubuntu@ec2-xxx.amazonaws.com
# SSH config shortcut
# ~/.ssh/config
Host myserver
HostName ec2-xxx.amazonaws.com
User ubuntu
IdentityFile ~/.ssh/key.pem
# Now: ssh myserver
# Copy files
scp file.txt ubuntu@server:/home/ubuntu/
rsync -avz --progress local/ ubuntu@server:/remote/ # Better than scp
# Port forwarding — access remote PostgreSQL locally
ssh -L 5432:localhost:5432 ubuntu@server
# Now connect to localhost:5432 in your DB client
# Generate SSH keypair
ssh-keygen -t ed25519 -C "your@email.com"
cat ~/.ssh/id_ed25519.pub # Copy to server's authorized_keysShell Scripting for DevOps
#!/bin/bash
# deploy.sh — production deployment script
set -euo pipefail # Exit on error, undefined vars, pipe failures
IFS=$'\n\t'
APP_DIR="/app"
BACKUP_DIR="/app/backups"
TIMESTAMP=$(date +%Y%m%d_%H%M%S)
log() { echo "[$(date +'%Y-%m-%d %H:%M:%S')] $*"; }
error() { log "ERROR: $*" >&2; exit 1; }
# Validate prerequisites
[[ -d "$APP_DIR" ]] || error "App directory not found: $APP_DIR"
command -v pm2 >/dev/null 2>&1 || error "pm2 not installed"
# Backup current version
log "Creating backup..."
mkdir -p "$BACKUP_DIR"
tar -czf "$BACKUP_DIR/backup_$TIMESTAMP.tar.gz" \
--exclude='node_modules' --exclude='.git' "$APP_DIR"
# Deploy
log "Pulling latest code..."
cd "$APP_DIR"
git fetch origin main
git reset --hard origin/main
log "Installing dependencies..."
npm ci --production
log "Building application..."
npm run build
log "Restarting service..."
pm2 reload ecosystem.config.js --update-env
log "Deploy complete!"Cron Jobs
crontab -e # Edit user crontab
# Cron format: minute hour day month weekday command
# * = any value, */5 = every 5 units
0 * * * * /app/scripts/hourly.sh >> /var/log/cron.log 2>&1
0 0 * * * /app/scripts/daily-backup.sh >> /var/log/cron.log 2>&1
0 0 * * 1 /app/scripts/weekly-report.sh >> /var/log/cron.log 2>&1
*/5 * * * * /app/scripts/health-check.sh >> /var/log/cron.log 2>&1Useful System Commands
# System information
uname -a # Kernel version
uptime # Load average and uptime
free -h # Memory usage
df -h # Disk usage
iostat -x 1 # Disk I/O stats (needs sysstat)
lscpu # CPU info
# Network
curl -I https://api.myapp.com # Check HTTP headers
dig myapp.com # DNS lookup
ip addr show # Network interfaces
ping -c 4 google.com # Test connectivity
wget -O /tmp/file.zip https://... # Download file
# System logs
journalctl -u nginx --since "1 hour ago"
journalctl -f # Follow all system logs
tail -f /var/log/nginx/error.logCommon Mistakes
- Running as root in production — always use a dedicated system user with only the permissions needed
- No
set -euo pipefailin scripts — without it, scripts silently continue after errors and leave systems in broken states - Port 22 open to the world — restrict SSH access to specific IPs or use a bastion host; better yet, use AWS SSM Session Manager
- Cron output not logged — always redirect stdout and stderr to a log file so you know if cron jobs fail
- Not verifying backups — a backup that has never been tested is not a backup; restore it to a test environment monthly
Best Practices
- Use
rsyncinstead ofscpfor syncing directories — it is incremental, resumable, and supports--dry-run - Store SSH keys as ed25519 (not RSA) — shorter, faster, and considered more secure
- Use
systemctlandjournalctlfor services rather than manual startup scripts on Ubuntu/Debian - Rotate logs with
logrotateto prevent log files from filling disks on long-running servers - Create deployment scripts with proper error handling and always test them against staging first
Key Takeaways
set -euo pipefailat the top of every Bash script makes it safe — it exits on error, undefined variables, and pipe failures- File permissions use the octal notation: 755 means owner rwx, group and others r-x; 644 means owner rw, others r
- SSH config files at
~/.ssh/configlet you alias complex SSH commands into simple hostnames find . -name "*.log" -newer /tmp/markerfinds files modified since a reference point — useful for debugging recent changeslsof -i :3000shows exactly which process is binding to a port — essential when a port conflict prevents startup- Cron expressions follow
minute hour day month weekday;*/5 * * * *runs every 5 minutes rsync -avz --delete local/ remote/syncs directories incrementally and removes files deleted locally — safer thanscp- Always use
kill(SIGTERM) beforekill -9(SIGKILL) to allow graceful shutdown and in-flight request completion
Advertisement