Complete Linux system optimization suite with tmpfs, zram, and German locale support

- Fixed missing setup_tmpfs() function that was causing silent failures
- Added comprehensive system scanning for browsers, IDEs, gaming caches
- Implemented detailed optimization information display for transparency
- Added German locale compatibility for 'free' command (Speicher: vs Mem:)
- Fixed division by zero errors in RAM calculations
- Created tmpfs-info.sh helper script for detailed status reporting
- Enhanced scanning to work on already-optimized systems
- Added comprehensive optimization breakdowns with purpose explanations
This commit is contained in:
mindesbunister
2025-09-23 12:11:45 +02:00
commit 2edb4a73c3
22 changed files with 4603 additions and 0 deletions

178
modules/hardware-detection.sh Executable file
View File

@@ -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
}

286
modules/usage-analysis.sh Executable file
View File

@@ -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
}