Major changes: - Added Proxmox detection with interactive mode selection - Mode 1: Proxmox Host (hypervisor-optimized) - Different kernel parameters (swappiness=10, BBR, FQ) - Minimal tmpfs (2GB APT cache only) - No zram (VMs need direct RAM) - No desktop app configuration - Mode 2: Desktop (original behavior with warnings) - Mode 3: Abort (recommends running in VMs) Technical implementation: - check_proxmox() now offers mode selection - analyze_and_prompt() branches on PROXMOX_MODE - tune_kernel() handles both desktop and proxmox profiles - setup_tmpfs() handles minimal proxmox tmpfs - Updated PROXMOX_COMPATIBILITY.md with new behavior Result: One unified script for both desktop and Proxmox use cases
1505 lines
58 KiB
Bash
Executable File
1505 lines
58 KiB
Bash
Executable File
#!/bin/bash
|
||
# Working Interactive System Optimizer
|
||
|
||
set -euo pipefail
|
||
|
||
# Colors
|
||
RED='\033[0;31m'
|
||
GREEN='\033[0;32m'
|
||
YELLOW='\033[1;33m'
|
||
BLUE='\033[0;34m'
|
||
NC='\033[0m'
|
||
|
||
# Configuration
|
||
BACKUP_DIR="/var/lib/system-tuning/backups"
|
||
LOG_FILE="/var/log/system-optimization.log"
|
||
|
||
log() {
|
||
echo -e "${BLUE}[INFO]${NC} $1"
|
||
[[ -w "$(dirname "$LOG_FILE")" ]] && echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1" >> "$LOG_FILE"
|
||
}
|
||
|
||
success() {
|
||
echo -e "${GREEN}[SUCCESS]${NC} $1"
|
||
[[ -w "$(dirname "$LOG_FILE")" ]] && echo "[$(date '+%Y-%m-%d %H:%M:%S')] SUCCESS: $1" >> "$LOG_FILE"
|
||
}
|
||
|
||
warn() {
|
||
echo -e "${YELLOW}[WARNING]${NC} $1"
|
||
[[ -w "$(dirname "$LOG_FILE")" ]] && echo "[$(date '+%Y-%m-%d %H:%M:%S')] WARNING: $1" >> "$LOG_FILE"
|
||
}
|
||
|
||
error() {
|
||
echo -e "${RED}[ERROR]${NC} $1"
|
||
[[ -w "$(dirname "$LOG_FILE")" ]] && echo "[$(date '+%Y-%m-%d %H:%M:%S')] ERROR: $1" >> "$LOG_FILE"
|
||
}
|
||
|
||
check_root() {
|
||
if [[ $EUID -ne 0 ]]; then
|
||
error "This script must be run as root"
|
||
echo "Usage: sudo $0"
|
||
exit 1
|
||
fi
|
||
}
|
||
|
||
check_proxmox() {
|
||
# Detect if running on Proxmox host
|
||
if [[ -f /etc/pve/.version ]] || [[ -d /etc/pve ]] || pveversion &>/dev/null; then
|
||
IS_PROXMOX_HOST=true
|
||
warn "⚠️ Proxmox VE host detected!"
|
||
echo ""
|
||
|
||
# Get VM/CT count
|
||
local vm_count=$(qm list 2>/dev/null | tail -n +2 | wc -l || echo "0")
|
||
local ct_count=$(pct list 2>/dev/null | tail -n +2 | wc -l || echo "0")
|
||
|
||
echo "🖥️ System: Proxmox VE (${vm_count} VMs, ${ct_count} containers)"
|
||
echo ""
|
||
echo "This tool has TWO modes:"
|
||
echo ""
|
||
echo " 1️⃣ Proxmox Host Mode (Hypervisor Optimization)"
|
||
echo " • Optimized kernel params for VM workloads"
|
||
echo " • Minimal RAM allocation (5-10% max)"
|
||
echo " • CPU performance governor"
|
||
echo " • ZFS ARC limiting (if applicable)"
|
||
echo " • No desktop app configuration"
|
||
echo ""
|
||
echo " 2️⃣ Desktop Mode (NOT recommended for host)"
|
||
echo " • Heavy RAM usage (zram + tmpfs = 40-50%)"
|
||
echo " • Desktop-focused optimizations"
|
||
echo " • Will reduce memory available for VMs"
|
||
echo ""
|
||
echo " 3️⃣ Abort (Recommended: Run inside your desktop VMs)"
|
||
echo ""
|
||
read -p "Choose mode (1=Proxmox/2=Desktop/3=Abort) [1]: " -n 1 -r
|
||
echo
|
||
echo ""
|
||
|
||
case "$REPLY" in
|
||
1|"")
|
||
log "Running in Proxmox Host Mode"
|
||
PROXMOX_MODE=true
|
||
;;
|
||
2)
|
||
warn "Running in Desktop Mode on Proxmox host - this may affect VMs!"
|
||
read -p "Are you sure? This is NOT recommended. (yes/N): " confirm
|
||
if [[ "$confirm" != "yes" ]]; then
|
||
log "Aborted by user"
|
||
exit 0
|
||
fi
|
||
PROXMOX_MODE=false
|
||
warn "Proceeding with desktop optimizations - monitor VM performance!"
|
||
echo ""
|
||
;;
|
||
3|*)
|
||
log "Aborted by user. Consider running inside VMs instead."
|
||
echo ""
|
||
echo "💡 To optimize your desktop VMs:"
|
||
echo " 1. SSH into your VM"
|
||
echo " 2. Run: sudo ./one-button-optimizer.sh"
|
||
echo " 3. Enjoy full desktop optimizations safely!"
|
||
exit 0
|
||
;;
|
||
esac
|
||
else
|
||
IS_PROXMOX_HOST=false
|
||
PROXMOX_MODE=false
|
||
fi
|
||
}
|
||
|
||
analyze_and_prompt() {
|
||
log "Analyzing current system optimizations..."
|
||
|
||
# Get system info
|
||
local ram_gb=$(free -g | awk '/^Mem:|^Speicher:/{print $2}')
|
||
local cpu_cores=$(nproc)
|
||
|
||
echo ""
|
||
echo "📊 System Information:"
|
||
echo " 💾 RAM: ${ram_gb}GB"
|
||
echo " 🖥️ CPU: ${cpu_cores} cores"
|
||
if [[ "${PROXMOX_MODE:-false}" == "true" ]]; then
|
||
echo " 🖥️ Mode: Proxmox Host Optimization"
|
||
fi
|
||
echo ""
|
||
|
||
# Check and prompt for each optimization
|
||
local needs_changes=false
|
||
|
||
# === ZRAM CHECK ===
|
||
if [[ "${PROXMOX_MODE:-false}" == "true" ]]; then
|
||
# Proxmox mode: Skip zram entirely
|
||
echo "🗜️ zram Compressed Swap Analysis:"
|
||
echo " ⏭️ Skipped (not recommended for Proxmox hosts)"
|
||
echo " 💡 Reason: VMs need direct RAM access for performance"
|
||
SETUP_ZRAM=false
|
||
else
|
||
# Desktop mode: Original zram logic
|
||
echo "🗜️ zram Compressed Swap Analysis:"
|
||
local optimal_size=$((ram_gb / 2))
|
||
[[ $optimal_size -lt 2 ]] && optimal_size=2
|
||
|
||
if [[ -e /dev/zram0 ]] && swapon --show | grep -q zram0; then
|
||
local zram_size=$(swapon --show | grep zram0 | awk '{print $3}')
|
||
local zram_gb=$(echo "$zram_size" | sed 's/[^0-9.]//g' | cut -d. -f1)
|
||
|
||
echo " 📈 Current: $zram_size"
|
||
echo " 📊 Optimal: ${optimal_size}GB"
|
||
|
||
if [[ $zram_gb -gt $((optimal_size + 2)) ]] || [[ $zram_gb -lt $((optimal_size - 1)) ]]; then
|
||
echo " ⚠️ Current size is suboptimal"
|
||
needs_changes=true
|
||
read -p " Would you like to reconfigure zram to ${optimal_size}GB? (y/N): " -n 1 -r
|
||
echo
|
||
if [[ $REPLY =~ ^[Yy]$ ]]; then
|
||
SETUP_ZRAM=true
|
||
else
|
||
SETUP_ZRAM=false
|
||
fi
|
||
else
|
||
echo " ✅ Size is optimal"
|
||
SETUP_ZRAM=false
|
||
fi
|
||
else
|
||
echo " ❌ Not configured"
|
||
echo " 📊 Recommended: ${optimal_size}GB"
|
||
needs_changes=true
|
||
read -p " Would you like to configure zram? (y/N): " -n 1 -r
|
||
echo
|
||
if [[ $REPLY =~ ^[Yy]$ ]]; then
|
||
SETUP_ZRAM=true
|
||
else
|
||
SETUP_ZRAM=false
|
||
fi
|
||
fi
|
||
fi
|
||
echo ""
|
||
|
||
# === TMPFS CHECK ===
|
||
echo "💾 tmpfs Cache System Analysis:"
|
||
|
||
if [[ "${PROXMOX_MODE:-false}" == "true" ]]; then
|
||
# Proxmox mode: Minimal tmpfs for APT cache only
|
||
echo " 📦 Proxmox Host Mode: Minimal tmpfs allocation"
|
||
local apt_cache_size=$(du -sm /var/cache/apt/archives 2>/dev/null | awk '{print $1}' || echo "0")
|
||
echo " 📊 Current APT cache: ${apt_cache_size}MB"
|
||
echo " 💡 Recommended: 2GB tmpfs for package cache (minimal RAM impact)"
|
||
echo ""
|
||
read -p " Configure minimal tmpfs for APT cache? (y/N): " -n 1 -r
|
||
echo
|
||
if [[ $REPLY =~ ^[Yy]$ ]]; then
|
||
SETUP_TMPFS=true
|
||
TMPFS_PROFILE="proxmox"
|
||
else
|
||
SETUP_TMPFS=false
|
||
fi
|
||
else
|
||
# Desktop mode: Original tmpfs logic
|
||
local tmpfs_count=$(mount | grep "tmpfs.*tmpfs-cache" | wc -l)
|
||
if [[ $tmpfs_count -gt 0 ]]; then
|
||
echo " ✅ Well configured ($tmpfs_count active mounts)"
|
||
echo " 📁 Current mounted caches:"
|
||
mount | grep "tmpfs.*tmpfs-cache" | head -3 | awk '{print " " $3 " (" $6 ")"}' | tr -d '()'
|
||
[[ $tmpfs_count -gt 3 ]] && echo " ... and $((tmpfs_count - 3)) more"
|
||
echo ""
|
||
echo " 🔍 Scanning for additional optimization opportunities..."
|
||
else
|
||
echo " ❌ Not configured"
|
||
echo " 🔍 Scanning system for cache directories..."
|
||
fi
|
||
|
||
# === OVERLAY FILESYSTEM CHECK ===
|
||
echo "🗂️ Overlay Filesystem Analysis:"
|
||
local overlay_count=$(mount -t overlay | wc -l)
|
||
if [[ $overlay_count -gt 0 ]]; then
|
||
echo " ⚠️ Found $overlay_count overlay mounts (deprecated for desktop use)"
|
||
echo " 📁 Current overlay mounts:"
|
||
mount -t overlay | head -3 | awk '{print " " $3 " (overlay)"}'
|
||
[[ $overlay_count -gt 3 ]] && echo " ... and $((overlay_count - 3)) more"
|
||
echo ""
|
||
echo " 💡 Overlays are complex and rarely needed on desktop systems."
|
||
echo " 💡 Consider removing them unless specifically required."
|
||
needs_changes=true
|
||
read -p " Would you like to remove overlay mounts? (y/N): " -n 1 -r
|
||
echo
|
||
if [[ $REPLY =~ ^[Yy]$ ]]; then
|
||
REMOVE_OVERLAYS=true
|
||
else
|
||
REMOVE_OVERLAYS=false
|
||
fi
|
||
else
|
||
echo " ✅ No overlay mounts found (good - not needed for desktop)"
|
||
REMOVE_OVERLAYS=false
|
||
fi
|
||
echo ""
|
||
|
||
# Always analyze potential tmpfs candidates (even if already configured)
|
||
local cache_analysis=""
|
||
local total_cache_size=0
|
||
local additional_opportunities=""
|
||
|
||
# Check browser caches
|
||
for user_home in /home/*; do
|
||
if [[ -d "$user_home" ]]; then
|
||
local browser_cache_size=0
|
||
for cache_dir in "$user_home/.cache/google-chrome" "$user_home/.cache/firefox" "$user_home/.cache/chromium" "$user_home/.cache/microsoft-edge" "$user_home/.cache/brave" "$user_home/.cache/opera"; do
|
||
if [[ -d "$cache_dir" ]]; then
|
||
local size=$(du -sm "$cache_dir" 2>/dev/null | cut -f1 || echo 0)
|
||
browser_cache_size=$((browser_cache_size + size))
|
||
fi
|
||
done
|
||
if [[ $browser_cache_size -gt 0 ]]; then
|
||
cache_analysis="${cache_analysis} Browser caches: ${browser_cache_size}MB\n"
|
||
total_cache_size=$((total_cache_size + browser_cache_size))
|
||
fi
|
||
fi
|
||
done
|
||
|
||
# Check development tool caches
|
||
for user_home in /home/*; do
|
||
if [[ -d "$user_home" ]]; then
|
||
local dev_cache_size=0
|
||
|
||
# Node.js/npm cache
|
||
if [[ -d "$user_home/.npm" ]]; then
|
||
local npm_size=$(du -sm "$user_home/.npm" 2>/dev/null | cut -f1 || echo 0)
|
||
dev_cache_size=$((dev_cache_size + npm_size))
|
||
fi
|
||
|
||
# Python pip cache
|
||
if [[ -d "$user_home/.cache/pip" ]]; then
|
||
local pip_size=$(du -sm "$user_home/.cache/pip" 2>/dev/null | cut -f1 || echo 0)
|
||
dev_cache_size=$((dev_cache_size + pip_size))
|
||
fi
|
||
|
||
# VS Code cache
|
||
if [[ -d "$user_home/.vscode" ]]; then
|
||
local vscode_size=$(du -sm "$user_home/.vscode" 2>/dev/null | cut -f1 || echo 0)
|
||
dev_cache_size=$((dev_cache_size + vscode_size))
|
||
fi
|
||
|
||
if [[ $dev_cache_size -gt 0 ]]; then
|
||
cache_analysis="${cache_analysis} Development caches: ${dev_cache_size}MB\n"
|
||
total_cache_size=$((total_cache_size + dev_cache_size))
|
||
fi
|
||
fi
|
||
done
|
||
|
||
# Check KDE/Plasma caches if detected
|
||
if [[ "$XDG_CURRENT_DESKTOP" == *"KDE"* ]] || [[ "$DESKTOP_SESSION" == *"plasma"* ]]; then
|
||
for user_home in /home/*; do
|
||
if [[ -d "$user_home" ]]; then
|
||
local kde_cache_size=0
|
||
for kde_dir in ".cache/baloo" ".cache/plasma" ".cache/krunner" ".cache/thumbnails" ".cache/mesa_shader_cache"; do
|
||
if [[ -d "$user_home/$kde_dir" ]]; then
|
||
local size=$(du -sm "$user_home/$kde_dir" 2>/dev/null | cut -f1 || echo 0)
|
||
kde_cache_size=$((kde_cache_size + size))
|
||
fi
|
||
done
|
||
if [[ $kde_cache_size -gt 0 ]]; then
|
||
cache_analysis="${cache_analysis} KDE/Plasma caches: ${kde_cache_size}MB\n"
|
||
total_cache_size=$((total_cache_size + kde_cache_size))
|
||
fi
|
||
fi
|
||
done
|
||
fi
|
||
|
||
# Look for additional optimization opportunities
|
||
for user_home in /home/*; do
|
||
if [[ -d "$user_home" ]]; then
|
||
# Check for gaming caches
|
||
if [[ -d "$user_home/.steam" ]]; then
|
||
local steam_cache_size=$(du -sm "$user_home/.steam/steam/appcache" 2>/dev/null | cut -f1 || echo 0)
|
||
if [[ $steam_cache_size -gt 50 ]]; then
|
||
additional_opportunities="${additional_opportunities} Steam cache: ${steam_cache_size}MB (gaming profile recommended)\n"
|
||
fi
|
||
fi
|
||
|
||
# Check for shader caches (important for gaming/graphics)
|
||
if [[ -d "$user_home/.local/share/Steam/steamapps/shadercache" ]]; then
|
||
local shader_cache_size=$(du -sm "$user_home/.local/share/Steam/steamapps/shadercache" 2>/dev/null | cut -f1 || echo 0)
|
||
if [[ $shader_cache_size -gt 100 ]]; then
|
||
additional_opportunities="${additional_opportunities} GPU shader cache: ${shader_cache_size}MB (CRITICAL for gaming performance)\n"
|
||
fi
|
||
fi
|
||
|
||
# Check for container development caches
|
||
if [[ -d "$user_home/.docker" ]]; then
|
||
local docker_cache_size=$(du -sm "$user_home/.docker" 2>/dev/null | cut -f1 || echo 0)
|
||
if [[ $docker_cache_size -gt 100 ]]; then
|
||
additional_opportunities="${additional_opportunities} Docker cache: ${docker_cache_size}MB (development profile)\n"
|
||
fi
|
||
fi
|
||
|
||
# Check for large build caches
|
||
if [[ -d "$user_home/.gradle/caches" ]]; then
|
||
local gradle_cache_size=$(du -sm "$user_home/.gradle/caches" 2>/dev/null | cut -f1 || echo 0)
|
||
if [[ $gradle_cache_size -gt 200 ]]; then
|
||
additional_opportunities="${additional_opportunities} Gradle build cache: ${gradle_cache_size}MB (development profile)\n"
|
||
fi
|
||
fi
|
||
fi
|
||
done
|
||
|
||
# Check system-level opportunities
|
||
if [[ -d /var/lib/flatpak ]]; then
|
||
local flatpak_size=$(du -sm /var/lib/flatpak 2>/dev/null | cut -f1 || echo 0)
|
||
if [[ $flatpak_size -gt 1000 ]]; then
|
||
additional_opportunities="${additional_opportunities} Flatpak apps: ${flatpak_size}MB (consider tmpfs for .cache)\n"
|
||
fi
|
||
fi
|
||
|
||
# Check package cache
|
||
if [[ -d /var/cache/apt ]]; then
|
||
local apt_cache_size=$(du -sm /var/cache/apt 2>/dev/null | cut -f1 || echo 0)
|
||
if [[ $apt_cache_size -gt 0 ]]; then
|
||
cache_analysis="${cache_analysis} Package cache: ${apt_cache_size}MB\n"
|
||
total_cache_size=$((total_cache_size + apt_cache_size))
|
||
fi
|
||
fi
|
||
|
||
# Check temp directories
|
||
local tmp_size=$(du -sm /tmp 2>/dev/null | cut -f1 || echo 0)
|
||
if [[ $tmp_size -gt 100 ]]; then
|
||
cache_analysis="${cache_analysis} Temp files: ${tmp_size}MB\n"
|
||
fi
|
||
|
||
if [[ $total_cache_size -gt 0 ]]; then
|
||
echo " 📊 Found cacheable data:"
|
||
echo -e "$cache_analysis"
|
||
echo " 💡 Total cache size: ${total_cache_size}MB"
|
||
|
||
# Recommend profile based on cache size and RAM
|
||
local recommended_profile="medium"
|
||
if [[ $ram_gb -ge 16 ]] && [[ $total_cache_size -gt 2000 ]]; then
|
||
recommended_profile="large"
|
||
echo " 📈 Recommended: Large profile (${ram_gb}GB RAM, ${total_cache_size}MB cache)"
|
||
elif [[ $ram_gb -le 8 ]] || [[ $total_cache_size -lt 1000 ]]; then
|
||
recommended_profile="small"
|
||
echo " 📈 Recommended: Small profile (${ram_gb}GB RAM, ${total_cache_size}MB cache)"
|
||
else
|
||
echo " 📈 Recommended: Medium profile (${ram_gb}GB RAM, ${total_cache_size}MB cache)"
|
||
fi
|
||
else
|
||
echo " 📊 No significant cache data found"
|
||
echo " 💡 tmpfs can still improve performance for future cache usage"
|
||
fi
|
||
|
||
# Check for additional opportunities regardless of current setup
|
||
if [[ -n "$additional_opportunities" ]]; then
|
||
echo ""
|
||
echo " 🎯 Additional Optimization Opportunities:"
|
||
echo -e "$additional_opportunities"
|
||
fi
|
||
|
||
# Determine if changes are needed
|
||
if [[ $tmpfs_count -gt 0 ]]; then
|
||
# Already configured - check if improvements are possible
|
||
local current_mounts=$(mount | grep "tmpfs.*tmpfs-cache" | wc -l)
|
||
local recommended_mounts=4
|
||
|
||
# Check if KDE is detected and we don't have a KDE-specific mount
|
||
if [[ "$XDG_CURRENT_DESKTOP" == *"KDE"* ]] || [[ "$DESKTOP_SESSION" == *"plasma"* ]]; then
|
||
if ! mount | grep -q "tmpfs-cache/kde"; then
|
||
recommended_mounts=5
|
||
echo " 💡 KDE environment detected - could add dedicated KDE cache mount"
|
||
fi
|
||
fi
|
||
|
||
# Check if development mount exists
|
||
if ! mount | grep -q "tmpfs-cache/development" && [[ $total_cache_size -gt 500 ]]; then
|
||
echo " 💡 Development caches detected - could add dedicated development mount"
|
||
recommended_mounts=$((recommended_mounts + 1))
|
||
fi
|
||
|
||
if [[ $current_mounts -lt $recommended_mounts ]] || [[ $total_cache_size -gt 3000 ]]; then
|
||
echo " ⚠️ Current setup could be enhanced"
|
||
needs_changes=true
|
||
read -p " Would you like to enhance your tmpfs setup? (y/N): " -n 1 -r
|
||
echo
|
||
if [[ $REPLY =~ ^[Yy]$ ]]; then
|
||
SETUP_TMPFS=true
|
||
else
|
||
SETUP_TMPFS=false
|
||
fi
|
||
else
|
||
echo " ✅ Current tmpfs setup is optimal for detected cache usage"
|
||
SETUP_TMPFS=false
|
||
fi
|
||
else
|
||
# Not configured at all
|
||
needs_changes=true
|
||
read -p " Would you like to set up tmpfs caches? (y/N): " -n 1 -r
|
||
echo
|
||
if [[ $REPLY =~ ^[Yy]$ ]]; then
|
||
SETUP_TMPFS=true
|
||
else
|
||
SETUP_TMPFS=false
|
||
fi
|
||
fi
|
||
fi # End desktop mode tmpfs check
|
||
echo ""
|
||
|
||
# === KERNEL PARAMS CHECK ===
|
||
echo "⚙️ Kernel Parameters Analysis:"
|
||
|
||
if [[ "${PROXMOX_MODE:-false}" == "true" ]]; then
|
||
# Proxmox mode: Different kernel parameters
|
||
local swappiness=$(sysctl -n vm.swappiness 2>/dev/null || echo "60")
|
||
local dirty_ratio=$(sysctl -n vm.dirty_ratio 2>/dev/null || echo "20")
|
||
local qdisc=$(sysctl -n net.core.default_qdisc 2>/dev/null || echo "pfifo_fast")
|
||
local tcp_congestion=$(sysctl -n net.ipv4.tcp_congestion_control 2>/dev/null || echo "cubic")
|
||
|
||
echo " 📊 Current: swappiness=$swappiness, dirty_ratio=$dirty_ratio"
|
||
echo " 📊 Network: qdisc=$qdisc, tcp_congestion=$tcp_congestion"
|
||
echo " 📊 Proxmox Recommended: swappiness=10, dirty_ratio=10, qdisc=fq, tcp_congestion=bbr"
|
||
echo ""
|
||
|
||
if [[ "$swappiness" != "10" ]] || [[ "$dirty_ratio" != "10" ]] || [[ "$qdisc" != "fq" ]]; then
|
||
echo " ⚠️ Parameters could be optimized for Proxmox workload"
|
||
read -p " Apply Proxmox-optimized kernel parameters? (y/N): " -n 1 -r
|
||
echo
|
||
if [[ $REPLY =~ ^[Yy]$ ]]; then
|
||
TUNE_KERNEL=true
|
||
KERNEL_PROFILE="proxmox"
|
||
else
|
||
TUNE_KERNEL=false
|
||
fi
|
||
else
|
||
echo " ✅ Parameters are optimal for Proxmox"
|
||
TUNE_KERNEL=false
|
||
fi
|
||
else
|
||
# Desktop mode: Original kernel parameter logic
|
||
if [[ -f /etc/sysctl.d/99-system-optimization.conf ]]; then
|
||
local swappiness=$(sysctl -n vm.swappiness 2>/dev/null)
|
||
local dirty_ratio=$(sysctl -n vm.dirty_ratio 2>/dev/null)
|
||
echo " ✅ Configuration exists"
|
||
echo " 📊 Current: swappiness=$swappiness, dirty_ratio=$dirty_ratio"
|
||
|
||
# Check if optimal
|
||
local opt_swap=5
|
||
local opt_dirty=5
|
||
if [[ $ram_gb -ge 16 ]]; then
|
||
opt_swap=1; opt_dirty=3
|
||
elif [[ $ram_gb -le 4 ]]; then
|
||
opt_swap=10; opt_dirty=10
|
||
fi
|
||
|
||
echo " 📊 Optimal: swappiness=$opt_swap, dirty_ratio=$opt_dirty"
|
||
|
||
if [[ "$swappiness" != "$opt_swap" ]] || [[ "$dirty_ratio" != "$opt_dirty" ]]; then
|
||
echo " ⚠️ Parameters could be optimized"
|
||
needs_changes=true
|
||
read -p " Would you like to optimize kernel parameters? (y/N): " -n 1 -r
|
||
echo
|
||
if [[ $REPLY =~ ^[Yy]$ ]]; then
|
||
TUNE_KERNEL=true
|
||
KERNEL_PROFILE="desktop"
|
||
else
|
||
TUNE_KERNEL=false
|
||
fi
|
||
else
|
||
echo " ✅ Parameters are optimal"
|
||
TUNE_KERNEL=false
|
||
fi
|
||
else
|
||
echo " ❌ Not optimized"
|
||
needs_changes=true
|
||
read -p " Would you like to optimize kernel parameters? (y/N): " -n 1 -r
|
||
echo
|
||
if [[ $REPLY =~ ^[Yy]$ ]]; then
|
||
TUNE_KERNEL=true
|
||
KERNEL_PROFILE="desktop"
|
||
else
|
||
TUNE_KERNEL=false
|
||
fi
|
||
fi
|
||
fi # End desktop mode kernel check
|
||
echo ""
|
||
|
||
# === SERVICE CHECK ===
|
||
echo "🔄 Systemd Service Analysis:"
|
||
if systemctl is-enabled system-optimization.service &>/dev/null; then
|
||
echo " ✅ Service is installed and enabled"
|
||
SETUP_SERVICE=false
|
||
else
|
||
echo " ❌ Service not installed"
|
||
needs_changes=true
|
||
read -p " Would you like to install the systemd service? (y/N): " -n 1 -r
|
||
echo
|
||
if [[ $REPLY =~ ^[Yy]$ ]]; then
|
||
SETUP_SERVICE=true
|
||
else
|
||
SETUP_SERVICE=false
|
||
fi
|
||
fi
|
||
echo ""
|
||
|
||
# Summary
|
||
if [[ $needs_changes == false ]]; then
|
||
success "🎉 All optimizations are already in great shape!"
|
||
echo ""
|
||
echo "📋 Current Optimization Details:"
|
||
echo "==============================="
|
||
|
||
# Show detailed zram info
|
||
if [[ -e /dev/zram0 ]] && swapon --show | grep -q zram0; then
|
||
local zram_size=$(swapon --show | grep zram0 | awk '{print $3}')
|
||
local zram_used=$(swapon --show | grep zram0 | awk '{print $4}')
|
||
echo ""
|
||
echo "🗜️ zram Compressed Swap:"
|
||
echo " 💾 Size: $zram_size (currently using: ${zram_used:-0B})"
|
||
echo " ⚡ Purpose: Compressed swap in RAM for better performance"
|
||
echo " 📈 Benefit: ~2-4x compression ratio reduces memory pressure"
|
||
echo " 🔧 Algorithm: $(cat /sys/block/zram0/comp_algorithm 2>/dev/null | grep -o '\[.*\]' | tr -d '[]' || echo 'lz4')"
|
||
fi
|
||
|
||
# Show detailed tmpfs info
|
||
local tmpfs_count=$(mount | grep "tmpfs.*tmpfs-cache" | wc -l)
|
||
if [[ $tmpfs_count -gt 0 ]]; then
|
||
echo ""
|
||
echo "💾 tmpfs Cache System:"
|
||
echo " 📊 Active Mounts: $tmpfs_count cache filesystems in RAM"
|
||
echo ""
|
||
echo " 📁 Mount Details:"
|
||
mount | grep "tmpfs.*tmpfs-cache" | while read -r line; do
|
||
local mount_point=$(echo "$line" | awk '{print $3}')
|
||
local mount_name=$(basename "$mount_point")
|
||
local size_info=$(echo "$line" | grep -o 'size=[^,]*' | cut -d= -f2)
|
||
local df_info=$(df -h "$mount_point" 2>/dev/null | tail -1)
|
||
local used=$(echo "$df_info" | awk '{print $3}')
|
||
local use_percent=$(echo "$df_info" | awk '{print $5}')
|
||
|
||
printf " • %-12s: %8s (%s used, %s)\n" "$mount_name" "$size_info" "$used" "$use_percent"
|
||
|
||
# Explain what each mount is for
|
||
case "$mount_name" in
|
||
"browser")
|
||
echo " 📝 Purpose: Browser caches (Chrome, Firefox, etc.)"
|
||
echo " ⚡ Benefit: Faster page loading, reduced SSD wear"
|
||
;;
|
||
"ide")
|
||
echo " 📝 Purpose: IDE and editor caches (VS Code, JetBrains)"
|
||
echo " ⚡ Benefit: Faster project loading, syntax highlighting"
|
||
;;
|
||
"packages")
|
||
echo " 📝 Purpose: Package manager cache (APT, etc.)"
|
||
echo " ⚡ Benefit: Faster package operations, reduced downloads"
|
||
;;
|
||
"development")
|
||
echo " 📝 Purpose: Development tool caches (npm, pip, Docker)"
|
||
echo " ⚡ Benefit: Faster builds, dependency resolution"
|
||
;;
|
||
"kde")
|
||
echo " 📝 Purpose: KDE/Plasma desktop caches (Baloo, thumbnails)"
|
||
echo " ⚡ Benefit: Faster file indexing, desktop responsiveness"
|
||
;;
|
||
"thumbnails")
|
||
echo " 📝 Purpose: File manager thumbnail cache"
|
||
echo " ⚡ Benefit: Instant thumbnail generation"
|
||
;;
|
||
esac
|
||
echo ""
|
||
done
|
||
|
||
# Calculate total tmpfs allocation
|
||
local total_kb=0
|
||
while read -r line; do
|
||
local size_kb=$(echo "$line" | grep -o 'size=[^,]*' | cut -d= -f2 | sed 's/k$//')
|
||
total_kb=$((total_kb + size_kb))
|
||
done < <(mount | grep "tmpfs.*tmpfs-cache")
|
||
local total_mb=$((total_kb / 1024))
|
||
|
||
# Get RAM info with proper fallback and locale support
|
||
local ram_gb=$(free -g | awk '/^Mem:|^Speicher:/{print $2}')
|
||
local ram_mb=$(free -m | awk '/^Mem:|^Speicher:/{print $2}')
|
||
|
||
# Handle edge cases for RAM detection
|
||
if [[ $ram_gb -eq 0 && $ram_mb -gt 0 ]]; then
|
||
ram_gb=$((ram_mb / 1024))
|
||
[[ $ram_gb -eq 0 ]] && ram_gb=1 # Minimum 1GB for display
|
||
fi
|
||
|
||
# Calculate percentage safely
|
||
local ram_percent=0
|
||
if [[ $ram_gb -gt 0 ]]; then
|
||
ram_percent=$(( (total_mb * 100) / (ram_gb * 1024) ))
|
||
elif [[ $ram_mb -gt 0 ]]; then
|
||
ram_percent=$(( (total_mb * 100) / ram_mb ))
|
||
fi
|
||
|
||
echo " 📊 Total tmpfs allocation: ${total_mb}MB (${ram_percent}% of ${ram_gb}GB RAM)"
|
||
echo " 🚀 Performance gain: Cache operations run at RAM speed (~50-100x faster)"
|
||
echo " 💿 SSD protection: Reduces write cycles by ~60-80% for cached data"
|
||
fi
|
||
|
||
# Show kernel parameter details
|
||
if [[ -f /etc/sysctl.d/99-system-optimization.conf ]]; then
|
||
local swappiness=$(sysctl -n vm.swappiness 2>/dev/null)
|
||
local dirty_ratio=$(sysctl -n vm.dirty_ratio 2>/dev/null)
|
||
local dirty_bg_ratio=$(sysctl -n vm.dirty_background_ratio 2>/dev/null)
|
||
echo ""
|
||
echo "⚙️ Kernel Parameter Optimizations:"
|
||
echo " 🔧 vm.swappiness = $swappiness (how aggressively to use swap)"
|
||
echo " 📝 Purpose: $(if [[ $swappiness -le 5 ]]; then echo "Prefer RAM over swap for better performance"; else echo "Balanced RAM/swap usage"; fi)"
|
||
echo ""
|
||
echo " 🔧 vm.dirty_ratio = $dirty_ratio (% RAM for write cache)"
|
||
echo " 📝 Purpose: Controls when dirty pages are written to disk"
|
||
echo ""
|
||
echo " 🔧 vm.dirty_background_ratio = $dirty_bg_ratio (background write threshold)"
|
||
echo " 📝 Purpose: When background writing starts"
|
||
echo ""
|
||
|
||
# Use the ram_gb variable calculated above, or recalculate if needed
|
||
local ram_display_gb=${ram_gb:-$(free -g | awk '/^Mem:|^Speicher:/{print $2}')}
|
||
if [[ $ram_display_gb -eq 0 ]]; then
|
||
local ram_display_mb=$(free -m | awk '/^Mem:|^Speicher:/{print $2}')
|
||
ram_display_gb=$((ram_display_mb / 1024))
|
||
[[ $ram_display_gb -eq 0 ]] && ram_display_gb=1
|
||
fi
|
||
|
||
echo " ⚡ Combined benefit: Optimized memory management for your ${ram_display_gb}GB system"
|
||
fi
|
||
|
||
# Show service status
|
||
if systemctl is-enabled system-optimization.service &>/dev/null; then
|
||
echo ""
|
||
echo "🔄 Persistence Service:"
|
||
echo " ✅ system-optimization.service enabled"
|
||
echo " 📝 Purpose: Automatically recreates optimizations after reboot"
|
||
echo " 🔧 Restores: zram device, tmpfs mounts, bind mounts"
|
||
fi
|
||
|
||
echo ""
|
||
echo "💡 Quick Reference Commands:"
|
||
echo " ./tmpfs-info.sh # Detailed tmpfs status and configuration"
|
||
echo " ./quick-status-check.sh # Quick system overview"
|
||
echo " df -h /tmp/tmpfs-cache/* # Check tmpfs usage"
|
||
echo " swapon --show # Check zram status"
|
||
echo ""
|
||
|
||
# Check if applications are configured for tmpfs
|
||
local current_user=$(logname 2>/dev/null || echo $SUDO_USER)
|
||
local user_home=$(eval echo ~$current_user)
|
||
|
||
echo "📱 Application Configuration Status:"
|
||
local configured_browsers=0
|
||
local total_browsers=0
|
||
|
||
# Check each browser
|
||
if [[ -d "$user_home/.mozilla/firefox" ]]; then
|
||
total_browsers=$((total_browsers + 1))
|
||
if grep -q "tmpfs-cache" "$user_home/.mozilla/firefox"/*default*/prefs.js 2>/dev/null; then
|
||
echo " ✅ Firefox: Configured"
|
||
configured_browsers=$((configured_browsers + 1))
|
||
else
|
||
echo " ⚠️ Firefox: Not configured"
|
||
fi
|
||
fi
|
||
|
||
if [[ -d "$user_home/.config/BraveSoftware" ]]; then
|
||
total_browsers=$((total_browsers + 1))
|
||
if [[ -f "$user_home/.local/share/applications/brave-browser.desktop" ]] && \
|
||
grep -q "tmpfs-cache" "$user_home/.local/share/applications/brave-browser.desktop" 2>/dev/null; then
|
||
echo " ✅ Brave: Configured"
|
||
configured_browsers=$((configured_browsers + 1))
|
||
else
|
||
echo " ⚠️ Brave: Not configured"
|
||
fi
|
||
fi
|
||
|
||
if [[ -d "$user_home/.config/google-chrome" ]]; then
|
||
total_browsers=$((total_browsers + 1))
|
||
if [[ -f "$user_home/.local/share/applications/google-chrome.desktop" ]] && \
|
||
grep -q "tmpfs-cache" "$user_home/.local/share/applications/google-chrome.desktop" 2>/dev/null; then
|
||
echo " ✅ Chrome: Configured"
|
||
configured_browsers=$((configured_browsers + 1))
|
||
else
|
||
echo " ⚠️ Chrome: Not configured"
|
||
fi
|
||
fi
|
||
|
||
if [[ -d "$user_home/.config/chromium" ]]; then
|
||
total_browsers=$((total_browsers + 1))
|
||
if [[ -f "$user_home/.local/share/applications/chromium-browser.desktop" ]] && \
|
||
grep -q "tmpfs-cache" "$user_home/.local/share/applications/chromium-browser.desktop" 2>/dev/null; then
|
||
echo " ✅ Chromium: Configured"
|
||
configured_browsers=$((configured_browsers + 1))
|
||
else
|
||
echo " ⚠️ Chromium: Not configured"
|
||
fi
|
||
fi
|
||
|
||
# Check dev tools
|
||
local npm_configured=false
|
||
if command -v npm &>/dev/null; then
|
||
local npm_cache=$(sudo -u $current_user npm config get cache 2>/dev/null)
|
||
if [[ "$npm_cache" == *"tmpfs-cache"* ]]; then
|
||
echo " ✅ NPM: Configured"
|
||
npm_configured=true
|
||
else
|
||
echo " ⚠️ NPM: Not configured"
|
||
fi
|
||
fi
|
||
|
||
local pip_configured=false
|
||
if command -v pip3 &>/dev/null || command -v pip &>/dev/null; then
|
||
if [[ -f "$user_home/.config/pip/pip.conf" ]] && \
|
||
grep -q "tmpfs-cache" "$user_home/.config/pip/pip.conf" 2>/dev/null; then
|
||
echo " ✅ Pip: Configured"
|
||
pip_configured=true
|
||
else
|
||
echo " ⚠️ Pip: Not configured"
|
||
fi
|
||
fi
|
||
|
||
echo ""
|
||
if [[ $configured_browsers -lt $total_browsers ]] || [[ $npm_configured == false ]] || [[ $pip_configured == false ]]; then
|
||
read -p " Would you like to configure/reconfigure your applications? (y/N): " -n 1 -r
|
||
echo
|
||
if [[ $REPLY =~ ^[Yy]$ ]]; then
|
||
echo ""
|
||
configure_applications_for_tmpfs
|
||
echo ""
|
||
success "Configuration complete! Restart your applications to use tmpfs caches."
|
||
fi
|
||
else
|
||
echo " ✅ Applications are configured to use tmpfs caches"
|
||
fi
|
||
echo ""
|
||
echo "🎯 Your system is fully optimized for maximum performance!"
|
||
exit 0
|
||
fi
|
||
|
||
# Show what will be done
|
||
local actions=()
|
||
[[ $SETUP_ZRAM == true ]] && actions+=("zram")
|
||
[[ $SETUP_TMPFS == true ]] && actions+=("tmpfs")
|
||
[[ $SETUP_KERNEL == true ]] && actions+=("kernel")
|
||
[[ $SETUP_SERVICE == true ]] && actions+=("service")
|
||
[[ $REMOVE_OVERLAYS == true ]] && actions+=("remove-overlays")
|
||
|
||
if [[ ${#actions[@]} -gt 0 ]]; then
|
||
echo "📋 Selected optimizations: ${actions[*]}"
|
||
echo ""
|
||
read -p "Proceed with these optimizations? (y/N): " -n 1 -r
|
||
echo
|
||
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
|
||
log "User cancelled optimization"
|
||
exit 0
|
||
fi
|
||
else
|
||
log "No optimizations selected"
|
||
exit 0
|
||
fi
|
||
|
||
# Export variables for the optimization functions
|
||
export SETUP_ZRAM SETUP_TMPFS SETUP_KERNEL SETUP_SERVICE REMOVE_OVERLAYS
|
||
export SYSTEM_RAM_GB=$ram_gb
|
||
}
|
||
|
||
setup_zram() {
|
||
if [[ $SETUP_ZRAM != true ]]; then
|
||
return 0
|
||
fi
|
||
|
||
log "Configuring zram..."
|
||
|
||
# Calculate optimal size
|
||
local zram_size=$((SYSTEM_RAM_GB / 2))
|
||
[[ $zram_size -lt 2 ]] && zram_size=2
|
||
|
||
# Remove existing zram properly
|
||
if [[ -e /dev/zram0 ]]; then
|
||
log "Removing existing zram configuration..."
|
||
# Disable swap first
|
||
swapoff /dev/zram0 2>/dev/null || true
|
||
sleep 1
|
||
|
||
# Reset the device
|
||
echo 1 > /sys/block/zram0/reset 2>/dev/null || true
|
||
sleep 1
|
||
|
||
# Remove the device if possible
|
||
if [[ -e /sys/class/zram-control/hot_remove ]]; then
|
||
echo 0 > /sys/class/zram-control/hot_remove 2>/dev/null || true
|
||
fi
|
||
sleep 1
|
||
fi
|
||
|
||
# Unload and reload zram module for clean state
|
||
rmmod zram 2>/dev/null || true
|
||
sleep 1
|
||
|
||
# Configure new zram
|
||
log "Setting up new zram with ${zram_size}GB..."
|
||
modprobe zram num_devices=1
|
||
|
||
# Wait for device to be ready
|
||
local attempts=0
|
||
while [[ ! -e /dev/zram0 && $attempts -lt 10 ]]; do
|
||
sleep 1
|
||
((attempts++))
|
||
done
|
||
|
||
if [[ ! -e /dev/zram0 ]]; then
|
||
error "Failed to create zram device"
|
||
return 1
|
||
fi
|
||
|
||
# Configure the new device
|
||
echo "${zram_size}G" > /sys/block/zram0/disksize
|
||
mkswap /dev/zram0
|
||
swapon /dev/zram0
|
||
|
||
success "zram reconfigured with ${zram_size}GB"
|
||
}
|
||
|
||
remove_overlays() {
|
||
if [[ $REMOVE_OVERLAYS != true ]]; then
|
||
return 0
|
||
fi
|
||
|
||
log "Removing overlay filesystem mounts..."
|
||
|
||
# Get list of overlay mounts
|
||
local overlay_mounts=$(mount -t overlay | awk '{print $3}')
|
||
|
||
if [[ -z "$overlay_mounts" ]]; then
|
||
log "No overlay mounts found to remove"
|
||
return 0
|
||
fi
|
||
|
||
# Unmount each overlay
|
||
echo "$overlay_mounts" | while read -r mount_point; do
|
||
if [[ -n "$mount_point" ]]; then
|
||
log " Unmounting overlay: $mount_point"
|
||
if umount "$mount_point" 2>/dev/null; then
|
||
success " Successfully unmounted: $mount_point"
|
||
|
||
# Clean up overlay work directories if they exist in /tmp
|
||
local work_dir="/tmp/overlay-work$(basename "$mount_point")"
|
||
local upper_dir="/tmp/overlay-upper$(basename "$mount_point")"
|
||
|
||
if [[ -d "$work_dir" ]]; then
|
||
rm -rf "$work_dir"
|
||
log " Cleaned up work directory: $work_dir"
|
||
fi
|
||
|
||
if [[ -d "$upper_dir" ]]; then
|
||
rm -rf "$upper_dir"
|
||
log " Cleaned up upper directory: $upper_dir"
|
||
fi
|
||
else
|
||
warn " Failed to unmount: $mount_point (may be in use)"
|
||
fi
|
||
fi
|
||
done
|
||
|
||
# Remove any overlay entries from fstab
|
||
if [[ -f /etc/fstab ]] && grep -q "overlay" /etc/fstab; then
|
||
log "Removing overlay entries from /etc/fstab..."
|
||
cp /etc/fstab /etc/fstab.backup.$(date +%s)
|
||
grep -v "overlay" /etc/fstab > /etc/fstab.tmp && mv /etc/fstab.tmp /etc/fstab
|
||
success "Removed overlay entries from /etc/fstab"
|
||
fi
|
||
|
||
success "Overlay filesystem cleanup completed"
|
||
}
|
||
|
||
setup_tmpfs() {
|
||
if [[ $SETUP_TMPFS != true ]]; then
|
||
return 0
|
||
fi
|
||
|
||
log "Setting up tmpfs cache optimization..."
|
||
|
||
# Check if Proxmox mode
|
||
if [[ "${TMPFS_PROFILE:-}" == "proxmox" ]]; then
|
||
# Proxmox minimal tmpfs: only for APT cache
|
||
mkdir -p /tmp/tmpfs-cache/apt
|
||
|
||
# Remove existing mount if it exists
|
||
if mount | grep -q "/tmp/tmpfs-cache/apt"; then
|
||
umount "/tmp/tmpfs-cache/apt" 2>/dev/null || true
|
||
fi
|
||
|
||
mount -t tmpfs -o size=2G tmpfs /tmp/tmpfs-cache/apt
|
||
|
||
# Configure APT to use tmpfs
|
||
mkdir -p /etc/apt/apt.conf.d
|
||
echo 'Dir::Cache::Archives "/tmp/tmpfs-cache/apt";' > /etc/apt/apt.conf.d/00tmpfs-cache
|
||
|
||
# Add to fstab for persistence
|
||
if ! grep -q "/tmp/tmpfs-cache/apt" /etc/fstab; then
|
||
echo "tmpfs /tmp/tmpfs-cache/apt tmpfs size=2G,mode=0755 0 0" >> /etc/fstab
|
||
fi
|
||
|
||
success "Proxmox minimal tmpfs configured (2GB for APT cache)"
|
||
return 0
|
||
fi
|
||
|
||
# Desktop mode: Full tmpfs setup
|
||
# Determine profile based on RAM
|
||
local profile="medium"
|
||
if [[ $SYSTEM_RAM_GB -ge 16 ]]; then
|
||
profile="large"
|
||
elif [[ $SYSTEM_RAM_GB -le 8 ]]; then
|
||
profile="small"
|
||
fi
|
||
|
||
# Create tmpfs directories
|
||
mkdir -p /tmp/tmpfs-cache/{browser,ide,packages,thumbnails,development,kde}
|
||
|
||
# Remove existing mounts if they exist
|
||
for dir in browser ide packages thumbnails development kde; do
|
||
if mount | grep -q "/tmp/tmpfs-cache/$dir"; then
|
||
umount "/tmp/tmpfs-cache/$dir" 2>/dev/null || true
|
||
fi
|
||
done
|
||
|
||
# Set up tmpfs mounts based on profile
|
||
case "$profile" in
|
||
"large")
|
||
mount -t tmpfs -o size=4G tmpfs /tmp/tmpfs-cache/browser
|
||
mount -t tmpfs -o size=2G tmpfs /tmp/tmpfs-cache/ide
|
||
mount -t tmpfs -o size=3G tmpfs /tmp/tmpfs-cache/packages
|
||
mount -t tmpfs -o size=512M tmpfs /tmp/tmpfs-cache/thumbnails
|
||
mount -t tmpfs -o size=2G tmpfs /tmp/tmpfs-cache/development
|
||
# KDE-specific cache if detected
|
||
if [[ "$XDG_CURRENT_DESKTOP" == *"KDE"* ]] || [[ "$DESKTOP_SESSION" == *"plasma"* ]]; then
|
||
mount -t tmpfs -o size=1G tmpfs /tmp/tmpfs-cache/kde
|
||
fi
|
||
;;
|
||
"medium")
|
||
mount -t tmpfs -o size=2G tmpfs /tmp/tmpfs-cache/browser
|
||
mount -t tmpfs -o size=1G tmpfs /tmp/tmpfs-cache/ide
|
||
mount -t tmpfs -o size=2G tmpfs /tmp/tmpfs-cache/packages
|
||
mount -t tmpfs -o size=256M tmpfs /tmp/tmpfs-cache/thumbnails
|
||
mount -t tmpfs -o size=1G tmpfs /tmp/tmpfs-cache/development
|
||
if [[ "$XDG_CURRENT_DESKTOP" == *"KDE"* ]] || [[ "$DESKTOP_SESSION" == *"plasma"* ]]; then
|
||
mount -t tmpfs -o size=512M tmpfs /tmp/tmpfs-cache/kde
|
||
fi
|
||
;;
|
||
"small")
|
||
mount -t tmpfs -o size=1G tmpfs /tmp/tmpfs-cache/browser
|
||
mount -t tmpfs -o size=512M tmpfs /tmp/tmpfs-cache/ide
|
||
mount -t tmpfs -o size=1G tmpfs /tmp/tmpfs-cache/packages
|
||
mount -t tmpfs -o size=128M tmpfs /tmp/tmpfs-cache/thumbnails
|
||
mount -t tmpfs -o size=512M tmpfs /tmp/tmpfs-cache/development
|
||
if [[ "$XDG_CURRENT_DESKTOP" == *"KDE"* ]] || [[ "$DESKTOP_SESSION" == *"plasma"* ]]; then
|
||
mount -t tmpfs -o size=256M tmpfs /tmp/tmpfs-cache/kde
|
||
fi
|
||
;;
|
||
esac
|
||
|
||
# Bind mount package cache if apt is available
|
||
if [[ -d /var/cache/apt ]]; then
|
||
# Backup existing cache
|
||
if [[ ! -L /var/cache/apt ]] && [[ -d /var/cache/apt ]] && [[ ! -d /var/cache/apt.backup ]]; then
|
||
cp -a /var/cache/apt /var/cache/apt.backup
|
||
fi
|
||
|
||
# Create bind mount
|
||
mount --bind /tmp/tmpfs-cache/packages /var/cache/apt
|
||
fi
|
||
|
||
# Add fstab entries for persistence
|
||
local fstab_tmpfs="/etc/fstab.tmpfs"
|
||
local browser_size ide_size packages_size thumbnails_size development_size kde_size
|
||
|
||
case "$profile" in
|
||
"large")
|
||
browser_size="4G"
|
||
ide_size="2G"
|
||
packages_size="3G"
|
||
thumbnails_size="512M"
|
||
development_size="2G"
|
||
kde_size="1G"
|
||
;;
|
||
"medium")
|
||
browser_size="2G"
|
||
ide_size="1G"
|
||
packages_size="2G"
|
||
thumbnails_size="256M"
|
||
development_size="1G"
|
||
kde_size="512M"
|
||
;;
|
||
"small")
|
||
browser_size="1G"
|
||
ide_size="512M"
|
||
packages_size="1G"
|
||
thumbnails_size="128M"
|
||
development_size="512M"
|
||
kde_size="256M"
|
||
;;
|
||
esac
|
||
|
||
cat > "$fstab_tmpfs" << EOF
|
||
# tmpfs cache mounts - Generated $(date)
|
||
# Profile: $profile for ${SYSTEM_RAM_GB}GB RAM
|
||
tmpfs /tmp/tmpfs-cache/browser tmpfs size=${browser_size},noatime,nosuid,nodev 0 0
|
||
tmpfs /tmp/tmpfs-cache/ide tmpfs size=${ide_size},noatime,nosuid,nodev 0 0
|
||
tmpfs /tmp/tmpfs-cache/packages tmpfs size=${packages_size},noatime,nosuid,nodev 0 0
|
||
tmpfs /tmp/tmpfs-cache/thumbnails tmpfs size=${thumbnails_size},noatime,nosuid,nodev 0 0
|
||
tmpfs /tmp/tmpfs-cache/development tmpfs size=${development_size},noatime,nosuid,nodev 0 0
|
||
EOF
|
||
|
||
# Add KDE-specific mount if KDE is detected
|
||
if [[ "$XDG_CURRENT_DESKTOP" == *"KDE"* ]] || [[ "$DESKTOP_SESSION" == *"plasma"* ]]; then
|
||
echo "tmpfs /tmp/tmpfs-cache/kde tmpfs size=${kde_size},noatime,nosuid,nodev 0 0" >> "$fstab_tmpfs"
|
||
fi
|
||
|
||
success "tmpfs cache optimization enabled ($profile profile)"
|
||
|
||
# Automatically configure detected applications
|
||
configure_applications_for_tmpfs
|
||
|
||
# Show summary of what was configured
|
||
echo ""
|
||
echo "📋 tmpfs Setup Complete:"
|
||
echo "======================="
|
||
echo ""
|
||
echo "🔧 Created tmpfs mount points:"
|
||
mount | grep "tmpfs.*tmpfs-cache" | while read -r line; do
|
||
mount_point=$(echo "$line" | awk '{print $3}')
|
||
size=$(echo "$line" | grep -o 'size=[^,]*' | cut -d= -f2)
|
||
echo " 📁 $mount_point - Size: $size"
|
||
done
|
||
|
||
echo ""
|
||
echo "⚡ Performance Benefits:"
|
||
echo " • <20> Faster cache access (RAM speed vs SSD)"
|
||
echo " • 💿 Reduced SSD wear and tear"
|
||
echo " • 🧹 Automatic cleanup on reboot"
|
||
echo " • 🔋 Lower power consumption for cache operations"
|
||
}
|
||
|
||
configure_applications_for_tmpfs() {
|
||
log "Auto-configuring applications to use tmpfs caches..."
|
||
echo ""
|
||
|
||
local configured_count=0
|
||
local current_user=$(logname 2>/dev/null || echo $SUDO_USER)
|
||
local user_home=$(eval echo ~$current_user)
|
||
|
||
# Browser Configuration
|
||
echo "🌐 Configuring Browsers:"
|
||
|
||
# Firefox
|
||
for firefox_profile in "$user_home"/.mozilla/firefox/*.default* "$user_home"/.mozilla/firefox/*.default-release*; do
|
||
if [[ -d "$firefox_profile" ]]; then
|
||
local prefs_file="$firefox_profile/prefs.js"
|
||
if [[ -f "$prefs_file" ]]; then
|
||
# Backup original
|
||
cp "$prefs_file" "$prefs_file.backup.$(date +%s)" 2>/dev/null || true
|
||
|
||
# Remove old cache settings
|
||
sed -i '/browser.cache.disk.parent_directory/d' "$prefs_file" 2>/dev/null || true
|
||
|
||
# Add new cache location
|
||
echo 'user_pref("browser.cache.disk.parent_directory", "/tmp/tmpfs-cache/browser/firefox");' >> "$prefs_file"
|
||
|
||
# Create cache directory
|
||
mkdir -p /tmp/tmpfs-cache/browser/firefox
|
||
chown -R $current_user:$current_user /tmp/tmpfs-cache/browser/firefox
|
||
|
||
success " ✅ Firefox configured to use tmpfs cache"
|
||
configured_count=$((configured_count + 1))
|
||
fi
|
||
fi
|
||
done
|
||
|
||
# Brave Browser
|
||
if [[ -d "$user_home/.config/BraveSoftware" ]]; then
|
||
mkdir -p /tmp/tmpfs-cache/browser/brave
|
||
mkdir -p "$user_home/.local/share/applications"
|
||
chown -R $current_user:$current_user /tmp/tmpfs-cache/browser/brave
|
||
|
||
local brave_desktop="$user_home/.local/share/applications/brave-browser.desktop"
|
||
cat > "$brave_desktop" << 'BRAVEEOF'
|
||
[Desktop Entry]
|
||
Version=1.0
|
||
Name=Brave Browser (tmpfs optimized)
|
||
Exec=brave-browser --disk-cache-dir=/tmp/tmpfs-cache/browser/brave %U
|
||
StartupNotify=true
|
||
Terminal=false
|
||
Icon=brave-browser
|
||
Type=Application
|
||
Categories=Network;WebBrowser;
|
||
MimeType=text/html;text/xml;application/xhtml+xml;x-scheme-handler/http;x-scheme-handler/https;
|
||
BRAVEEOF
|
||
chown $current_user:$current_user "$brave_desktop" 2>/dev/null || true
|
||
chmod +x "$brave_desktop" 2>/dev/null || true
|
||
success " ✅ Brave Browser configured to use tmpfs cache"
|
||
configured_count=$((configured_count + 1))
|
||
fi
|
||
|
||
# Google Chrome
|
||
if [[ -d "$user_home/.config/google-chrome" ]]; then
|
||
mkdir -p /tmp/tmpfs-cache/browser/google-chrome
|
||
mkdir -p "$user_home/.local/share/applications"
|
||
chown -R $current_user:$current_user /tmp/tmpfs-cache/browser/google-chrome
|
||
|
||
local chrome_desktop="$user_home/.local/share/applications/google-chrome.desktop"
|
||
cat > "$chrome_desktop" << 'CHROMEOF'
|
||
[Desktop Entry]
|
||
Version=1.0
|
||
Name=Google Chrome (tmpfs optimized)
|
||
Exec=google-chrome --disk-cache-dir=/tmp/tmpfs-cache/browser/google-chrome %U
|
||
StartupNotify=true
|
||
Terminal=false
|
||
Icon=google-chrome
|
||
Type=Application
|
||
Categories=Network;WebBrowser;
|
||
MimeType=text/html;text/xml;application/xhtml+xml;x-scheme-handler/http;x-scheme-handler/https;
|
||
CHROMEOF
|
||
chown $current_user:$current_user "$chrome_desktop" 2>/dev/null || true
|
||
chmod +x "$chrome_desktop" 2>/dev/null || true
|
||
success " ✅ Google Chrome configured to use tmpfs cache"
|
||
configured_count=$((configured_count + 1))
|
||
fi
|
||
|
||
# Chromium
|
||
if [[ -d "$user_home/.config/chromium" ]]; then
|
||
mkdir -p /tmp/tmpfs-cache/browser/chromium
|
||
mkdir -p "$user_home/.local/share/applications"
|
||
chown -R $current_user:$current_user /tmp/tmpfs-cache/browser/chromium
|
||
|
||
local chromium_desktop="$user_home/.local/share/applications/chromium-browser.desktop"
|
||
cat > "$chromium_desktop" << 'CHROMIUMEOF'
|
||
[Desktop Entry]
|
||
Version=1.0
|
||
Name=Chromium (tmpfs optimized)
|
||
Exec=chromium --disk-cache-dir=/tmp/tmpfs-cache/browser/chromium %U
|
||
StartupNotify=true
|
||
Terminal=false
|
||
Icon=chromium
|
||
Type=Application
|
||
Categories=Network;WebBrowser;
|
||
MimeType=text/html;text/xml;application/xhtml+xml;x-scheme-handler/http;x-scheme-handler/https;
|
||
CHROMIUMEOF
|
||
chown $current_user:$current_user "$chromium_desktop" 2>/dev/null || true
|
||
chmod +x "$chromium_desktop" 2>/dev/null || true
|
||
success " ✅ Chromium configured to use tmpfs cache"
|
||
configured_count=$((configured_count + 1))
|
||
fi
|
||
|
||
# Development Tools Configuration
|
||
echo ""
|
||
echo "💻 Configuring Development Tools:"
|
||
|
||
# NPM
|
||
if command -v npm &>/dev/null; then
|
||
sudo -u $current_user npm config set cache /tmp/tmpfs-cache/development/npm 2>/dev/null && \
|
||
success " ✅ NPM cache configured" && configured_count=$((configured_count + 1))
|
||
fi
|
||
|
||
# Pip
|
||
if command -v pip3 &>/dev/null || command -v pip &>/dev/null; then
|
||
mkdir -p "$user_home/.config/pip"
|
||
cat > "$user_home/.config/pip/pip.conf" << 'PIPEOF'
|
||
[global]
|
||
cache-dir = /tmp/tmpfs-cache/development/pip
|
||
PIPEOF
|
||
chown $current_user:$current_user "$user_home/.config/pip/pip.conf" 2>/dev/null || true
|
||
success " ✅ Pip cache configured" && configured_count=$((configured_count + 1))
|
||
fi
|
||
|
||
# KDE/Plasma Configuration
|
||
if [[ "$XDG_CURRENT_DESKTOP" == *"KDE"* ]] || [[ "$DESKTOP_SESSION" == *"plasma"* ]]; then
|
||
echo ""
|
||
echo "🖥️ Configuring KDE/Plasma:"
|
||
|
||
# Link thumbnails
|
||
if [[ -d "$user_home/.cache/thumbnails" ]]; then
|
||
mv "$user_home/.cache/thumbnails" "$user_home/.cache/thumbnails.backup.$(date +%s)" 2>/dev/null || true
|
||
fi
|
||
mkdir -p /tmp/tmpfs-cache/kde/thumbnails
|
||
ln -sf /tmp/tmpfs-cache/kde/thumbnails "$user_home/.cache/thumbnails"
|
||
chown -R $current_user:$current_user /tmp/tmpfs-cache/kde/thumbnails
|
||
success " ✅ KDE thumbnail cache linked to tmpfs"
|
||
configured_count=$((configured_count + 1))
|
||
fi
|
||
|
||
echo ""
|
||
if [[ $configured_count -gt 0 ]]; then
|
||
success "🎉 Automatically configured $configured_count applications!"
|
||
echo ""
|
||
log "💡 Changes will take effect when you restart the configured applications"
|
||
else
|
||
log "ℹ️ No applications detected for automatic configuration"
|
||
echo " You can manually configure other applications to use:"
|
||
echo " • Browser cache: /tmp/tmpfs-cache/browser/"
|
||
echo " • Dev tools: /tmp/tmpfs-cache/development/"
|
||
echo " • IDE cache: /tmp/tmpfs-cache/ide/"
|
||
fi
|
||
}
|
||
|
||
tune_kernel() {
|
||
if [[ ${TUNE_KERNEL:-false} != true ]]; then
|
||
return 0
|
||
fi
|
||
|
||
log "Optimizing kernel parameters..."
|
||
|
||
local sysctl_conf="/etc/sysctl.d/99-system-optimization.conf"
|
||
|
||
# Determine optimal values based on mode
|
||
local swappiness=5
|
||
local dirty_ratio=5
|
||
local profile="desktop"
|
||
|
||
if [[ "${KERNEL_PROFILE:-desktop}" == "proxmox" ]]; then
|
||
# Proxmox-specific parameters
|
||
swappiness=10
|
||
dirty_ratio=10
|
||
profile="proxmox-host"
|
||
|
||
cat > "$sysctl_conf" << EOF
|
||
# Proxmox Host Optimization - Generated $(date)
|
||
# Profile: $profile for ${SYSTEM_RAM_GB}GB RAM
|
||
|
||
# Memory management (for hypervisor workload)
|
||
vm.swappiness = $swappiness
|
||
vm.dirty_ratio = $dirty_ratio
|
||
vm.dirty_background_ratio = 5
|
||
vm.vfs_cache_pressure = 50
|
||
vm.min_free_kbytes = 67584
|
||
|
||
# Networking (for VM/CT traffic)
|
||
net.core.default_qdisc = fq
|
||
net.ipv4.tcp_congestion_control = bbr
|
||
net.core.netdev_max_backlog = 5000
|
||
net.ipv4.tcp_max_syn_backlog = 8192
|
||
net.core.rmem_max = 16777216
|
||
net.core.wmem_max = 16777216
|
||
|
||
# File system
|
||
fs.file-max = 2097152
|
||
fs.inotify.max_user_watches = 524288
|
||
|
||
# Kernel
|
||
kernel.panic = 10
|
||
kernel.panic_on_oops = 1
|
||
EOF
|
||
else
|
||
# Desktop-specific parameters
|
||
if [[ $SYSTEM_RAM_GB -ge 16 ]]; then
|
||
swappiness=1
|
||
dirty_ratio=3
|
||
profile="high-memory-desktop"
|
||
elif [[ $SYSTEM_RAM_GB -le 4 ]]; then
|
||
swappiness=10
|
||
dirty_ratio=10
|
||
profile="low-memory-desktop"
|
||
fi
|
||
|
||
cat > "$sysctl_conf" << EOF
|
||
# Desktop System Optimization - Generated $(date)
|
||
# Profile: $profile for ${SYSTEM_RAM_GB}GB RAM
|
||
|
||
# Memory management
|
||
vm.swappiness = $swappiness
|
||
vm.dirty_ratio = $dirty_ratio
|
||
vm.dirty_background_ratio = $((dirty_ratio / 2))
|
||
vm.vfs_cache_pressure = 50
|
||
|
||
# Network optimizations
|
||
net.core.rmem_max = 16777216
|
||
net.core.wmem_max = 16777216
|
||
|
||
# General performance
|
||
kernel.sched_autogroup_enabled = 1
|
||
EOF
|
||
fi
|
||
|
||
# Apply immediately
|
||
sysctl -p "$sysctl_conf"
|
||
success "Kernel parameters optimized ($profile profile)"
|
||
}
|
||
|
||
create_service() {
|
||
if [[ $SETUP_SERVICE != true ]]; then
|
||
return 0
|
||
fi
|
||
|
||
log "Creating systemd service..."
|
||
|
||
# Create startup script
|
||
cat > /usr/local/bin/system-optimization-startup.sh << 'EOF'
|
||
#!/bin/bash
|
||
# Recreate optimizations after reboot
|
||
|
||
# Ensure zram if not present
|
||
if [[ ! -e /dev/zram0 ]]; then
|
||
ram_gb=$(free -g | awk '/^Mem:|^Speicher:/{print $2}')
|
||
zram_size=$((ram_gb / 2))
|
||
[[ $zram_size -lt 2 ]] && zram_size=2
|
||
|
||
modprobe zram num_devices=1 2>/dev/null || true
|
||
if [[ -e /sys/block/zram0/disksize ]]; then
|
||
echo "${zram_size}G" > /sys/block/zram0/disksize
|
||
mkswap /dev/zram0
|
||
swapon /dev/zram0
|
||
fi
|
||
fi
|
||
|
||
# Recreate tmpfs mounts if configured
|
||
if [[ -f /etc/fstab.tmpfs ]]; then
|
||
# Create directories
|
||
mkdir -p /tmp/tmpfs-cache/{browser,ide,packages,thumbnails,development,kde}
|
||
|
||
# Mount tmpfs filesystems
|
||
while IFS= read -r line; do
|
||
if [[ $line =~ ^tmpfs ]]; then
|
||
# Parse the fstab line and mount
|
||
eval "mount $line" 2>/dev/null || true
|
||
fi
|
||
done < /etc/fstab.tmpfs
|
||
|
||
# Restore package cache bind mount
|
||
if [[ -d /var/cache/apt ]] && [[ -d /tmp/tmpfs-cache/packages ]]; then
|
||
mount --bind /tmp/tmpfs-cache/packages /var/cache/apt 2>/dev/null || true
|
||
fi
|
||
fi
|
||
EOF
|
||
|
||
chmod +x /usr/local/bin/system-optimization-startup.sh
|
||
|
||
# Create systemd service
|
||
cat > /etc/systemd/system/system-optimization.service << EOF
|
||
[Unit]
|
||
Description=System Performance Optimization
|
||
After=multi-user.target
|
||
|
||
[Service]
|
||
Type=oneshot
|
||
ExecStart=/usr/local/bin/system-optimization-startup.sh
|
||
RemainAfterExit=yes
|
||
|
||
[Install]
|
||
WantedBy=multi-user.target
|
||
EOF
|
||
|
||
systemctl daemon-reload
|
||
systemctl enable system-optimization.service
|
||
|
||
success "Systemd service created and enabled"
|
||
}
|
||
|
||
show_final_status() {
|
||
echo ""
|
||
echo "🎉 Optimization Complete!"
|
||
echo "========================"
|
||
echo ""
|
||
|
||
# Show current status with more details
|
||
echo "📊 Current Optimization Status:"
|
||
|
||
# zram with usage info
|
||
if [[ -e /dev/zram0 ]] && swapon --show | grep -q zram0; then
|
||
local zram_size=$(swapon --show | grep zram0 | awk '{print $3}')
|
||
local zram_used=$(swapon --show | grep zram0 | awk '{print $4}')
|
||
echo " 🗜️ zram: $zram_size (used: ${zram_used:-0B})"
|
||
fi
|
||
|
||
# tmpfs with detailed mount info
|
||
local tmpfs_count=$(mount | grep "tmpfs.*tmpfs-cache" | wc -l)
|
||
echo " 💾 tmpfs: $tmpfs_count cache mounts active"
|
||
if [[ $tmpfs_count -gt 0 ]]; then
|
||
local total_tmpfs_size=0
|
||
echo " 📁 Active mounts:"
|
||
mount | grep "tmpfs.*tmpfs-cache" | while read -r line; do
|
||
local mount_point=$(echo "$line" | awk '{print $3}' | sed 's|/tmp/tmpfs-cache/||')
|
||
local size_kb=$(echo "$line" | grep -o 'size=[^,]*' | cut -d= -f2 | sed 's/k$//')
|
||
local size_mb=$((size_kb / 1024))
|
||
local usage=$(df "$line" 2>/dev/null | tail -1 | awk '{print $5}' || echo "0%")
|
||
printf " • %-12s: %4dMB (%s used)\n" "$mount_point" "$size_mb" "$usage"
|
||
done
|
||
|
||
# Calculate total allocated tmpfs space
|
||
local total_kb=0
|
||
while read -r line; do
|
||
local size_kb=$(echo "$line" | grep -o 'size=[^,]*' | cut -d= -f2 | sed 's/k$//')
|
||
total_kb=$((total_kb + size_kb))
|
||
done < <(mount | grep "tmpfs.*tmpfs-cache")
|
||
local total_mb=$((total_kb / 1024))
|
||
echo " 📊 Total tmpfs allocated: ${total_mb}MB"
|
||
fi
|
||
|
||
# overlay status
|
||
local overlay_count=$(mount -t overlay | wc -l)
|
||
if [[ $overlay_count -eq 0 ]]; then
|
||
echo " 🗂️ overlays: None (optimal for desktop systems)"
|
||
else
|
||
echo " ⚠️ overlays: $overlay_count mounts found (consider removal)"
|
||
fi
|
||
|
||
# kernel with current values
|
||
if [[ -f /etc/sysctl.d/99-system-optimization.conf ]]; then
|
||
local swappiness=$(sysctl -n vm.swappiness 2>/dev/null)
|
||
local dirty_ratio=$(sysctl -n vm.dirty_ratio 2>/dev/null)
|
||
echo " ⚙️ kernel: swappiness=$swappiness, dirty_ratio=$dirty_ratio"
|
||
fi
|
||
|
||
# service status
|
||
if systemctl is-enabled system-optimization.service &>/dev/null; then
|
||
echo " 🔄 service: enabled (will restore tmpfs on reboot)"
|
||
fi
|
||
|
||
echo ""
|
||
echo "🎯 Next Steps:"
|
||
echo " 1. 🔄 Restart configured applications (browsers, IDEs) to use new cache locations"
|
||
echo " 2. 📊 Monitor cache usage: df -h | grep tmpfs-cache"
|
||
echo " 3. 🔍 Check status anytime: ./quick-status-check.sh"
|
||
echo " 4. <20> Optional: Reboot to verify all optimizations persist"
|
||
echo ""
|
||
echo "💡 Useful Commands:"
|
||
echo " • Check tmpfs usage: df -h /tmp/tmpfs-cache/*"
|
||
echo " • Monitor performance: iotop -ao"
|
||
echo " • View mount details: mount | grep tmpfs-cache"
|
||
echo ""
|
||
echo "🔧 Changes applied successfully!"
|
||
if [[ $tmpfs_count -gt 0 ]]; then
|
||
# Calculate total tmpfs space for the final message
|
||
local final_total_kb=0
|
||
while read -r line; do
|
||
local size_kb=$(echo "$line" | grep -o 'size=[^,]*' | cut -d= -f2 | sed 's/k$//')
|
||
final_total_kb=$((final_total_kb + size_kb))
|
||
done < <(mount | grep "tmpfs.*tmpfs-cache")
|
||
local final_total_mb=$((final_total_kb / 1024))
|
||
echo "🚀 Your system now has ${final_total_mb}MB of high-speed cache storage in RAM!"
|
||
fi
|
||
}
|
||
|
||
main() {
|
||
echo "🚀 Interactive System Optimizer"
|
||
echo "==============================="
|
||
echo ""
|
||
|
||
check_root
|
||
check_proxmox
|
||
|
||
# Setup directories
|
||
mkdir -p "$(dirname "$LOG_FILE")" "$BACKUP_DIR"
|
||
touch "$LOG_FILE" 2>/dev/null || true
|
||
|
||
# Analyze and get user input
|
||
analyze_and_prompt
|
||
|
||
# Apply selected optimizations
|
||
remove_overlays
|
||
setup_zram
|
||
setup_tmpfs
|
||
tune_kernel
|
||
create_service
|
||
|
||
# Show results
|
||
show_final_status
|
||
|
||
log "Optimization completed successfully"
|
||
}
|
||
|
||
main "$@" |