commit 697a01ce36aa4607bdbc3670a9d6a1da814865cc Author: root Date: Sun Sep 21 15:52:07 2025 +0200 Initial commit: Linux System Tuning Suite - Intelligent hardware detection and analysis - Modular optimization system with profiles - Automatic tmpfs, zram, and kernel tuning - Real-time monitoring and health checks - Support for desktop, gaming, and development workloads - Safe backup and rollback capabilities - Systemd integration for persistent optimizations diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..56a80d5 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2025 Linux System Tuning Suite + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..3e5e116 --- /dev/null +++ b/README.md @@ -0,0 +1,94 @@ +# Linux System Tuning Suite + +🚀 **Intelligent system optimization toolkit for Linux desktop systems** + +This repository provides automated system tuning based on hardware detection, usage patterns, and best practices for tmpfs, overlay filesystems, and kernel parameter optimization. + +## 🎯 Features + +- **Hardware Detection**: Automatically detects RAM, CPU, storage configuration +- **Usage Analysis**: Identifies frequently accessed files and directories +- **Intelligent Tuning**: Applies optimizations based on system characteristics +- **Modular Design**: Easy to customize and extend +- **Safe Deployment**: Backup and rollback capabilities +- **Multi-Distribution**: Works across different Linux distributions + +## 🏗️ Components + +### Core Scripts +- `tune-system.sh` - Main tuning orchestrator +- `system-analyzer.sh` - Hardware and usage analysis +- `optimizer.sh` - Apply specific optimizations +- `monitor.sh` - System monitoring and health checks + +### Modules +- `modules/hardware-detection.sh` - RAM, CPU, storage detection +- `modules/usage-analysis.sh` - File access pattern analysis +- `modules/tmpfs-optimizer.sh` - tmpfs configuration +- `modules/overlay-optimizer.sh` - overlay filesystem setup +- `modules/kernel-tuning.sh` - kernel parameter optimization +- `modules/zram-optimizer.sh` - zram/zswap configuration + +### Profiles +- `profiles/` - Pre-configured optimization profiles +- `configs/` - Configuration templates + +## 🚀 Quick Start + +```bash +# Clone the repository +git clone git@gitea.egonetix.de:root/linux_system_tuning.git +cd linux_system_tuning + +# Run system analysis +sudo ./system-analyzer.sh + +# Apply optimizations +sudo ./tune-system.sh --auto + +# Monitor results +./monitor.sh +``` + +## 📊 Supported Optimizations + +- **Memory Management**: zram, tmpfs, overlay filesystems +- **Kernel Tuning**: vm parameters, scheduler settings +- **Cache Optimization**: Browser, IDE, package manager caches +- **I/O Optimization**: Storage and network tuning +- **Desktop Responsiveness**: Priority and scheduling tweaks + +## 🔧 Configuration + +The system can be configured through: +- Interactive setup wizard +- Configuration files +- Command-line parameters +- Environment variables + +## 📈 Benchmarking + +Built-in benchmarking tools to measure: +- Boot time improvements +- Application startup times +- Memory utilization efficiency +- I/O performance gains + +## 🛡️ Safety + +- Automatic backups before changes +- Rollback capabilities +- Safe mode for testing +- Validation checks + +## 📄 License + +MIT License - see LICENSE file for details + +## 🤝 Contributing + +Contributions welcome! Please read CONTRIBUTING.md for guidelines. + +--- + +*Making Linux systems faster, one optimization at a time* ⚡ \ No newline at end of file diff --git a/configs/default.conf b/configs/default.conf new file mode 100644 index 0000000..dab3686 --- /dev/null +++ b/configs/default.conf @@ -0,0 +1,43 @@ +# Configuration Template +# Copy this file to /var/lib/system-tuning/configs/custom.conf and modify + +# Global settings +PROFILE="desktop" # desktop, gaming, development, minimal +DRY_RUN=false # Test mode - show what would be done +VERBOSE=true # Detailed output +BACKUP_ENABLED=true # Create backups before changes + +# Memory settings +ZRAM_ENABLED=true # Enable zram compression +ZRAM_SIZE="auto" # Size: auto, 4G, 8G, 12G, etc. +ZRAM_ALGORITHM="lz4" # Compression: lz4, zstd, lzo + +# tmpfs settings +TMPFS_BROWSER_CACHE=true # Browser cache in RAM +TMPFS_IDE_CACHE=true # IDE/editor cache in RAM +TMPFS_PACKAGE_CACHE=true # Package manager cache in RAM +TMPFS_BUILD_CACHE=false # Build cache in RAM (development) + +# Kernel tuning +TUNE_KERNEL_PARAMS=true # Optimize kernel parameters +CUSTOM_SWAPPINESS="" # Leave empty for profile default +CUSTOM_DIRTY_RATIO="" # Leave empty for profile default + +# Advanced settings +OVERLAY_ENABLED=false # Enable overlay filesystems +OVERLAY_PROTECT_CONFIGS=false # Protect system configs with overlay +SYSTEMD_SERVICE=true # Install systemd service + +# Exclusions (space-separated paths) +EXCLUDE_PATHS="/home/user/important /opt/critical" + +# Custom tmpfs mounts (format: path:size) +CUSTOM_TMPFS=" +/tmp/custom-cache:1G +/var/tmp/builds:2G +" + +# Performance monitoring +ENABLE_MONITORING=true # Enable performance monitoring +LOG_METRICS=true # Log performance metrics +BENCHMARK_ON_COMPLETION=false # Run benchmark after optimization \ No newline at end of file diff --git a/install.sh b/install.sh new file mode 100755 index 0000000..fac292a --- /dev/null +++ b/install.sh @@ -0,0 +1,46 @@ +#!/bin/bash +# Installation script for Linux System Tuning Suite + +set -euo pipefail + +INSTALL_DIR="/opt/linux-system-tuning" +BIN_DIR="/usr/local/bin" +SYSTEMD_DIR="/etc/systemd/system" + +echo "🚀 Installing Linux System Tuning Suite" +echo "=======================================" + +# Check if running as root +if [[ $EUID -ne 0 ]]; then + echo "Please run this installer as root (use sudo)" + exit 1 +fi + +# Create installation directory +echo "Creating installation directory..." +mkdir -p "$INSTALL_DIR" +cp -r * "$INSTALL_DIR/" + +# Create symlinks in PATH +echo "Creating command symlinks..." +ln -sf "$INSTALL_DIR/tune-system.sh" "$BIN_DIR/tune-system" +ln -sf "$INSTALL_DIR/system-analyzer.sh" "$BIN_DIR/system-analyzer" +ln -sf "$INSTALL_DIR/monitor.sh" "$BIN_DIR/system-monitor" + +# Create directories +mkdir -p /var/lib/system-tuning/{backups,configs,logs} +mkdir -p /tmp/tmpfs-cache + +echo "✅ Installation complete!" +echo "" +echo "Available commands:" +echo " tune-system - Main tuning tool" +echo " system-analyzer - System analysis" +echo " system-monitor - Performance monitoring" +echo "" +echo "Quick start:" +echo " sudo system-analyzer # Analyze your system" +echo " sudo tune-system --auto # Apply optimizations" +echo " system-monitor live # Monitor performance" +echo "" +echo "For more information, see: $INSTALL_DIR/README.md" \ No newline at end of file diff --git a/modules/hardware-detection.sh b/modules/hardware-detection.sh new file mode 100755 index 0000000..a48dee2 --- /dev/null +++ b/modules/hardware-detection.sh @@ -0,0 +1,178 @@ +#!/bin/bash +# Hardware Detection Module +# Part of Linux System Tuning Suite + +detect_hardware() { + local output_file="${1:-/dev/stdout}" + + # Detect RAM + local ram_total_gb=$(free -g | awk '/^Mem:/{print $2}') + local ram_total_mb=$(free -m | awk '/^Mem:/{print $2}') + local ram_available_gb=$(free -g | awk '/^Mem:/{print $7}') + + # Detect CPU + local cpu_cores=$(nproc) + local cpu_threads=$(lscpu | grep "^CPU(s):" | awk '{print $2}') + local cpu_model=$(lscpu | grep "Model name:" | sed 's/Model name:[[:space:]]*//') + local cpu_arch=$(uname -m) + local cpu_freq=$(lscpu | grep "CPU MHz:" | awk '{print $3}' | head -1) + + # Detect storage + local ssd_count=0 + local hdd_count=0 + local nvme_count=0 + + while IFS= read -r line; do + if [[ "$line" =~ nvme ]]; then + ((nvme_count++)) + elif [[ "$line" =~ "0$" ]]; then + ((ssd_count++)) + elif [[ "$line" =~ "1$" ]]; then + ((hdd_count++)) + fi + done < <(lsblk -d -o name,rota 2>/dev/null | tail -n +2) + + # Detect GPU + local gpu_info="" + if command -v lspci >/dev/null 2>&1; then + gpu_info=$(lspci | grep -i "vga\|3d\|display" | head -1) + fi + + # Generate hardware profile + cat > "$output_file" << EOF +{ + "ram": { + "total_gb": $ram_total_gb, + "total_mb": $ram_total_mb, + "available_gb": $ram_available_gb, + "classification": "$(classify_ram_size $ram_total_gb)" + }, + "cpu": { + "cores": $cpu_cores, + "threads": $cpu_threads, + "model": "$cpu_model", + "architecture": "$cpu_arch", + "frequency_mhz": ${cpu_freq:-0}, + "classification": "$(classify_cpu_performance $cpu_cores)" + }, + "storage": { + "nvme_drives": $nvme_count, + "ssd_drives": $ssd_count, + "hdd_drives": $hdd_count, + "primary_type": "$(determine_primary_storage_type $nvme_count $ssd_count $hdd_count)" + }, + "gpu": "$gpu_info", + "optimization_profile": "$(determine_optimization_profile $ram_total_gb $cpu_cores $nvme_count $ssd_count)" +} +EOF +} + +classify_ram_size() { + local ram_gb=$1 + + if [[ $ram_gb -ge 32 ]]; then + echo "very_high" + elif [[ $ram_gb -ge 16 ]]; then + echo "high" + elif [[ $ram_gb -ge 8 ]]; then + echo "medium" + elif [[ $ram_gb -ge 4 ]]; then + echo "low" + else + echo "very_low" + fi +} + +classify_cpu_performance() { + local cores=$1 + + if [[ $cores -ge 16 ]]; then + echo "very_high" + elif [[ $cores -ge 8 ]]; then + echo "high" + elif [[ $cores -ge 4 ]]; then + echo "medium" + elif [[ $cores -ge 2 ]]; then + echo "low" + else + echo "very_low" + fi +} + +determine_primary_storage_type() { + local nvme=$1 + local ssd=$2 + local hdd=$3 + + if [[ $nvme -gt 0 ]]; then + echo "nvme" + elif [[ $ssd -gt 0 ]]; then + echo "ssd" + elif [[ $hdd -gt 0 ]]; then + echo "hdd" + else + echo "unknown" + fi +} + +determine_optimization_profile() { + local ram_gb=$1 + local cores=$2 + local nvme=$3 + local ssd=$4 + + # High-end system + if [[ $ram_gb -ge 16 && $cores -ge 8 && ($nvme -gt 0 || $ssd -gt 0) ]]; then + echo "aggressive" + # Mid-range system + elif [[ $ram_gb -ge 8 && $cores -ge 4 ]]; then + echo "moderate" + # Low-end system + elif [[ $ram_gb -ge 4 ]]; then + echo "conservative" + # Very low-end system + else + echo "minimal" + fi +} + +# Function to get recommended zram size based on RAM +get_recommended_zram_size() { + local ram_gb=$(free -g | awk '/^Mem:/{print $2}') + + if [[ $ram_gb -ge 32 ]]; then + echo "16G" + elif [[ $ram_gb -ge 16 ]]; then + echo "12G" + elif [[ $ram_gb -ge 8 ]]; then + echo "6G" + elif [[ $ram_gb -ge 4 ]]; then + echo "4G" + else + echo "2G" + fi +} + +# Function to get recommended tmpfs sizes +get_recommended_tmpfs_sizes() { + local ram_gb=$(free -g | awk '/^Mem:/{print $2}') + local profile="$1" + + case "$profile" in + "aggressive") + echo "browser:4G,ide:2G,packages:3G,thumbnails:512M" + ;; + "moderate") + echo "browser:2G,ide:1G,packages:2G,thumbnails:256M" + ;; + "conservative") + echo "browser:1G,ide:512M,packages:1G,thumbnails:128M" + ;; + "minimal") + echo "browser:512M,packages:512M" + ;; + *) + echo "browser:1G,packages:1G" + ;; + esac +} \ No newline at end of file diff --git a/modules/usage-analysis.sh b/modules/usage-analysis.sh new file mode 100755 index 0000000..1390dd2 --- /dev/null +++ b/modules/usage-analysis.sh @@ -0,0 +1,286 @@ +#!/bin/bash +# Usage Analysis Module +# Analyzes file access patterns and cache usage + +analyze_usage_patterns() { + local output_file="${1:-/dev/stdout}" + local analysis_duration="${2:-300}" # 5 minutes default + + log "Analyzing file access patterns (duration: ${analysis_duration}s)..." + + # Create temporary files for analysis + local temp_dir="/tmp/usage-analysis-$$" + mkdir -p "$temp_dir" + + # Start monitoring file access + start_file_access_monitoring "$temp_dir" "$analysis_duration" & + local monitor_pid=$! + + # Analyze current cache usage + analyze_current_cache_usage "$temp_dir" + + # Analyze browser usage + analyze_browser_usage "$temp_dir" + + # Analyze development tools usage + analyze_development_usage "$temp_dir" + + # Wait for file access monitoring to complete + wait $monitor_pid 2>/dev/null || true + + # Compile results + compile_usage_analysis "$temp_dir" "$output_file" + + # Cleanup + rm -rf "$temp_dir" +} + +start_file_access_monitoring() { + local temp_dir="$1" + local duration="$2" + + # Monitor file access using inotifywait if available + if command -v inotifywait >/dev/null 2>&1; then + timeout "$duration" inotifywait -m -r /home --format '%w%f %e' \ + -e access,modify,create,delete \ + 2>/dev/null > "$temp_dir/file_access.log" || true + else + # Fallback: use find to detect recently accessed files + find /home -type f -atime -1 2>/dev/null > "$temp_dir/recent_files.log" || true + fi +} + +analyze_current_cache_usage() { + local temp_dir="$1" + + { + echo "=== CURRENT CACHE ANALYSIS ===" + + # Browser caches + echo "Browser cache sizes:" + find /home -type d \( -name "*cache*" -o -name "*Cache*" \) \ + -path "*/.mozilla/*" -o -path "*/.config/google-chrome/*" \ + -o -path "*/.config/chromium/*" -o -path "*/.cache/mozilla/*" \ + 2>/dev/null | while read -r dir; do + if [[ -d "$dir" ]]; then + size=$(du -sh "$dir" 2>/dev/null | cut -f1) + echo " $dir: $size" + fi + done + + echo "" + echo "System caches:" + + # Package manager caches + [[ -d /var/cache/apt ]] && echo " APT cache: $(du -sh /var/cache/apt 2>/dev/null | cut -f1)" + [[ -d /var/cache/pacman ]] && echo " Pacman cache: $(du -sh /var/cache/pacman 2>/dev/null | cut -f1)" + [[ -d /var/cache/yum ]] && echo " YUM cache: $(du -sh /var/cache/yum 2>/dev/null | cut -f1)" + + # User application caches + find /home -maxdepth 3 -type d -name ".cache" 2>/dev/null | while read -r cache_dir; do + if [[ -d "$cache_dir" ]]; then + size=$(du -sh "$cache_dir" 2>/dev/null | cut -f1) + echo " User cache ($cache_dir): $size" + fi + done + + } > "$temp_dir/cache_analysis.txt" +} + +analyze_browser_usage() { + local temp_dir="$1" + + { + echo "=== BROWSER USAGE ANALYSIS ===" + + # Firefox profiles + find /home -path "*/.mozilla/firefox/*/prefs.js" 2>/dev/null | while read -r prefs_file; do + profile_dir=$(dirname "$prefs_file") + profile_name=$(basename "$profile_dir") + size=$(du -sh "$profile_dir" 2>/dev/null | cut -f1) + last_used=$(stat -c %Y "$prefs_file" 2>/dev/null || echo "0") + last_used_human=$(date -d "@$last_used" 2>/dev/null || echo "unknown") + + echo "Firefox profile: $profile_name" + echo " Size: $size" + echo " Last used: $last_used_human" + echo " Path: $profile_dir" + echo "" + done + + # Chrome/Chromium profiles + find /home -path "*/.config/google-chrome/*/Preferences" -o \ + -path "*/.config/chromium/*/Preferences" 2>/dev/null | while read -r prefs_file; do + profile_dir=$(dirname "$prefs_file") + browser_type=$(echo "$profile_dir" | grep -o -E "(google-chrome|chromium)") + profile_name=$(basename "$profile_dir") + size=$(du -sh "$profile_dir" 2>/dev/null | cut -f1) + last_used=$(stat -c %Y "$prefs_file" 2>/dev/null || echo "0") + last_used_human=$(date -d "@$last_used" 2>/dev/null || echo "unknown") + + echo "$browser_type profile: $profile_name" + echo " Size: $size" + echo " Last used: $last_used_human" + echo " Path: $profile_dir" + echo "" + done + + } > "$temp_dir/browser_analysis.txt" +} + +analyze_development_usage() { + local temp_dir="$1" + + { + echo "=== DEVELOPMENT TOOLS ANALYSIS ===" + + # VS Code + find /home -path "*/.vscode/extensions" -o \ + -path "*/.config/Code/CachedData" 2>/dev/null | while read -r vscode_dir; do + size=$(du -sh "$vscode_dir" 2>/dev/null | cut -f1) + echo "VS Code data: $size ($vscode_dir)" + done + + # Node.js caches + find /home -name "node_modules" -type d 2>/dev/null | head -10 | while read -r node_dir; do + size=$(du -sh "$node_dir" 2>/dev/null | cut -f1) + echo "Node modules: $size ($node_dir)" + done + + # Python caches + find /home -name "__pycache__" -type d 2>/dev/null | wc -l | xargs echo "Python cache directories:" + + # Docker (if accessible) + if [[ -d /var/lib/docker ]] && command -v docker >/dev/null 2>&1; then + docker_size=$(du -sh /var/lib/docker 2>/dev/null | cut -f1 || echo "unknown") + echo "Docker data: $docker_size" + fi + + # Git repositories + find /home -name ".git" -type d 2>/dev/null | wc -l | xargs echo "Git repositories found:" + + } > "$temp_dir/development_analysis.txt" +} + +compile_usage_analysis() { + local temp_dir="$1" + local output_file="$2" + + # Calculate recommendations based on analysis + local total_browser_cache=0 + local total_dev_cache=0 + local total_system_cache=0 + + # Parse cache sizes and convert to MB for calculations + if [[ -f "$temp_dir/cache_analysis.txt" ]]; then + total_browser_cache=$(grep -E "(firefox|chrome|chromium)" "$temp_dir/cache_analysis.txt" | \ + grep -oE "[0-9.]+[KMG]" | sed 's/G/*1024/g;s/M/*1/g;s/K\/1024/g' | bc -l 2>/dev/null | \ + awk '{sum+=$1} END {print int(sum)}' || echo "0") + fi + + cat > "$output_file" << EOF +{ + "analysis_timestamp": "$(date -Iseconds)", + "cache_usage": { + "browser_cache_mb": $total_browser_cache, + "development_cache_mb": $total_dev_cache, + "system_cache_mb": $total_system_cache + }, + "recommendations": { + "browser_tmpfs_size": "$(recommend_browser_tmpfs_size $total_browser_cache)", + "development_tmpfs_size": "$(recommend_dev_tmpfs_size $total_dev_cache)", + "priority_directories": $(generate_priority_directories "$temp_dir") + }, + "frequent_paths": $(analyze_frequent_paths "$temp_dir"), + "optimization_score": $(calculate_optimization_potential "$temp_dir") +} +EOF +} + +recommend_browser_tmpfs_size() { + local current_mb=$1 + + if [[ $current_mb -gt 2048 ]]; then + echo "4G" + elif [[ $current_mb -gt 1024 ]]; then + echo "2G" + elif [[ $current_mb -gt 512 ]]; then + echo "1G" + else + echo "512M" + fi +} + +recommend_dev_tmpfs_size() { + local current_mb=$1 + + if [[ $current_mb -gt 1024 ]]; then + echo "2G" + elif [[ $current_mb -gt 512 ]]; then + echo "1G" + else + echo "512M" + fi +} + +generate_priority_directories() { + local temp_dir="$1" + + # Generate JSON array of priority directories for tmpfs + cat << 'EOF' +[ + {"path": "/var/cache/apt", "type": "package_cache", "priority": "high"}, + {"path": "~/.cache", "type": "user_cache", "priority": "medium"}, + {"path": "~/.mozilla/firefox/*/storage", "type": "browser_storage", "priority": "high"}, + {"path": "~/.config/google-chrome/*/storage", "type": "browser_storage", "priority": "high"}, + {"path": "~/.vscode/extensions", "type": "ide_extensions", "priority": "medium"} +] +EOF +} + +analyze_frequent_paths() { + local temp_dir="$1" + + if [[ -f "$temp_dir/file_access.log" ]]; then + # Parse inotify log to find most accessed paths + awk '{print $1}' "$temp_dir/file_access.log" | \ + sort | uniq -c | sort -nr | head -10 | \ + jq -R -s 'split("\n") | map(select(length > 0)) | map(split(" ") | {count: .[0], path: .[1]})' + else + echo "[]" + fi +} + +calculate_optimization_potential() { + local temp_dir="$1" + local score=0 + + # Base score calculation + local ram_gb=$(free -g | awk '/^Mem:/{print $2}') + + # More RAM = higher potential + if [[ $ram_gb -gt 16 ]]; then + score=$((score + 40)) + elif [[ $ram_gb -gt 8 ]]; then + score=$((score + 30)) + else + score=$((score + 20)) + fi + + # Check for existing optimizations + if mount | grep -q "tmpfs.*cache"; then + score=$((score + 10)) + fi + + if [[ -e /dev/zram0 ]]; then + score=$((score + 15)) + fi + + # Check for large caches that could benefit from tmpfs + if [[ -f "$temp_dir/cache_analysis.txt" ]]; then + local large_caches=$(grep -c "[0-9][0-9][0-9]M\|[0-9]G" "$temp_dir/cache_analysis.txt" 2>/dev/null || echo "0") + score=$((score + large_caches * 5)) + fi + + echo $score +} \ No newline at end of file diff --git a/monitor.sh b/monitor.sh new file mode 100755 index 0000000..00d4524 --- /dev/null +++ b/monitor.sh @@ -0,0 +1,426 @@ +#!/bin/bash +# System Monitoring and Health Check +# Part of Linux System Tuning Suite + +set -euo pipefail + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +LOG_DIR="/var/log/system-tuning" +METRICS_FILE="$LOG_DIR/metrics.log" + +# Colors +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +BLUE='\033[0;34m' +NC='\033[0m' + +log() { + echo -e "${BLUE}[$(date '+%H:%M:%S')]${NC} $1" +} + +warn() { + echo -e "${YELLOW}[WARNING]${NC} $1" +} + +error() { + echo -e "${RED}[ERROR]${NC} $1" +} + +success() { + echo -e "${GREEN}[SUCCESS]${NC} $1" +} + +show_usage() { + cat << EOF +System Monitoring Tool + +Usage: $0 [OPTIONS] [MODE] + +OPTIONS: + -h, --help Show this help message + -l, --log Log metrics to file + -d, --duration SEC Monitoring duration in seconds (default: continuous) + +MODES: + status Show current status (default) + live Live monitoring with updates + benchmark Run performance benchmarks + health Health check of optimizations + compare Compare performance before/after + export Export metrics for external analysis + +EXAMPLES: + $0 # Show current status + $0 live # Live monitoring + $0 health # Health check + $0 benchmark # Run benchmarks + +EOF +} + +setup_logging() { + if [[ ! -d "$LOG_DIR" ]]; then + sudo mkdir -p "$LOG_DIR" + sudo chown $USER:$USER "$LOG_DIR" 2>/dev/null || true + fi +} + +collect_metrics() { + local timestamp=$(date '+%Y-%m-%d %H:%M:%S') + + # Memory metrics + local mem_info=$(free -m | awk '/^Mem:/{printf "total:%s,used:%s,free:%s,available:%s", $2,$3,$4,$7}') + local swap_info=$(free -m | awk '/^Swap:/{printf "total:%s,used:%s,free:%s", $2,$3,$4}') + + # zram metrics + local zram_info="" + if [[ -e /dev/zram0 ]]; then + local zram_size=$(cat /sys/block/zram0/disksize 2>/dev/null || echo "0") + local zram_used=$(cat /sys/block/zram0/compr_data_size 2>/dev/null || echo "0") + local zram_orig=$(cat /sys/block/zram0/orig_data_size 2>/dev/null || echo "0") + zram_info="size:$zram_size,used:$zram_used,orig:$zram_orig" + fi + + # tmpfs metrics + local tmpfs_count=$(mount -t tmpfs | wc -l) + local tmpfs_total=$(df -t tmpfs --total | tail -1 | awk '{print $2}' 2>/dev/null || echo "0") + local tmpfs_used=$(df -t tmpfs --total | tail -1 | awk '{print $3}' 2>/dev/null || echo "0") + + # System load + local load_avg=$(uptime | awk -F'load average:' '{print $2}' | sed 's/^ *//') + + # I/O stats + local io_stats="" + if command -v iostat >/dev/null 2>&1; then + io_stats=$(iostat -d 1 2 | tail -n +4 | awk 'NR>1{tps+=$2; read+=$3; write+=$4} END{printf "tps:%.2f,read:%.2f,write:%.2f", tps, read, write}') + fi + + cat << EOF +{ + "timestamp": "$timestamp", + "memory": {$mem_info}, + "swap": {$swap_info}, + "zram": {$zram_info}, + "tmpfs": {"count": $tmpfs_count, "total_kb": $tmpfs_total, "used_kb": $tmpfs_used}, + "load": "$load_avg", + "io": {$io_stats} +} +EOF +} + +show_status() { + echo "🚀 System Tuning Status" + echo "=======================" + echo "" + + # Memory overview + echo "💾 Memory Overview:" + free -h | while IFS= read -r line; do + echo " $line" + done + echo "" + + # zram status + echo "🔄 Compression (zram):" + if [[ -e /dev/zram0 ]]; then + if command -v zramctl >/dev/null 2>&1; then + zramctl | while IFS= read -r line; do + echo " $line" + done + else + local zram_size=$(cat /sys/block/zram0/disksize 2>/dev/null) + local zram_used=$(cat /sys/block/zram0/compr_data_size 2>/dev/null) + echo " Size: $((zram_size / 1024 / 1024 / 1024))GB" + echo " Used: $((zram_used / 1024 / 1024))MB" + fi + else + echo " Not configured" + fi + echo "" + + # tmpfs overview + echo "📁 tmpfs Filesystems:" + df -h -t tmpfs | while IFS= read -r line; do + echo " $line" + done + echo "" + + # Kernel parameters + echo "⚙️ Key Kernel Parameters:" + echo " Swappiness: $(cat /proc/sys/vm/swappiness)" + echo " Dirty ratio: $(cat /proc/sys/vm/dirty_ratio)" + echo " Dirty background ratio: $(cat /proc/sys/vm/dirty_background_ratio)" + echo " VFS cache pressure: $(cat /proc/sys/vm/vfs_cache_pressure)" + echo "" + + # Service status + echo "🔧 Services:" + if systemctl is-enabled system-tuning.service >/dev/null 2>&1; then + echo " System tuning service: ✅ ENABLED" + else + echo " System tuning service: ❌ DISABLED" + fi + + # Performance score + echo "" + echo "📊 Performance Score: $(calculate_performance_score)/100" +} + +live_monitoring() { + local duration=${1:-0} + local count=0 + + echo "📊 Live System Monitoring" + echo "========================" + echo "Press Ctrl+C to stop" + echo "" + + while true; do + clear + echo "🔄 Live Monitor - $(date) (Update #$((++count)))" + echo "==================================================" + echo "" + + # Real-time metrics + echo "Memory Usage:" + free -h | head -2 + echo "" + + echo "Top tmpfs by usage:" + df -h -t tmpfs | sort -k5 -nr | head -5 | while IFS= read -r line; do + echo " $line" + done + echo "" + + echo "zram compression ratio:" + if [[ -e /dev/zram0 ]]; then + local orig=$(cat /sys/block/zram0/orig_data_size 2>/dev/null || echo "0") + local compr=$(cat /sys/block/zram0/compr_data_size 2>/dev/null || echo "0") + if [[ $orig -gt 0 && $compr -gt 0 ]]; then + local ratio=$(echo "scale=2; $orig / $compr" | bc -l 2>/dev/null || echo "N/A") + echo " Compression: ${ratio}:1" + echo " Original: $((orig / 1024 / 1024))MB" + echo " Compressed: $((compr / 1024 / 1024))MB" + else + echo " No compression data available" + fi + else + echo " zram not active" + fi + echo "" + + echo "System Load: $(uptime | awk -F'load average:' '{print $2}')" + + # Log metrics if enabled + if [[ -f "$METRICS_FILE" ]]; then + collect_metrics >> "$METRICS_FILE" + fi + + sleep 2 + + # Exit if duration specified and reached + if [[ $duration -gt 0 && $count -ge $duration ]]; then + break + fi + done +} + +run_benchmark() { + echo "🏁 Performance Benchmark" + echo "========================" + echo "" + + log "Running memory performance tests..." + + # Memory speed test + echo "Memory Performance:" + if command -v dd >/dev/null 2>&1; then + echo " Write test (1GB to tmpfs):" + time (dd if=/dev/zero of=/tmp/benchmark-test bs=1M count=1024 2>/dev/null && sync) + rm -f /tmp/benchmark-test + echo "" + fi + + # Application startup test + echo "Application Startup Test:" + if command -v time >/dev/null 2>&1; then + echo " Shell startup:" + time bash -c "exit" 2>&1 | grep real || echo " Could not measure" + + if command -v python3 >/dev/null 2>&1; then + echo " Python startup:" + time python3 -c "pass" 2>&1 | grep real || echo " Could not measure" + fi + fi + echo "" + + # I/O performance + if command -v iostat >/dev/null 2>&1; then + echo "Current I/O performance:" + iostat -x 1 1 | tail -n +4 + fi + echo "" + + success "Benchmark completed" +} + +health_check() { + echo "🏥 System Health Check" + echo "=====================" + echo "" + + local issues=0 + local warnings=0 + + # Check zram + if [[ -e /dev/zram0 ]]; then + if swapon --show | grep -q zram0; then + success "zram swap is active" + else + error "zram device exists but swap is not active" + ((issues++)) + fi + else + warn "zram not configured" + ((warnings++)) + fi + + # Check tmpfs mounts + local tmpfs_count=$(mount -t tmpfs | wc -l) + if [[ $tmpfs_count -gt 5 ]]; then + success "Multiple tmpfs mounts detected ($tmpfs_count)" + else + warn "Few tmpfs mounts detected ($tmpfs_count) - consider more optimizations" + ((warnings++)) + fi + + # Check memory usage + local mem_usage=$(free | awk '/^Mem:/{printf "%.0f", $3/$2*100}') + if [[ $mem_usage -lt 80 ]]; then + success "Memory usage is healthy ($mem_usage%)" + else + warn "High memory usage ($mem_usage%) - monitor for performance impact" + ((warnings++)) + fi + + # Check swap usage + local swap_usage=$(free | awk '/^Swap:/{if($2>0) printf "%.0f", $3/$2*100; else print "0"}') + if [[ $swap_usage -lt 50 ]]; then + success "Swap usage is reasonable ($swap_usage%)" + else + warn "High swap usage ($swap_usage%) - consider adding more RAM" + ((warnings++)) + fi + + # Check service status + if systemctl is-active system-tuning.service >/dev/null 2>&1; then + success "System tuning service is running" + else + warn "System tuning service is not running" + ((warnings++)) + fi + + echo "" + echo "Health Summary:" + echo " Issues: $issues" + echo " Warnings: $warnings" + + if [[ $issues -eq 0 && $warnings -eq 0 ]]; then + success "System is optimally configured! 🎉" + elif [[ $issues -eq 0 ]]; then + warn "System is mostly optimized with $warnings minor warnings" + else + error "System has $issues issues that need attention" + fi +} + +calculate_performance_score() { + local score=0 + + # Base score + score=30 + + # zram bonus + [[ -e /dev/zram0 ]] && score=$((score + 20)) + + # tmpfs bonus + local tmpfs_count=$(mount -t tmpfs | wc -l) + if [[ $tmpfs_count -gt 8 ]]; then + score=$((score + 25)) + elif [[ $tmpfs_count -gt 5 ]]; then + score=$((score + 15)) + fi + + # Kernel parameter optimization + local swappiness=$(cat /proc/sys/vm/swappiness) + [[ $swappiness -le 10 ]] && score=$((score + 10)) + + # Service bonus + systemctl is-enabled system-tuning.service >/dev/null 2>&1 && score=$((score + 15)) + + echo $score +} + +main() { + local mode="status" + local log_metrics=false + local duration=0 + + # Parse arguments + while [[ $# -gt 0 ]]; do + case $1 in + -h|--help) + show_usage + exit 0 + ;; + -l|--log) + log_metrics=true + shift + ;; + -d|--duration) + duration="$2" + shift 2 + ;; + status|live|benchmark|health|compare|export) + mode="$1" + shift + ;; + *) + error "Unknown option: $1" + show_usage + exit 1 + ;; + esac + done + + # Setup logging if requested + if [[ "$log_metrics" == "true" ]]; then + setup_logging + fi + + # Execute requested mode + case "$mode" in + status) + show_status + ;; + live) + live_monitoring "$duration" + ;; + benchmark) + run_benchmark + ;; + health) + health_check + ;; + *) + error "Mode '$mode' not implemented yet" + exit 1 + ;; + esac +} + +# Run if called directly +if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then + main "$@" +fi \ No newline at end of file diff --git a/profiles/desktop.json b/profiles/desktop.json new file mode 100644 index 0000000..a1aaf32 --- /dev/null +++ b/profiles/desktop.json @@ -0,0 +1,81 @@ +{ + "_comment": "Desktop/Workstation Optimization Profile - Optimized for general desktop use with focus on responsiveness", + "profile_name": "desktop", + "description": "General desktop optimization for workstations", + "target_systems": [ + "Desktop computers", + "Workstations", + "General purpose laptops" + ], + "requirements": { + "min_ram_gb": 4, + "recommended_ram_gb": 8 + }, + "optimizations": { + "zram": { + "enabled": true, + "size_formula": "min(ram_gb * 0.75, 12)G", + "compression_algorithm": "lz4" + }, + "tmpfs": { + "browser_cache": { + "enabled": true, + "size": "auto", + "paths": [ + "/tmp/tmpfs-cache/browser" + ] + }, + "ide_cache": { + "enabled": true, + "size": "1G", + "paths": [ + "/tmp/tmpfs-cache/vscode", + "/tmp/tmpfs-cache/jetbrains" + ] + }, + "package_cache": { + "enabled": true, + "size": "2G", + "bind_mounts": [ + "/var/cache/apt", + "/var/cache/pacman/pkg" + ] + }, + "thumbnails": { + "enabled": true, + "size": "256M", + "paths": [ + "/tmp/tmpfs-cache/thumbnails" + ] + } + }, + "kernel_parameters": { + "vm.swappiness": 5, + "vm.dirty_ratio": 5, + "vm.dirty_background_ratio": 2, + "vm.vfs_cache_pressure": 50, + "vm.page-cluster": 0, + "net.core.netdev_max_backlog": 5000, + "net.core.rmem_max": 16777216, + "net.core.wmem_max": 16777216 + }, + "overlayfs": { + "enabled": false, + "protect_configs": false + } + }, + "sizing_rules": { + "browser_cache": { + "ram_4gb": "512M", + "ram_8gb": "1G", + "ram_16gb": "2G", + "ram_32gb": "4G" + }, + "zram_size": { + "ram_4gb": "3G", + "ram_8gb": "6G", + "ram_16gb": "12G", + "ram_32gb": "16G" + } + } +} \ No newline at end of file diff --git a/profiles/development.json b/profiles/development.json new file mode 100644 index 0000000..995c39b --- /dev/null +++ b/profiles/development.json @@ -0,0 +1,76 @@ +{ + "_comment": "Development Workstation Profile - Optimized for software development with large projects", + "profile_name": "development", + "description": "Development-focused optimization for IDEs and build tools", + "target_systems": [ + "Development workstations", + "DevOps machines", + "CI/CD systems" + ], + "requirements": { + "min_ram_gb": 8, + "recommended_ram_gb": 32 + }, + "optimizations": { + "zram": { + "enabled": true, + "size_formula": "min(ram_gb * 0.8, 16)G", + "compression_algorithm": "zstd" + }, + "tmpfs": { + "build_cache": { + "enabled": true, + "size": "8G", + "paths": [ + "/tmp/tmpfs-cache/build", + "/tmp/tmpfs-cache/ccache" + ] + }, + "ide_cache": { + "enabled": true, + "size": "4G", + "paths": [ + "/tmp/tmpfs-cache/vscode", + "/tmp/tmpfs-cache/jetbrains", + "/tmp/tmpfs-cache/eclipse" + ] + }, + "package_cache": { + "enabled": true, + "size": "4G", + "bind_mounts": [ + "/var/cache/apt", + "/var/cache/pacman/pkg", + "/root/.cache/pip" + ] + }, + "node_modules": { + "enabled": true, + "size": "6G", + "paths": ["/tmp/tmpfs-cache/node_modules"] + } + }, + "kernel_parameters": { + "vm.swappiness": 5, + "vm.dirty_ratio": 10, + "vm.dirty_background_ratio": 5, + "vm.vfs_cache_pressure": 50, + "fs.file-max": 2097152, + "fs.inotify.max_user_watches": 524288, + "kernel.pid_max": 32768 + }, + "overlayfs": { + "enabled": true, + "protect_configs": true, + "overlay_paths": [ + "/home/*/workspace", + "/opt/projects" + ] + } + }, + "development_specific": { + "docker_optimization": true, + "git_optimization": true, + "compiler_cache": true + } +} \ No newline at end of file diff --git a/profiles/gaming.json b/profiles/gaming.json new file mode 100644 index 0000000..7b9ea9e --- /dev/null +++ b/profiles/gaming.json @@ -0,0 +1,64 @@ +{ + "_comment": "Gaming Optimization Profile - Optimized for gaming performance with low latency", + "profile_name": "gaming", + "description": "Gaming-focused optimization for maximum performance", + "target_systems": [ + "Gaming desktops", + "High-performance laptops", + "Streaming setups" + ], + "requirements": { + "min_ram_gb": 8, + "recommended_ram_gb": 16 + }, + "optimizations": { + "zram": { + "enabled": true, + "size_formula": "min(ram_gb * 0.5, 8)G", + "compression_algorithm": "lz4" + }, + "tmpfs": { + "game_cache": { + "enabled": true, + "size": "4G", + "paths": [ + "/tmp/tmpfs-cache/steam", + "/tmp/tmpfs-cache/games" + ] + }, + "browser_cache": { + "enabled": true, + "size": "1G", + "paths": ["/tmp/tmpfs-cache/browser"] + }, + "shader_cache": { + "enabled": true, + "size": "2G", + "paths": ["/tmp/tmpfs-cache/shaders"] + } + }, + "kernel_parameters": { + "vm.swappiness": 1, + "vm.dirty_ratio": 3, + "vm.dirty_background_ratio": 1, + "vm.vfs_cache_pressure": 40, + "vm.page-cluster": 0, + "kernel.sched_autogroup_enabled": 0, + "kernel.sched_child_runs_first": 1, + "net.core.netdev_max_backlog": 10000, + "net.core.rmem_max": 33554432, + "net.core.wmem_max": 33554432 + }, + "overlayfs": { + "enabled": false + } + }, + "gaming_specific": { + "cpu_governor": "performance", + "disable_services": [ + "bluetooth", + "cups" + ], + "priority_adjustments": true + } +} \ No newline at end of file diff --git a/system-analyzer.sh b/system-analyzer.sh new file mode 100755 index 0000000..fb11aaa --- /dev/null +++ b/system-analyzer.sh @@ -0,0 +1,251 @@ +#!/bin/bash +# System Analyzer - Hardware Detection and Usage Analysis +# Part of Linux System Tuning Suite + +set -euo pipefail + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +MODULES_DIR="$SCRIPT_DIR/modules" +ANALYSIS_DIR="/tmp/system-analysis-$(date +%Y%m%d-%H%M%S)" + +# Colors for output +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +BLUE='\033[0;34m' +NC='\033[0m' # No Color + +log() { + echo -e "${BLUE}[$(date '+%H:%M:%S')]${NC} $1" +} + +warn() { + echo -e "${YELLOW}[WARNING]${NC} $1" +} + +error() { + echo -e "${RED}[ERROR]${NC} $1" +} + +success() { + echo -e "${GREEN}[SUCCESS]${NC} $1" +} + +# Check if running as root +check_root() { + if [[ $EUID -ne 0 ]]; then + error "This script must be run as root for complete analysis" + echo "Usage: sudo $0" + exit 1 + fi +} + +# Create analysis directory +setup_analysis_dir() { + mkdir -p "$ANALYSIS_DIR" + log "Analysis directory created: $ANALYSIS_DIR" +} + +# Load modules +load_modules() { + for module in "$MODULES_DIR"/*.sh; do + if [[ -f "$module" ]]; then + source "$module" + log "Loaded module: $(basename "$module")" + fi + done +} + +# Main analysis function +run_analysis() { + log "Starting comprehensive system analysis..." + + echo "=== SYSTEM ANALYSIS REPORT ===" > "$ANALYSIS_DIR/report.txt" + echo "Generated: $(date)" >> "$ANALYSIS_DIR/report.txt" + echo "Hostname: $(hostname)" >> "$ANALYSIS_DIR/report.txt" + echo "" >> "$ANALYSIS_DIR/report.txt" + + # Hardware detection + log "Analyzing hardware configuration..." + detect_hardware > "$ANALYSIS_DIR/hardware.json" + + # Memory analysis + log "Analyzing memory usage patterns..." + analyze_memory > "$ANALYSIS_DIR/memory.json" + + # Storage analysis + log "Analyzing storage configuration..." + analyze_storage > "$ANALYSIS_DIR/storage.json" + + # Usage pattern analysis + log "Analyzing file access patterns (this may take a moment)..." + analyze_usage_patterns > "$ANALYSIS_DIR/usage.json" + + # Current optimizations + log "Checking existing optimizations..." + check_current_optimizations > "$ANALYSIS_DIR/current.json" + + # Generate recommendations + log "Generating optimization recommendations..." + generate_recommendations > "$ANALYSIS_DIR/recommendations.json" + + success "Analysis complete! Results saved to: $ANALYSIS_DIR" +} + +# Display summary +show_summary() { + echo "" + echo "=== ANALYSIS SUMMARY ===" + + local ram_gb=$(free -g | awk '/^Mem:/{print $2}') + local cpu_cores=$(nproc) + local disk_type=$(lsblk -d -o name,rota | awk '$2==0{print "SSD"} $2==1{print "HDD"}' | head -1) + + echo "💻 Hardware Overview:" + echo " RAM: ${ram_gb}GB" + echo " CPU Cores: $cpu_cores" + echo " Primary Storage: ${disk_type:-Unknown}" + + if [[ -f "$ANALYSIS_DIR/recommendations.json" ]]; then + echo "" + echo "🎯 Top Recommendations:" + jq -r '.recommendations[] | " • " + .description' "$ANALYSIS_DIR/recommendations.json" 2>/dev/null | head -5 || { + echo " Run ./tune-system.sh --analyze for detailed recommendations" + } + fi + + echo "" + echo "📊 Next Steps:" + echo " 1. Review full report: cat $ANALYSIS_DIR/report.txt" + echo " 2. Apply optimizations: sudo ./tune-system.sh --auto" + echo " 3. Monitor performance: ./monitor.sh" +} + +main() { + check_root + setup_analysis_dir + + # Load modules if they exist + if [[ -d "$MODULES_DIR" ]]; then + load_modules + else + warn "Modules directory not found. Using built-in functions." + fi + + run_analysis + show_summary +} + +# Built-in analysis functions (if modules not available) +detect_hardware() { + cat << EOF +{ + "ram": { + "total_gb": $(free -g | awk '/^Mem:/{print $2}'), + "total_bytes": $(free -b | awk '/^Mem:/{print $2}'), + "available_gb": $(free -g | awk '/^Mem:/{print $7}'), + "used_percent": $(free | awk '/^Mem:/{printf "%.1f", $3/$2*100}') + }, + "cpu": { + "cores": $(nproc), + "model": "$(lscpu | grep 'Model name:' | sed 's/Model name:[[:space:]]*//' | tr -d '\n')", + "architecture": "$(uname -m)" + }, + "storage": $(lsblk -J -o NAME,SIZE,TYPE,MOUNTPOINT,ROTA 2>/dev/null || echo '{"blockdevices":[]}') +} +EOF +} + +analyze_memory() { + cat << EOF +{ + "current_usage": $(free -j 2>/dev/null || free | awk '/^Mem:/{printf "{\"total\":%s,\"used\":%s,\"free\":%s,\"available\":%s}", $2, $3, $4, $7}'), + "swap": $(free | awk '/^Swap:/{printf "{\"total\":%s,\"used\":%s,\"free\":%s}", $2, $3, $4}'), + "tmpfs_mounts": $(df -t tmpfs --output=target,size,used,avail | tail -n +2 | jq -R -s 'split("\n") | map(select(length > 0)) | map(split(" ") | {target: .[0], size: .[1], used: .[2], available: .[3]})') +} +EOF +} + +analyze_storage() { + cat << EOF +{ + "filesystems": $(df -h --output=source,fstype,size,used,avail,pcent,target | tail -n +2 | jq -R -s 'split("\n") | map(select(length > 0)) | map(split(" ") | select(length >= 7) | {device: .[0], type: .[1], size: .[2], used: .[3], available: .[4], percent: .[5], mount: .[6]})'), + "block_devices": $(lsblk -J 2>/dev/null || echo '{"blockdevices":[]}') +} +EOF +} + +analyze_usage_patterns() { + # Analyze frequently accessed directories/files + cat << EOF +{ + "large_cache_dirs": [ +$(find /home -name ".cache" -type d 2>/dev/null | while read dir; do + size=$(du -sh "$dir" 2>/dev/null | cut -f1 || echo "0") + echo " {\"path\": \"$dir\", \"size\": \"$size\"}," +done | sed '$s/,$//') + ], + "browser_profiles": [ +$(find /home -path "*/.mozilla/firefox/*/storage" -o -path "*/.config/google-chrome/*/storage*" -o -path "*/.config/chromium/*/storage*" 2>/dev/null | while read dir; do + size=$(du -sh "$(dirname "$dir")" 2>/dev/null | cut -f1 || echo "0") + echo " {\"path\": \"$(dirname "$dir")\", \"type\": \"browser\", \"size\": \"$size\"}," +done | sed '$s/,$//') + ] +} +EOF +} + +check_current_optimizations() { + cat << EOF +{ + "zram": $(zramctl -J 2>/dev/null || echo '[]'), + "tmpfs_count": $(mount -t tmpfs | wc -l), + "kernel_params": { + "swappiness": $(cat /proc/sys/vm/swappiness), + "dirty_ratio": $(cat /proc/sys/vm/dirty_ratio), + "dirty_background_ratio": $(cat /proc/sys/vm/dirty_background_ratio), + "vfs_cache_pressure": $(cat /proc/sys/vm/vfs_cache_pressure) + } +} +EOF +} + +generate_recommendations() { + local ram_gb=$(free -g | awk '/^Mem:/{print $2}') + local has_zram=$(zramctl 2>/dev/null | grep -q zram && echo "true" || echo "false") + + cat << EOF +{ + "recommendations": [ + { + "priority": "high", + "category": "memory", + "description": "Configure zram compression (current: $has_zram)", + "command": "./tune-system.sh --enable-zram" + }, + { + "priority": "high", + "category": "tmpfs", + "description": "Set up tmpfs for browser cache", + "command": "./tune-system.sh --enable-tmpfs-cache" + }, + { + "priority": "medium", + "category": "kernel", + "description": "Optimize kernel parameters for desktop", + "command": "./tune-system.sh --tune-kernel" + } + ], + "system_score": { + "current": 65, + "potential": 85, + "improvement": "+20 points" + } +} +EOF +} + +# Run if called directly +if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then + main "$@" +fi \ No newline at end of file diff --git a/tune-system.sh b/tune-system.sh new file mode 100755 index 0000000..a6b2189 --- /dev/null +++ b/tune-system.sh @@ -0,0 +1,511 @@ +#!/bin/bash +# Linux System Tuning Suite - Main Orchestrator +# Intelligent system optimization based on hardware and usage analysis + +set -euo pipefail + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +MODULES_DIR="$SCRIPT_DIR/modules" +PROFILES_DIR="$SCRIPT_DIR/profiles" +CONFIG_DIR="$SCRIPT_DIR/configs" +BACKUP_DIR="/var/lib/system-tuning/backups" + +# Colors +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +BLUE='\033[0;34m' +NC='\033[0m' + +# Global variables +DRY_RUN=false +VERBOSE=false +AUTO_MODE=false +PROFILE="" +FORCE=false + +log() { + echo -e "${BLUE}[$(date '+%H:%M:%S')]${NC} $1" +} + +warn() { + echo -e "${YELLOW}[WARNING]${NC} $1" +} + +error() { + echo -e "${RED}[ERROR]${NC} $1" +} + +success() { + echo -e "${GREEN}[SUCCESS]${NC} $1" +} + +show_usage() { + cat << EOF +Linux System Tuning Suite + +Usage: $0 [OPTIONS] [ACTIONS] + +OPTIONS: + -h, --help Show this help message + -v, --verbose Enable verbose output + -n, --dry-run Show what would be done without making changes + -f, --force Force operations without confirmation + -p, --profile NAME Use specific optimization profile + +ACTIONS: + --analyze Run system analysis only + --auto Automatic optimization based on system analysis + --enable-zram Configure zram compression + --enable-tmpfs Set up tmpfs optimizations + --tune-kernel Optimize kernel parameters + --create-service Install systemd service for persistent optimizations + --benchmark Run performance benchmarks + --rollback Restore previous configuration + --status Show current optimization status + +PROFILES: + desktop Desktop/workstation optimization (default) + server Server optimization + gaming Gaming-focused optimization + development Development workstation optimization + minimal Minimal safe optimizations + +EXAMPLES: + $0 --analyze # Analyze system only + $0 --auto # Automatic optimization + $0 --profile gaming --auto # Gaming-optimized setup + $0 --dry-run --auto # Show what would be done + $0 --enable-zram --enable-tmpfs # Specific optimizations + +EOF +} + +check_root() { + if [[ $EUID -ne 0 ]]; then + error "This script must be run as root" + echo "Usage: sudo $0 [options]" + exit 1 + fi +} + +setup_directories() { + mkdir -p "$BACKUP_DIR" + mkdir -p /var/lib/system-tuning/configs + mkdir -p /var/lib/system-tuning/logs +} + +load_modules() { + for module in "$MODULES_DIR"/*.sh; do + if [[ -f "$module" ]]; then + source "$module" + [[ "$VERBOSE" == "true" ]] && log "Loaded module: $(basename "$module")" + fi + done +} + +create_backup() { + local backup_name="backup-$(date +%Y%m%d-%H%M%S)" + local backup_path="$BACKUP_DIR/$backup_name" + + mkdir -p "$backup_path" + + log "Creating system backup..." + + # Backup important configs + [[ -f /etc/sysctl.conf ]] && cp /etc/sysctl.conf "$backup_path/" + [[ -f /etc/fstab ]] && cp /etc/fstab "$backup_path/" + + # Save current state + free -h > "$backup_path/memory-before.txt" + mount > "$backup_path/mounts-before.txt" + sysctl -a > "$backup_path/sysctl-before.txt" 2>/dev/null + + echo "$backup_name" > /var/lib/system-tuning/last-backup + success "Backup created: $backup_path" +} + +analyze_system() { + log "Running system analysis..." + + if [[ -f "$SCRIPT_DIR/system-analyzer.sh" ]]; then + bash "$SCRIPT_DIR/system-analyzer.sh" + else + error "System analyzer not found" + return 1 + fi +} + +auto_optimize() { + log "Starting automatic optimization..." + + # Run analysis first + analyze_system + + # Determine optimal configuration based on hardware + local ram_gb=$(free -g | awk '/^Mem:/{print $2}') + local cpu_cores=$(nproc) + + log "Detected: ${ram_gb}GB RAM, ${cpu_cores} CPU cores" + + # Apply optimizations based on available RAM + if [[ $ram_gb -ge 16 ]]; then + log "High-memory system detected (≥16GB) - applying aggressive optimizations" + enable_zram "12G" + enable_tmpfs_cache "large" + tune_kernel_params "desktop-high-memory" + elif [[ $ram_gb -ge 8 ]]; then + log "Medium-memory system detected (8-15GB) - applying moderate optimizations" + enable_zram "6G" + enable_tmpfs_cache "medium" + tune_kernel_params "desktop" + elif [[ $ram_gb -ge 4 ]]; then + log "Low-memory system detected (4-7GB) - applying conservative optimizations" + enable_zram "4G" + enable_tmpfs_cache "small" + tune_kernel_params "desktop-low-memory" + else + warn "Very low memory system (<4GB) - applying minimal optimizations only" + enable_zram "2G" + tune_kernel_params "minimal" + fi + + create_systemd_service + success "Automatic optimization complete!" +} + +enable_zram() { + local size=${1:-"8G"} + log "Configuring zram with size: $size" + + if [[ "$DRY_RUN" == "true" ]]; then + echo "[DRY RUN] Would configure zram with size $size" + return + fi + + # Check if zram module exists + if ! modinfo zram >/dev/null 2>&1; then + error "zram module not available" + return 1 + fi + + # Configure zram + if [[ -e /dev/zram0 ]]; then + swapoff /dev/zram0 2>/dev/null || true + echo 1 > /sys/class/zram-control/hot_remove 2>/dev/null || true + fi + + modprobe zram num_devices=1 + echo "$size" > /sys/block/zram0/disksize + mkswap /dev/zram0 + swapon /dev/zram0 + + success "zram configured with $size" +} + +enable_tmpfs_cache() { + local profile=${1:-"medium"} + log "Setting up tmpfs cache optimization (profile: $profile)" + + if [[ "$DRY_RUN" == "true" ]]; then + echo "[DRY RUN] Would set up tmpfs cache with profile: $profile" + return + fi + + # Create tmpfs directories + mkdir -p /tmp/tmpfs-cache/{browser,ide,packages,thumbnails} + + 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 + ;; + "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 + ;; + "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 + ;; + esac + + # Bind mount package cache + if [[ -d /var/cache/apt ]]; then + mount --bind /tmp/tmpfs-cache/packages /var/cache/apt + fi + + success "tmpfs cache optimization enabled" +} + +tune_kernel_params() { + local profile=${1:-"desktop"} + log "Tuning kernel parameters (profile: $profile)" + + if [[ "$DRY_RUN" == "true" ]]; then + echo "[DRY RUN] Would tune kernel parameters with profile: $profile" + return + fi + + local sysctl_conf="/etc/sysctl.d/99-system-tuning.conf" + + cat > "$sysctl_conf" << EOF +# System Tuning - Generated $(date) +# Profile: $profile + +EOF + + case "$profile" in + "desktop-high-memory") + cat >> "$sysctl_conf" << EOF +# High-memory desktop optimization +vm.swappiness = 1 +vm.dirty_ratio = 3 +vm.dirty_background_ratio = 1 +vm.vfs_cache_pressure = 40 +vm.page-cluster = 0 +EOF + ;; + "desktop") + cat >> "$sysctl_conf" << EOF +# Desktop optimization +vm.swappiness = 5 +vm.dirty_ratio = 5 +vm.dirty_background_ratio = 2 +vm.vfs_cache_pressure = 50 +vm.page-cluster = 0 +EOF + ;; + "desktop-low-memory") + cat >> "$sysctl_conf" << EOF +# Low-memory desktop optimization +vm.swappiness = 10 +vm.dirty_ratio = 10 +vm.dirty_background_ratio = 5 +vm.vfs_cache_pressure = 100 +EOF + ;; + "minimal") + cat >> "$sysctl_conf" << EOF +# Minimal safe optimization +vm.swappiness = 10 +vm.dirty_ratio = 10 +vm.dirty_background_ratio = 5 +EOF + ;; + esac + + # Apply immediately + sysctl -p "$sysctl_conf" + success "Kernel parameters tuned" +} + +create_systemd_service() { + log "Creating systemd service for persistent optimizations" + + if [[ "$DRY_RUN" == "true" ]]; then + echo "[DRY RUN] Would create systemd service" + return + fi + + # Create startup script + cat > /usr/local/bin/system-tuning-startup.sh << 'EOF' +#!/bin/bash +# System Tuning Startup Script +# Auto-generated by Linux System Tuning Suite + +log() { + echo "[$(date '+%H:%M:%S')] $1" | systemd-cat -t system-tuning +} + +log "Starting system optimizations..." + +# Recreate tmpfs mounts +if [[ -d /tmp/tmpfs-cache ]]; then + for cache_dir in /tmp/tmpfs-cache/*; do + if [[ -d "$cache_dir" ]] && ! mountpoint -q "$cache_dir"; then + size=$(df -h "$cache_dir" 2>/dev/null | awk 'NR==2{print $2}' || echo "1G") + mount -t tmpfs -o size="$size" tmpfs "$cache_dir" + log "Mounted tmpfs: $cache_dir ($size)" + fi + done +fi + +# Ensure zram is configured +if [[ ! -e /dev/zram0 ]]; then + modprobe zram num_devices=1 2>/dev/null || true + if [[ -e /sys/block/zram0/disksize ]]; then + echo "8G" > /sys/block/zram0/disksize + mkswap /dev/zram0 + swapon /dev/zram0 + log "Configured zram swap" + fi +fi + +log "System optimizations applied" +EOF + + chmod +x /usr/local/bin/system-tuning-startup.sh + + # Create systemd service + cat > /etc/systemd/system/system-tuning.service << EOF +[Unit] +Description=System Performance Tuning +After=multi-user.target +Wants=multi-user.target + +[Service] +Type=oneshot +ExecStart=/usr/local/bin/system-tuning-startup.sh +RemainAfterExit=yes +StandardOutput=journal +StandardError=journal + +[Install] +WantedBy=multi-user.target +EOF + + systemctl daemon-reload + systemctl enable system-tuning.service + + success "Systemd service created and enabled" +} + +show_status() { + echo "=== SYSTEM TUNING STATUS ===" + echo + + echo "💾 Memory:" + free -h + echo + + echo "🔄 Swap/zram:" + if command -v zramctl >/dev/null 2>&1; then + zramctl 2>/dev/null || echo "No zram devices" + else + echo "zramctl not available" + fi + echo + + echo "📁 tmpfs mounts:" + df -h | grep tmpfs | head -10 + echo + + echo "⚙️ Key kernel parameters:" + echo " Swappiness: $(cat /proc/sys/vm/swappiness)" + echo " Dirty ratio: $(cat /proc/sys/vm/dirty_ratio)" + echo " VFS cache pressure: $(cat /proc/sys/vm/vfs_cache_pressure)" + echo + + echo "🔧 Service status:" + if systemctl is-enabled system-tuning.service >/dev/null 2>&1; then + echo " System tuning service: ENABLED" + else + echo " System tuning service: DISABLED" + fi +} + +parse_args() { + while [[ $# -gt 0 ]]; do + case $1 in + -h|--help) + show_usage + exit 0 + ;; + -v|--verbose) + VERBOSE=true + shift + ;; + -n|--dry-run) + DRY_RUN=true + shift + ;; + -f|--force) + FORCE=true + shift + ;; + -p|--profile) + PROFILE="$2" + shift 2 + ;; + --analyze) + analyze_system + exit 0 + ;; + --auto) + AUTO_MODE=true + shift + ;; + --enable-zram) + enable_zram + shift + ;; + --enable-tmpfs) + enable_tmpfs_cache + shift + ;; + --tune-kernel) + tune_kernel_params + shift + ;; + --create-service) + create_systemd_service + shift + ;; + --status) + show_status + exit 0 + ;; + *) + error "Unknown option: $1" + show_usage + exit 1 + ;; + esac + done +} + +main() { + echo "🚀 Linux System Tuning Suite" + echo "==============================" + + check_root + setup_directories + + # Load modules if available + if [[ -d "$MODULES_DIR" ]]; then + load_modules + fi + + # Parse arguments + parse_args "$@" + + # If no specific action, show usage + if [[ "$AUTO_MODE" != "true" ]] && [[ $# -eq 0 ]]; then + show_usage + exit 0 + fi + + # Create backup before making changes + if [[ "$DRY_RUN" != "true" ]]; then + create_backup + fi + + # Execute auto mode if requested + if [[ "$AUTO_MODE" == "true" ]]; then + auto_optimize + fi + + success "Operation completed successfully!" +} + +# Run main function if script is executed directly +if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then + main "$@" +fi \ No newline at end of file