Files
linux_system_tuning/one-button-optimizer.sh
mindesbunister 2edb4a73c3 Complete Linux system optimization suite with tmpfs, zram, and German locale support
- Fixed missing setup_tmpfs() function that was causing silent failures
- Added comprehensive system scanning for browsers, IDEs, gaming caches
- Implemented detailed optimization information display for transparency
- Added German locale compatibility for 'free' command (Speicher: vs Mem:)
- Fixed division by zero errors in RAM calculations
- Created tmpfs-info.sh helper script for detailed status reporting
- Enhanced scanning to work on already-optimized systems
- Added comprehensive optimization breakdowns with purpose explanations
2025-09-23 12:11:45 +02:00

1000 lines
38 KiB
Bash
Executable File
Raw Blame History

#!/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
}
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"
echo ""
# Check and prompt for each optimization
local needs_changes=false
# === ZRAM CHECK ===
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
echo ""
# === TMPFS CHECK ===
echo "💾 tmpfs Cache System Analysis:"
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
# 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 overlayfs)\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
echo ""
# === KERNEL PARAMS CHECK ===
echo "⚙️ Kernel Parameters Analysis:"
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
SETUP_KERNEL=true
else
SETUP_KERNEL=false
fi
else
echo " ✅ Parameters are optimal"
SETUP_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
SETUP_KERNEL=true
else
SETUP_KERNEL=false
fi
fi
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 ""
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")
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
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"
}
setup_tmpfs() {
if [[ $SETUP_TMPFS != true ]]; then
return 0
fi
log "Setting up tmpfs cache optimization..."
# 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)"
# Show detailed information about what was set up
echo ""
echo "📋 tmpfs Setup Details:"
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 "💡 How to use these optimizations:"
echo ""
echo "🌐 Browser Cache (/tmp/tmpfs-cache/browser):"
echo " • Chrome: Set cache to /tmp/tmpfs-cache/browser/chrome"
echo " • Firefox: Set cache to /tmp/tmpfs-cache/browser/firefox"
echo " • Manual: ln -sf /tmp/tmpfs-cache/browser ~/.cache/browser-backup"
echo ""
echo "💻 Development Cache (/tmp/tmpfs-cache/development):"
echo " • NPM: npm config set cache /tmp/tmpfs-cache/development/npm"
echo " • Pip: export PIP_CACHE_DIR=/tmp/tmpfs-cache/development/pip"
echo " • Docker: Configure build cache to use this mount"
echo ""
echo "🎨 IDE Cache (/tmp/tmpfs-cache/ide):"
echo " • VS Code: Link ~/.vscode to /tmp/tmpfs-cache/ide/vscode"
echo " • JetBrains: Configure temp/cache directories"
echo ""
if [[ "$XDG_CURRENT_DESKTOP" == *"KDE"* ]] || [[ "$DESKTOP_SESSION" == *"plasma"* ]]; then
echo "🖥️ KDE Cache (/tmp/tmpfs-cache/kde):"
echo " • Baloo: kwriteconfig5 --file baloofilerc --group 'Basic Settings' --key 'Indexing-Enabled' false"
echo " • Thumbnails: Link ~/.cache/thumbnails to /tmp/tmpfs-cache/kde/thumbnails"
echo " • Plasma cache: Automatically used by system"
echo ""
fi
echo "📦 Package Cache (Automatically configured):"
echo " • APT cache is already bound to /var/cache/apt → tmpfs"
echo " • Reduces SSD wear during package operations"
echo ""
echo "⚡ Performance Benefits:"
echo " • 🚀 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"
}
tune_kernel() {
if [[ $SETUP_KERNEL != true ]]; then
return 0
fi
log "Optimizing kernel parameters..."
local sysctl_conf="/etc/sysctl.d/99-system-optimization.conf"
# Determine optimal values
local swappiness=5
local dirty_ratio=5
local profile="desktop"
if [[ $SYSTEM_RAM_GB -ge 16 ]]; then
swappiness=1
dirty_ratio=3
profile="high-memory"
elif [[ $SYSTEM_RAM_GB -le 4 ]]; then
swappiness=10
dirty_ratio=10
profile="low-memory"
fi
cat > "$sysctl_conf" << EOF
# 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
# 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
# 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. <20> Reboot to ensure all optimizations persist"
echo " 2. 🌐 Configure applications to use tmpfs caches (see details above)"
echo " 3. 📊 Monitor usage: df -h | grep tmpfs-cache"
echo " 4. 🔍 Check status anytime: ./quick-status-check.sh"
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
# 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
setup_zram
setup_tmpfs
tune_kernel
create_service
# Show results
show_final_status
log "Optimization completed successfully"
}
main "$@"