#!/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 # === 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 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 "" # Check if applications are already configured for tmpfs local current_user=$(logname 2>/dev/null || echo $SUDO_USER) local user_home=$(eval echo ~$current_user) local apps_configured=false # Quick check if browsers are configured if [[ -f "$user_home/.mozilla/firefox"/*default*/prefs.js ]] && \ grep -q "tmpfs-cache" "$user_home/.mozilla/firefox"/*default*/prefs.js 2>/dev/null; then apps_configured=true fi if [[ ! $apps_configured ]]; then echo "๐Ÿ“ฑ Application Configuration:" echo " โš ๏ธ Your applications are not yet configured to use tmpfs caches" echo "" read -p " Would you like to automatically configure your browsers and dev tools? (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..." # 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 " โ€ข ๏ฟฝ 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++)) fi fi done # Chrome/Chromium if command -v google-chrome &>/dev/null || command -v chromium &>/dev/null; then local chrome_dir="$user_home/.config/google-chrome" local chromium_dir="$user_home/.config/chromium" for browser_dir in "$chrome_dir" "$chromium_dir"; do if [[ -d "$browser_dir" ]]; then local browser_name=$(basename "$browser_dir") mkdir -p /tmp/tmpfs-cache/browser/$browser_name # Create wrapper script to launch with cache dir local desktop_file="" if [[ "$browser_name" == "google-chrome" ]]; then desktop_file="$user_home/.local/share/applications/google-chrome.desktop" cat > "$desktop_file" << '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 else desktop_file="$user_home/.local/share/applications/chromium.desktop" cat > "$desktop_file" << '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 fi chown $current_user:$current_user "$desktop_file" 2>/dev/null || true chmod +x "$desktop_file" 2>/dev/null || true success " โœ… $browser_name configured to use tmpfs cache" ((configured_count++)) fi done fi # Brave if [[ -d "$user_home/.config/BraveSoftware" ]]; then mkdir -p /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 configured to use tmpfs cache" ((configured_count++)) 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++)) 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++)) 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++)) 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 [[ $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 # 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. ๏ฟฝ 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 # 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 "$@"