Files
dbbackup/prepare_system.sh
Alexander Renz d835bef8d4 fix(prepare_system): Smart swap handling - check existing swap first
- If already have 4GB+ swap, skip creation
- Only add additional swap if needed
- Target: 8GB total swap
- Shows current vs new swap size
2026-01-23 08:33:44 +01:00

295 lines
9.5 KiB
Bash
Executable File
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/bin/bash
#
# SYSTEM PREPARATION FOR LARGE DATABASE RESTORES
# ===============================================
# Run as: root
#
# This script handles system-level preparation:
# - Swap creation
# - OOM killer protection
# - Kernel tuning
#
# Usage:
# sudo ./prepare_system.sh # Run diagnostics
# sudo ./prepare_system.sh --fix # Apply all fixes
# sudo ./prepare_system.sh --swap # Create swap only
#
set -euo pipefail
VERSION="1.0.0"
# Colors
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
CYAN='\033[0;36m'
NC='\033[0m'
log_info() { echo -e "${BLUE}${NC} $1"; }
log_ok() { echo -e "${GREEN}${NC} $1"; }
log_warn() { echo -e "${YELLOW}${NC} $1"; }
log_error() { echo -e "${RED}${NC} $1"; }
#==============================================================================
# CHECK ROOT
#==============================================================================
check_root() {
if [ "$EUID" -ne 0 ]; then
log_error "This script must be run as root"
echo " Run: sudo $0"
exit 1
fi
}
#==============================================================================
# DIAGNOSE
#==============================================================================
diagnose() {
echo
echo "╔══════════════════════════════════════════════════════════════════╗"
echo "║ SYSTEM DIAGNOSIS FOR LARGE RESTORES ║"
echo "╚══════════════════════════════════════════════════════════════════╝"
echo
# Memory
echo -e "${CYAN}━━━ MEMORY ━━━${NC}"
free -h
echo
# Swap
echo -e "${CYAN}━━━ SWAP ━━━${NC}"
swapon --show 2>/dev/null || echo " No swap configured!"
echo
# Disk
echo -e "${CYAN}━━━ DISK SPACE ━━━${NC}"
df -h / /var/lib/pgsql 2>/dev/null || df -h /
echo
# OOM
echo -e "${CYAN}━━━ RECENT OOM KILLS ━━━${NC}"
dmesg 2>/dev/null | grep -i "out of memory\|oom\|killed process" | tail -5 || echo " None found"
echo
# PostgreSQL OOM protection
echo -e "${CYAN}━━━ POSTGRESQL OOM PROTECTION ━━━${NC}"
local pg_pid
pg_pid=$(pgrep -x postgres 2>/dev/null | head -1 || echo "")
if [ -n "$pg_pid" ] && [ -f "/proc/$pg_pid/oom_score_adj" ]; then
local score=$(cat "/proc/$pg_pid/oom_score_adj")
if [ "$score" = "-1000" ]; then
log_ok "PostgreSQL protected (oom_score_adj = -1000)"
else
log_warn "PostgreSQL NOT protected (oom_score_adj = $score)"
fi
else
log_warn "Cannot check PostgreSQL OOM status"
fi
echo
# Summary
echo -e "${CYAN}━━━ RECOMMENDATIONS ━━━${NC}"
local swap_gb=$(free -g | awk '/^Swap:/ {print $2}')
local avail_gb=$(df -BG / | tail -1 | awk '{print $4}' | tr -d 'G')
if [ "${swap_gb:-0}" -lt 4 ]; then
log_warn "Create swap: sudo $0 --swap"
fi
if [ -n "$pg_pid" ]; then
local score=$(cat "/proc/$pg_pid/oom_score_adj" 2>/dev/null || echo "0")
if [ "$score" != "-1000" ]; then
log_warn "Enable OOM protection: sudo $0 --oom-protect"
fi
fi
echo
echo "To apply all fixes: sudo $0 --fix"
echo
}
#==============================================================================
# CREATE SWAP
#==============================================================================
create_swap() {
local SWAP_FILE="/swapfile_dbbackup"
echo -e "${CYAN}━━━ SWAP CHECK ━━━${NC}"
# Check existing swap
local current_swap_gb=$(free -g | awk '/^Swap:/ {print $2}')
current_swap_gb=${current_swap_gb:-0}
echo " Current swap: ${current_swap_gb}GB"
swapon --show 2>/dev/null || true
echo
# If already have 4GB+ swap, we're good
if [ "$current_swap_gb" -ge 4 ]; then
log_ok "Sufficient swap already configured (${current_swap_gb}GB)"
return 0
fi
# Check if our swap file already exists
if [ -f "$SWAP_FILE" ]; then
if swapon --show | grep -q "$SWAP_FILE"; then
log_ok "Our swap file already active: $SWAP_FILE"
return 0
else
# File exists but not active - activate it
log_info "Activating existing swap file..."
swapon "$SWAP_FILE" 2>/dev/null && log_ok "Swap activated" && return 0
fi
fi
# Need to create swap
local avail_gb=$(df -BG / | tail -1 | awk '{print $4}' | tr -d 'G')
# Calculate how much MORE swap we need (target: 8GB total)
local target_swap=8
local need_swap=$((target_swap - current_swap_gb))
if [ "$need_swap" -le 0 ]; then
log_ok "Swap is sufficient"
return 0
fi
# Auto-detect size based on available disk AND what we need
local size
if [ "$avail_gb" -ge 40 ] && [ "$need_swap" -ge 16 ]; then
size="32G"
elif [ "$avail_gb" -ge 20 ] && [ "$need_swap" -ge 8 ]; then
size="16G"
elif [ "$avail_gb" -ge 12 ] && [ "$need_swap" -ge 4 ]; then
size="8G"
elif [ "$avail_gb" -ge 6 ]; then
size="4G"
elif [ "$avail_gb" -ge 4 ]; then
size="3G"
elif [ "$avail_gb" -ge 3 ]; then
size="2G"
elif [ "$avail_gb" -ge 2 ]; then
size="1G"
else
log_error "Not enough disk space (only ${avail_gb}GB available)"
return 1
fi
log_info "Creating additional swap: $size (current: ${current_swap_gb}GB, disk: ${avail_gb}GB)"
echo " Creating ${size} swap file..."
if command -v fallocate &>/dev/null; then
fallocate -l "$size" "$SWAP_FILE"
else
local size_mb=$((${size//[!0-9]/} * 1024))
dd if=/dev/zero of="$SWAP_FILE" bs=1M count="$size_mb" status=progress
fi
chmod 600 "$SWAP_FILE"
mkswap "$SWAP_FILE"
swapon "$SWAP_FILE"
# Persist
if ! grep -q "$SWAP_FILE" /etc/fstab 2>/dev/null; then
echo "$SWAP_FILE none swap sw 0 0" >> /etc/fstab
log_ok "Added to /etc/fstab"
fi
# Show result
local new_swap_gb=$(free -g | awk '/^Swap:/ {print $2}')
log_ok "Swap now: ${new_swap_gb}GB (was ${current_swap_gb}GB)"
swapon --show
}
#==============================================================================
# OOM PROTECTION
#==============================================================================
enable_oom_protection() {
echo -e "${CYAN}━━━ ENABLING OOM PROTECTION ━━━${NC}"
# Protect PostgreSQL
local pg_pids=$(pgrep -x postgres 2>/dev/null || echo "")
if [ -z "$pg_pids" ]; then
log_warn "PostgreSQL not running"
else
for pid in $pg_pids; do
if [ -f "/proc/$pid/oom_score_adj" ]; then
echo -1000 > "/proc/$pid/oom_score_adj" 2>/dev/null || true
fi
done
log_ok "PostgreSQL processes protected"
fi
# Kernel tuning
sysctl -w vm.overcommit_memory=2 2>/dev/null && log_ok "vm.overcommit_memory = 2"
sysctl -w vm.overcommit_ratio=90 2>/dev/null && log_ok "vm.overcommit_ratio = 90"
# Persist
if ! grep -q "vm.overcommit_memory" /etc/sysctl.conf 2>/dev/null; then
echo "vm.overcommit_memory = 2" >> /etc/sysctl.conf
echo "vm.overcommit_ratio = 90" >> /etc/sysctl.conf
log_ok "Settings persisted to /etc/sysctl.conf"
fi
}
#==============================================================================
# APPLY ALL FIXES
#==============================================================================
apply_all() {
echo
echo "╔══════════════════════════════════════════════════════════════════╗"
echo "║ APPLYING SYSTEM FIXES ║"
echo "╚══════════════════════════════════════════════════════════════════╝"
echo
create_swap
echo
enable_oom_protection
echo
log_ok "System preparation complete!"
echo
echo " Next: Run PostgreSQL tuning as postgres user:"
echo " su - postgres -c './prepare_postgres.sh --fix'"
echo
}
#==============================================================================
# HELP
#==============================================================================
show_help() {
echo "SYSTEM PREPARATION v$VERSION"
echo
echo "Usage: sudo $0 [OPTION]"
echo
echo "Options:"
echo " (none) Run diagnostics"
echo " --fix Apply all fixes"
echo " --swap Create swap file only"
echo " --oom-protect Enable OOM protection only"
echo " --help Show this help"
echo
}
#==============================================================================
# MAIN
#==============================================================================
main() {
check_root
case "${1:-}" in
--help|-h) show_help ;;
--fix) apply_all ;;
--swap) create_swap ;;
--oom-protect) enable_oom_protection ;;
"") diagnose ;;
*) log_error "Unknown option: $1"; show_help; exit 1 ;;
esac
}
main "$@"