scripts v2.0
All checks were successful
Check scripts syntax / check-scripts-syntax (push) Successful in 35s
All checks were successful
Check scripts syntax / check-scripts-syntax (push) Successful in 35s
This commit is contained in:
594
clean.sh
594
clean.sh
@@ -1,74 +1,558 @@
|
||||
#!/bin/bash
|
||||
|
||||
### AUTO-UPDATER ###
|
||||
# Variables
|
||||
SERVER_FILE="https://git.ivanch.me/ivanch/server-scripts/raw/branch/main/clean.sh"
|
||||
SERVER_OK=1
|
||||
# System Cleanup and Maintenance Script
|
||||
#
|
||||
# Description: Comprehensive system cleanup for Docker containers and Linux systems
|
||||
# Features:
|
||||
# - Self-updating capability
|
||||
# - Docker resource cleanup (images, containers, volumes, networks)
|
||||
# - Package manager cache cleanup (APK/APT)
|
||||
# - System cache and temporary file cleanup
|
||||
# - Log rotation and cleanup
|
||||
# - Memory cache optimization
|
||||
# - Journal cleanup (systemd)
|
||||
# - Thumbnail and user cache cleanup
|
||||
# Author: ivanch
|
||||
# Version: 2.0
|
||||
|
||||
# Check if the server file exists
|
||||
curl -s --head $SERVER_FILE | head -n 1 | grep -E "HTTP/[12] [23].." > /dev/null
|
||||
set -euo pipefail # Exit on error, undefined vars, and pipe failures
|
||||
|
||||
if [ $? -ne 0 ]; then
|
||||
echo "Error: $SERVER_FILE not found." >&2
|
||||
SERVER_OK=0
|
||||
fi
|
||||
#==============================================================================
|
||||
# CONFIGURATION
|
||||
#==============================================================================
|
||||
|
||||
if [ $SERVER_OK -eq 1 ]; then
|
||||
echo "Running auto-update..."
|
||||
# Color definitions for output formatting
|
||||
readonly NC='\033[0m'
|
||||
readonly RED='\033[1;31m'
|
||||
readonly GREEN='\033[1;32m'
|
||||
readonly LIGHT_GREEN='\033[1;32m'
|
||||
readonly LIGHT_BLUE='\033[1;34m'
|
||||
readonly LIGHT_GREY='\033[0;37m'
|
||||
readonly YELLOW='\033[1;33m'
|
||||
|
||||
# Compare the local and server files sha256sum to check if an update is needed
|
||||
LOCAL_SHA256=$(sha256sum clean.sh | awk '{print $1}')
|
||||
SERVER_SHA256=$(curl -s $SERVER_FILE | sha256sum | awk '{print $1}')
|
||||
# Script configuration
|
||||
readonly SCRIPT_NAME="clean.sh"
|
||||
readonly SERVER_BASE_URL="https://git.ivanch.me/ivanch/server-scripts/raw/branch/main"
|
||||
|
||||
if [ "$LOCAL_SHA256" != "$SERVER_SHA256" ]; then
|
||||
echo "Updating clean.sh..."
|
||||
curl -s -o clean.sh $SERVER_FILE
|
||||
echo "clean.sh updated."
|
||||
# Cleanup configuration
|
||||
readonly LOG_RETENTION_DAYS=30
|
||||
readonly JOURNAL_RETENTION_DAYS=7
|
||||
readonly TEMP_DIRS=("/tmp" "/var/tmp")
|
||||
readonly CACHE_DIRS=("/var/cache" "/root/.cache")
|
||||
|
||||
chmod +x clean.sh
|
||||
echo "Permissions set up."
|
||||
# Auto-update configuration
|
||||
readonly AUTO_UPDATE_ENABLED=true
|
||||
|
||||
echo "Running updated clean.sh..."
|
||||
./clean.sh
|
||||
exit 0
|
||||
#==============================================================================
|
||||
# UTILITY FUNCTIONS
|
||||
#==============================================================================
|
||||
|
||||
# Print formatted log messages
|
||||
log_info() { echo -e "${LIGHT_GREY}[i] $1${NC}"; }
|
||||
log_success() { echo -e "${LIGHT_GREEN}[✓] $1${NC}"; }
|
||||
log_warning() { echo -e "${YELLOW}[!] $1${NC}"; }
|
||||
log_error() { echo -e "${RED}[x] $1${NC}" >&2; }
|
||||
log_step() { echo -e "${LIGHT_BLUE}[i] $1${NC}"; }
|
||||
|
||||
# Exit with error message
|
||||
die() {
|
||||
log_error "$1"
|
||||
exit 1
|
||||
}
|
||||
|
||||
# Check if a command exists
|
||||
command_exists() {
|
||||
command -v "$1" >/dev/null 2>&1
|
||||
}
|
||||
|
||||
# Get directory size in human readable format
|
||||
get_dir_size() {
|
||||
local dir="$1"
|
||||
if [[ -d "$dir" ]]; then
|
||||
du -sh "$dir" 2>/dev/null | cut -f1 || echo "0B"
|
||||
else
|
||||
echo "clean.sh is up to date.."
|
||||
echo "0B"
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
####################
|
||||
# Safe directory cleanup with size reporting
|
||||
clean_directory() {
|
||||
local dir="$1"
|
||||
local description="$2"
|
||||
|
||||
if [[ ! -d "$dir" ]]; then
|
||||
return 0
|
||||
fi
|
||||
|
||||
local size_before
|
||||
size_before=$(get_dir_size "$dir")
|
||||
|
||||
if [[ "$size_before" == "0B" ]]; then
|
||||
log_info "$description: already clean"
|
||||
return 0
|
||||
fi
|
||||
|
||||
log_step "$description (was $size_before)..."
|
||||
|
||||
# Use find with -delete for safer cleanup
|
||||
if find "$dir" -mindepth 1 -delete 2>/dev/null; then
|
||||
log_success "$description: freed $size_before"
|
||||
else
|
||||
# Fallback to rm if find fails
|
||||
if rm -rf "$dir"/* 2>/dev/null; then
|
||||
log_success "$description: freed $size_before"
|
||||
else
|
||||
log_warning "$description: partial cleanup completed"
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
# Run Docker system prune
|
||||
echo "Running Docker system prune..."
|
||||
docker image prune -af
|
||||
docker system prune -af
|
||||
# Get system information for reporting
|
||||
get_system_info() {
|
||||
local info=""
|
||||
|
||||
# Memory info
|
||||
if [[ -f /proc/meminfo ]]; then
|
||||
local mem_total mem_available
|
||||
mem_total=$(grep MemTotal /proc/meminfo | awk '{print $2}')
|
||||
mem_available=$(grep MemAvailable /proc/meminfo | awk '{print $2}')
|
||||
if [[ -n "$mem_total" && -n "$mem_available" ]]; then
|
||||
info+="Memory: $((mem_available/1024))MB available of $((mem_total/1024))MB total"
|
||||
fi
|
||||
fi
|
||||
|
||||
# Disk space info
|
||||
if command_exists df; then
|
||||
local disk_info
|
||||
disk_info=$(df -h / 2>/dev/null | tail -1 | awk '{print $4 " available of " $2 " total"}')
|
||||
if [[ -n "$disk_info" ]]; then
|
||||
info+="${info:+, }Disk: $disk_info"
|
||||
fi
|
||||
fi
|
||||
|
||||
echo "$info"
|
||||
}
|
||||
|
||||
# Clean APK cache from Alpine or apt for Debian
|
||||
if [ -x "$(command -v apk)" ]; then
|
||||
echo "Cleaning APK cache..."
|
||||
rm -rf /var/cache/apk/*
|
||||
apk cache clean
|
||||
apk update
|
||||
fi
|
||||
#==============================================================================
|
||||
# AUTO-UPDATE FUNCTIONALITY
|
||||
#==============================================================================
|
||||
|
||||
if [ -x "$(command -v apt)" ]; then
|
||||
echo "Cleaning apt cache..."
|
||||
apt-get clean
|
||||
apt-get autoclean
|
||||
apt-get update
|
||||
fi
|
||||
# Check server connectivity
|
||||
check_server_connectivity() {
|
||||
local url="$1"
|
||||
curl -s --head "$url" | head -n 1 | grep -E "HTTP/[12] [23].." >/dev/null 2>&1
|
||||
}
|
||||
|
||||
# Clean system caches
|
||||
echo "Cleaning system caches..."
|
||||
rm -rf /var/cache/*
|
||||
rm -rf /tmp/*
|
||||
# Get SHA256 hash of a file
|
||||
get_file_hash() {
|
||||
local file="$1"
|
||||
sha256sum "$file" 2>/dev/null | awk '{print $1}' || echo ""
|
||||
}
|
||||
|
||||
# General system maintenance
|
||||
echo "Performing general system maintenance..."
|
||||
sync; echo 3 > /proc/sys/vm/drop_caches
|
||||
# Get SHA256 hash from URL content
|
||||
get_url_hash() {
|
||||
local url="$1"
|
||||
curl -s "$url" 2>/dev/null | sha256sum | awk '{print $1}' || echo ""
|
||||
}
|
||||
|
||||
# Remove old logs
|
||||
echo "Removing old logs..."
|
||||
find /var/log -type f -name "*.log" -mtime +30 -delete
|
||||
# Perform self-update if newer version is available
|
||||
perform_self_update() {
|
||||
if [[ "$AUTO_UPDATE_ENABLED" != "true" ]]; then
|
||||
log_info "Auto-update is disabled"
|
||||
return 0
|
||||
fi
|
||||
|
||||
local server_url="$SERVER_BASE_URL/$SCRIPT_NAME"
|
||||
|
||||
log_step "Checking for script updates..."
|
||||
|
||||
# Check if server file is accessible
|
||||
if ! check_server_connectivity "$server_url"; then
|
||||
log_warning "Cannot connect to update server, continuing with current version"
|
||||
return 0
|
||||
fi
|
||||
|
||||
# Compare local and server file hashes
|
||||
local local_hash server_hash
|
||||
local_hash=$(get_file_hash "$SCRIPT_NAME")
|
||||
server_hash=$(get_url_hash "$server_url")
|
||||
|
||||
if [[ -z "$local_hash" || -z "$server_hash" ]]; then
|
||||
log_warning "Cannot determine file hashes, skipping update"
|
||||
return 0
|
||||
fi
|
||||
|
||||
if [[ "$local_hash" != "$server_hash" ]]; then
|
||||
log_info "Update available, downloading new version..."
|
||||
|
||||
# Create backup of current script
|
||||
local backup_file="${SCRIPT_NAME}.backup.$(date +%s)"
|
||||
cp "$SCRIPT_NAME" "$backup_file" || die "Failed to create backup"
|
||||
|
||||
# Download updated script
|
||||
if curl -s -o "$SCRIPT_NAME" "$server_url"; then
|
||||
chmod +x "$SCRIPT_NAME" || die "Failed to set executable permissions"
|
||||
log_success "Script updated successfully"
|
||||
|
||||
log_step "Running updated script..."
|
||||
exec ./"$SCRIPT_NAME" "$@"
|
||||
else
|
||||
# Restore backup on failure
|
||||
mv "$backup_file" "$SCRIPT_NAME"
|
||||
die "Failed to download updated script"
|
||||
fi
|
||||
else
|
||||
log_success "Script is already up to date"
|
||||
fi
|
||||
}
|
||||
|
||||
echo "Maintenance completed."
|
||||
#==============================================================================
|
||||
# DOCKER CLEANUP FUNCTIONS
|
||||
#==============================================================================
|
||||
|
||||
# Clean Docker resources
|
||||
cleanup_docker() {
|
||||
if ! command_exists docker; then
|
||||
log_info "Docker not found, skipping Docker cleanup"
|
||||
return 0
|
||||
fi
|
||||
|
||||
log_step "Starting Docker cleanup..."
|
||||
|
||||
# Check if Docker daemon is running
|
||||
if ! docker info >/dev/null 2>&1; then
|
||||
log_warning "Docker daemon not running, skipping Docker cleanup"
|
||||
return 0
|
||||
fi
|
||||
|
||||
# Get initial Docker disk usage
|
||||
local docker_usage_before=""
|
||||
if docker system df >/dev/null 2>&1; then
|
||||
docker_usage_before=$(docker system df 2>/dev/null || echo "")
|
||||
fi
|
||||
|
||||
# Remove unused images
|
||||
log_info "Removing unused Docker images..."
|
||||
if docker image prune -af >/dev/null 2>&1; then
|
||||
log_success "Docker images cleaned"
|
||||
else
|
||||
log_warning "Docker image cleanup failed"
|
||||
fi
|
||||
|
||||
# Remove stopped containers
|
||||
log_info "Removing stopped Docker containers..."
|
||||
if docker container prune -f >/dev/null 2>&1; then
|
||||
log_success "Docker containers cleaned"
|
||||
else
|
||||
log_warning "Docker container cleanup failed"
|
||||
fi
|
||||
|
||||
# Remove unused volumes
|
||||
log_info "Removing unused Docker volumes..."
|
||||
if docker volume prune -f >/dev/null 2>&1; then
|
||||
log_success "Docker volumes cleaned"
|
||||
else
|
||||
log_warning "Docker volume cleanup failed"
|
||||
fi
|
||||
|
||||
# Remove unused networks
|
||||
log_info "Removing unused Docker networks..."
|
||||
if docker network prune -f >/dev/null 2>&1; then
|
||||
log_success "Docker networks cleaned"
|
||||
else
|
||||
log_warning "Docker network cleanup failed"
|
||||
fi
|
||||
|
||||
# Complete system cleanup
|
||||
log_info "Running Docker system cleanup..."
|
||||
if docker system prune -af >/dev/null 2>&1; then
|
||||
log_success "Docker system cleanup completed"
|
||||
else
|
||||
log_warning "Docker system cleanup failed"
|
||||
fi
|
||||
|
||||
# Show space freed if possible
|
||||
if [[ -n "$docker_usage_before" ]] && docker system df >/dev/null 2>&1; then
|
||||
log_info "Docker cleanup completed"
|
||||
fi
|
||||
}
|
||||
|
||||
#==============================================================================
|
||||
# PACKAGE MANAGER CLEANUP FUNCTIONS
|
||||
#==============================================================================
|
||||
|
||||
# Clean APK cache (Alpine Linux)
|
||||
cleanup_apk() {
|
||||
if ! command_exists apk; then
|
||||
return 0
|
||||
fi
|
||||
|
||||
log_step "Cleaning APK cache..."
|
||||
|
||||
# Clean APK cache
|
||||
if [[ -d /var/cache/apk ]]; then
|
||||
clean_directory "/var/cache/apk" "APK cache directory"
|
||||
fi
|
||||
|
||||
# Clean APK cache using apk command
|
||||
if apk cache clean >/dev/null 2>&1; then
|
||||
log_success "APK cache cleaned"
|
||||
fi
|
||||
|
||||
# Update package index
|
||||
log_info "Updating APK package index..."
|
||||
if apk update >/dev/null 2>&1; then
|
||||
log_success "APK index updated"
|
||||
else
|
||||
log_warning "APK index update failed"
|
||||
fi
|
||||
}
|
||||
|
||||
# Clean APT cache (Debian/Ubuntu)
|
||||
cleanup_apt() {
|
||||
if ! command_exists apt-get; then
|
||||
return 0
|
||||
fi
|
||||
|
||||
log_step "Cleaning APT cache..."
|
||||
|
||||
# Clean downloaded packages
|
||||
if apt-get clean >/dev/null 2>&1; then
|
||||
log_success "APT cache cleaned"
|
||||
else
|
||||
log_warning "APT clean failed"
|
||||
fi
|
||||
|
||||
# Remove orphaned packages
|
||||
if apt-get autoclean >/dev/null 2>&1; then
|
||||
log_success "APT autocleaned"
|
||||
else
|
||||
log_warning "APT autoclean failed"
|
||||
fi
|
||||
|
||||
# Remove unnecessary packages
|
||||
if apt-get autoremove -y >/dev/null 2>&1; then
|
||||
log_success "Unnecessary packages removed"
|
||||
else
|
||||
log_warning "APT autoremove failed"
|
||||
fi
|
||||
|
||||
# Update package index
|
||||
log_info "Updating APT package index..."
|
||||
if apt-get update >/dev/null 2>&1; then
|
||||
log_success "APT index updated"
|
||||
else
|
||||
log_warning "APT index update failed"
|
||||
fi
|
||||
}
|
||||
|
||||
#==============================================================================
|
||||
# SYSTEM CLEANUP FUNCTIONS
|
||||
#==============================================================================
|
||||
|
||||
# Clean system temporary directories
|
||||
cleanup_temp_dirs() {
|
||||
log_step "Cleaning temporary directories..."
|
||||
|
||||
for temp_dir in "${TEMP_DIRS[@]}"; do
|
||||
if [[ -d "$temp_dir" ]]; then
|
||||
# Clean contents but preserve the directory
|
||||
find "$temp_dir" -mindepth 1 -maxdepth 1 -mtime +1 -exec rm -rf {} + 2>/dev/null || true
|
||||
log_success "Cleaned old files in $temp_dir"
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
# Clean system cache directories
|
||||
cleanup_cache_dirs() {
|
||||
log_step "Cleaning cache directories..."
|
||||
|
||||
for cache_dir in "${CACHE_DIRS[@]}"; do
|
||||
if [[ -d "$cache_dir" ]]; then
|
||||
clean_directory "$cache_dir" "Cache directory $cache_dir"
|
||||
fi
|
||||
done
|
||||
|
||||
# Clean additional cache locations
|
||||
local additional_caches=(
|
||||
"/var/lib/apt/lists"
|
||||
"/var/cache/debconf"
|
||||
"/root/.npm"
|
||||
"/root/.pip"
|
||||
"/home/*/.cache"
|
||||
"/home/*/.npm"
|
||||
"/home/*/.pip"
|
||||
)
|
||||
|
||||
for cache_pattern in "${additional_caches[@]}"; do
|
||||
# Use shell expansion for patterns
|
||||
for cache_path in $cache_pattern; do
|
||||
if [[ -d "$cache_path" ]]; then
|
||||
clean_directory "$cache_path" "Additional cache $cache_path"
|
||||
fi
|
||||
done 2>/dev/null || true
|
||||
done
|
||||
}
|
||||
|
||||
# Clean old log files
|
||||
cleanup_logs() {
|
||||
log_step "Cleaning old log files..."
|
||||
|
||||
# Clean logs older than retention period
|
||||
if [[ -d /var/log ]]; then
|
||||
local cleaned_count=0
|
||||
|
||||
# Find and remove old log files
|
||||
while IFS= read -r -d '' logfile; do
|
||||
rm -f "$logfile" 2>/dev/null && ((cleaned_count++))
|
||||
done < <(find /var/log -type f -name "*.log" -mtime +"$LOG_RETENTION_DAYS" -print0 2>/dev/null || true)
|
||||
|
||||
# Clean compressed logs
|
||||
while IFS= read -r -d '' logfile; do
|
||||
rm -f "$logfile" 2>/dev/null && ((cleaned_count++))
|
||||
done < <(find /var/log -type f \( -name "*.log.gz" -o -name "*.log.bz2" -o -name "*.log.xz" \) -mtime +"$LOG_RETENTION_DAYS" -print0 2>/dev/null || true)
|
||||
|
||||
if [[ $cleaned_count -gt 0 ]]; then
|
||||
log_success "Removed $cleaned_count old log files"
|
||||
else
|
||||
log_info "No old log files to remove"
|
||||
fi
|
||||
fi
|
||||
|
||||
# Truncate large active log files
|
||||
local large_logs
|
||||
while IFS= read -r -d '' logfile; do
|
||||
if [[ -f "$logfile" && -w "$logfile" ]]; then
|
||||
truncate -s 0 "$logfile" 2>/dev/null || true
|
||||
fi
|
||||
done < <(find /var/log -type f -name "*.log" -size +100M -print0 2>/dev/null || true)
|
||||
}
|
||||
|
||||
# Clean systemd journal
|
||||
cleanup_journal() {
|
||||
if ! command_exists journalctl; then
|
||||
return 0
|
||||
fi
|
||||
|
||||
log_step "Cleaning systemd journal..."
|
||||
|
||||
# Clean journal older than retention period
|
||||
if journalctl --vacuum-time="${JOURNAL_RETENTION_DAYS}d" >/dev/null 2>&1; then
|
||||
log_success "Journal cleaned (older than $JOURNAL_RETENTION_DAYS days)"
|
||||
else
|
||||
log_warning "Journal cleanup failed"
|
||||
fi
|
||||
|
||||
# Limit journal size
|
||||
if journalctl --vacuum-size=100M >/dev/null 2>&1; then
|
||||
log_success "Journal size limited to 100MB"
|
||||
fi
|
||||
}
|
||||
|
||||
# Clean thumbnail caches
|
||||
cleanup_thumbnails() {
|
||||
log_step "Cleaning thumbnail caches..."
|
||||
|
||||
local thumbnail_dirs=(
|
||||
"/root/.thumbnails"
|
||||
"/root/.cache/thumbnails"
|
||||
"/home/*/.thumbnails"
|
||||
"/home/*/.cache/thumbnails"
|
||||
)
|
||||
|
||||
for thumb_pattern in "${thumbnail_dirs[@]}"; do
|
||||
for thumb_dir in $thumb_pattern; do
|
||||
if [[ -d "$thumb_dir" ]]; then
|
||||
clean_directory "$thumb_dir" "Thumbnail cache $thumb_dir"
|
||||
fi
|
||||
done 2>/dev/null || true
|
||||
done
|
||||
}
|
||||
|
||||
# Optimize memory caches
|
||||
optimize_memory() {
|
||||
log_step "Optimizing memory caches..."
|
||||
|
||||
# Sync filesystem
|
||||
if sync; then
|
||||
log_info "Filesystem synced"
|
||||
fi
|
||||
|
||||
# Drop caches (page cache, dentries and inodes)
|
||||
if [[ -w /proc/sys/vm/drop_caches ]]; then
|
||||
echo 3 > /proc/sys/vm/drop_caches 2>/dev/null && log_success "Memory caches dropped" || log_warning "Failed to drop memory caches"
|
||||
fi
|
||||
}
|
||||
|
||||
#==============================================================================
|
||||
# REPORTING FUNCTIONS
|
||||
#==============================================================================
|
||||
|
||||
# Generate cleanup summary
|
||||
generate_summary() {
|
||||
log_step "Generating cleanup summary..."
|
||||
|
||||
local system_info
|
||||
system_info=$(get_system_info)
|
||||
|
||||
if [[ -n "$system_info" ]]; then
|
||||
log_info "System status: $system_info"
|
||||
fi
|
||||
|
||||
# Show disk usage of important directories
|
||||
local important_dirs=("/" "/var" "/tmp" "/var/log" "/var/cache")
|
||||
for dir in "${important_dirs[@]}"; do
|
||||
if [[ -d "$dir" ]]; then
|
||||
local usage
|
||||
usage=$(df -h "$dir" 2>/dev/null | tail -1 | awk '{print $5 " used (" $4 " available)"}' || echo "unknown")
|
||||
log_info "$dir: $usage"
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
#==============================================================================
|
||||
# MAIN EXECUTION
|
||||
#==============================================================================
|
||||
|
||||
main() {
|
||||
log_step "Starting System Cleanup and Maintenance"
|
||||
echo
|
||||
|
||||
# Show initial system status
|
||||
local initial_info
|
||||
initial_info=$(get_system_info)
|
||||
if [[ -n "$initial_info" ]]; then
|
||||
log_info "Initial system status: $initial_info"
|
||||
echo
|
||||
fi
|
||||
|
||||
# Perform self-update if enabled
|
||||
perform_self_update "$@"
|
||||
|
||||
# Docker cleanup
|
||||
cleanup_docker
|
||||
|
||||
# Package manager cleanup
|
||||
cleanup_apk
|
||||
cleanup_apt
|
||||
|
||||
# System cleanup
|
||||
cleanup_temp_dirs
|
||||
cleanup_cache_dirs
|
||||
cleanup_logs
|
||||
cleanup_journal
|
||||
cleanup_thumbnails
|
||||
|
||||
# Memory optimization
|
||||
optimize_memory
|
||||
|
||||
# Generate summary
|
||||
echo
|
||||
generate_summary
|
||||
|
||||
echo
|
||||
log_success "System cleanup and maintenance completed!"
|
||||
}
|
||||
|
||||
# Execute main function with all arguments
|
||||
main "$@"
|
Reference in New Issue
Block a user