Linux Commands Guide 2026 — Server Administration and Shell Scripting for Developers

Sanjeev SharmaSanjeev Sharma
6 min read

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 matches

File 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_keys

Shell 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>&1

Useful 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.log

Common Mistakes

  • Running as root in production — always use a dedicated system user with only the permissions needed
  • No set -euo pipefail in 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 rsync instead of scp for syncing directories — it is incremental, resumable, and supports --dry-run
  • Store SSH keys as ed25519 (not RSA) — shorter, faster, and considered more secure
  • Use systemctl and journalctl for services rather than manual startup scripts on Ubuntu/Debian
  • Rotate logs with logrotate to 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 pipefail at 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/config let you alias complex SSH commands into simple hostnames
  • find . -name "*.log" -newer /tmp/marker finds files modified since a reference point — useful for debugging recent changes
  • lsof -i :3000 shows 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 than scp
  • Always use kill (SIGTERM) before kill -9 (SIGKILL) to allow graceful shutdown and in-flight request completion

Advertisement

Sanjeev Sharma

Written by

Sanjeev Sharma

Full Stack Engineer · E-mopro

Related reading