- Complete Particle-OS rebranding from uBlue-OS - Professional installation system with standardized paths - Self-initialization system with --init and --reset commands - Enhanced error messages and dependency checking - Comprehensive testing infrastructure - All source scriptlets updated with runtime improvements - Clean codebase with redundant files moved to archive - Complete documentation suite
330 lines
No EOL
9.1 KiB
Bash
330 lines
No EOL
9.1 KiB
Bash
#!/bin/bash
|
|
|
|
# Ubuntu uBlue Log Rotation Utility
|
|
# Provides log rotation functionality for Ubuntu uBlue logs
|
|
|
|
set -euo pipefail
|
|
|
|
# Source unified configuration
|
|
if [[ -f "/usr/local/etc/particle-config.sh" ]]; then
|
|
source "/usr/local/etc/particle-config.sh"
|
|
else
|
|
# Fallback configuration
|
|
PARTICLE_LOG_DIR="/var/log/particle-os"
|
|
PARTICLE_LOG_MAX_SIZE="${PARTICLE_LOG_MAX_SIZE:-100M}"
|
|
PARTICLE_LOG_MAX_FILES="${PARTICLE_LOG_MAX_FILES:-5}"
|
|
fi
|
|
|
|
# Colors for output
|
|
RED='\033[0;31m'
|
|
GREEN='\033[0;32m'
|
|
YELLOW='\033[1;33m'
|
|
BLUE='\033[0;34m'
|
|
NC='\033[0m'
|
|
|
|
# Logging functions
|
|
log_info() {
|
|
echo -e "${BLUE}[INFO]${NC} $1"
|
|
}
|
|
|
|
log_success() {
|
|
echo -e "${GREEN}[SUCCESS]${NC} $1"
|
|
}
|
|
|
|
log_error() {
|
|
echo -e "${RED}[ERROR]${NC} $1"
|
|
}
|
|
|
|
log_warning() {
|
|
echo -e "${YELLOW}[WARNING]${NC} $1"
|
|
}
|
|
|
|
# Convert size string to bytes
|
|
size_to_bytes() {
|
|
local size="$1"
|
|
local number
|
|
local unit
|
|
|
|
# Extract number and unit
|
|
if [[ "$size" =~ ^([0-9]+)([KMGT]?)$ ]]; then
|
|
number="${BASH_REMATCH[1]}"
|
|
unit="${BASH_REMATCH[2]}"
|
|
else
|
|
log_error "Invalid size format: $size"
|
|
return 1
|
|
fi
|
|
|
|
case "$unit" in
|
|
"K"|"k") echo $((number * 1024)) ;;
|
|
"M"|"m") echo $((number * 1024 * 1024)) ;;
|
|
"G"|"g") echo $((number * 1024 * 1024 * 1024)) ;;
|
|
"T"|"t") echo $((number * 1024 * 1024 * 1024 * 1024)) ;;
|
|
"") echo "$number" ;;
|
|
*) log_error "Unknown unit: $unit"; return 1 ;;
|
|
esac
|
|
}
|
|
|
|
# Get file size in bytes
|
|
get_file_size() {
|
|
local file="$1"
|
|
if [[ -f "$file" ]]; then
|
|
stat -c%s "$file" 2>/dev/null || echo "0"
|
|
else
|
|
echo "0"
|
|
fi
|
|
}
|
|
|
|
# Rotate a single log file
|
|
rotate_log_file() {
|
|
local log_file="$1"
|
|
local max_size_bytes="$2"
|
|
local max_files="$3"
|
|
|
|
if [[ ! -f "$log_file" ]]; then
|
|
return 0
|
|
fi
|
|
|
|
local current_size
|
|
current_size=$(get_file_size "$log_file")
|
|
|
|
if [[ $current_size -gt $max_size_bytes ]]; then
|
|
log_info "Rotating log file: $log_file (size: $current_size bytes)"
|
|
|
|
# Remove oldest backup if we've reached max_files
|
|
local oldest_backup="$log_file.$max_files"
|
|
if [[ -f "$oldest_backup" ]]; then
|
|
rm -f "$oldest_backup"
|
|
fi
|
|
|
|
# Shift existing backups
|
|
for ((i=max_files-1; i>=1; i--)); do
|
|
local src="$log_file.$i"
|
|
local dst="$log_file.$((i+1))"
|
|
if [[ -f "$src" ]]; then
|
|
mv "$src" "$dst"
|
|
fi
|
|
done
|
|
|
|
# Compress and move current log
|
|
local compression_cmd
|
|
case "$PARTICLE_LOG_COMPRESSION" in
|
|
"gzip")
|
|
compression_cmd="gzip -c"
|
|
;;
|
|
"bzip2")
|
|
compression_cmd="bzip2 -c"
|
|
;;
|
|
"xz")
|
|
compression_cmd="xz -c"
|
|
;;
|
|
"zstd")
|
|
compression_cmd="zstd -c"
|
|
;;
|
|
*)
|
|
log_warning "Unknown compression: $PARTICLE_LOG_COMPRESSION, using gzip"
|
|
compression_cmd="gzip -c"
|
|
;;
|
|
esac
|
|
|
|
local extension
|
|
case "$PARTICLE_LOG_COMPRESSION" in
|
|
"gzip") extension="gz" ;;
|
|
"bzip2") extension="bz2" ;;
|
|
"xz") extension="xz" ;;
|
|
"zstd") extension="zst" ;;
|
|
*) extension="gz" ;;
|
|
esac
|
|
|
|
if eval "$compression_cmd" "$log_file" > "$log_file.1.$extension"; then
|
|
# Truncate original file
|
|
: > "$log_file"
|
|
log_success "Rotated $log_file"
|
|
else
|
|
log_error "Failed to compress $log_file"
|
|
return 1
|
|
fi
|
|
fi
|
|
}
|
|
|
|
# Rotate all Particle-OS logs
|
|
rotate_all_logs() {
|
|
log_info "Starting Particle-OS log rotation..."
|
|
|
|
local max_size_bytes
|
|
max_size_bytes=$(size_to_bytes "$PARTICLE_LOG_MAX_SIZE")
|
|
|
|
# Find all log files in the log directory
|
|
if [[ ! -d "$PARTICLE_LOG_DIR" ]]; then
|
|
log_warning "Log directory not found: $PARTICLE_LOG_DIR"
|
|
return 0
|
|
fi
|
|
|
|
local rotated_count=0
|
|
local error_count=0
|
|
|
|
# Parse log file patterns
|
|
local patterns
|
|
IFS=' ' read -ra patterns <<< "$PARTICLE_LOG_FILES_PATTERN"
|
|
|
|
# Rotate each log file matching patterns
|
|
for pattern in "${patterns[@]}"; do
|
|
while IFS= read -r -d '' log_file; do
|
|
if rotate_log_file "$log_file" "$max_size_bytes" "$PARTICLE_LOG_MAX_FILES"; then
|
|
rotated_count=$((rotated_count + 1))
|
|
else
|
|
error_count=$((error_count + 1))
|
|
fi
|
|
done < <(find "$PARTICLE_LOG_DIR" -name "$pattern" -type f -print0)
|
|
done
|
|
|
|
if [[ $error_count -eq 0 ]]; then
|
|
log_success "Log rotation completed successfully"
|
|
log_info "Rotated $rotated_count log files"
|
|
else
|
|
log_warning "Log rotation completed with $error_count errors"
|
|
fi
|
|
}
|
|
|
|
# Clean up old log files
|
|
cleanup_old_logs() {
|
|
log_info "Cleaning up old log files..."
|
|
|
|
local cleanup_count=0
|
|
|
|
# Parse log file patterns for cleanup
|
|
local patterns
|
|
IFS=' ' read -ra patterns <<< "$PARTICLE_LOG_FILES_PATTERN"
|
|
|
|
# Remove log files older than 30 days
|
|
for pattern in "${patterns[@]}"; do
|
|
while IFS= read -r -d '' log_file; do
|
|
if [[ $(find "$log_file" -mtime +30 2>/dev/null) ]]; then
|
|
rm -f "$log_file"
|
|
cleanup_count=$((cleanup_count + 1))
|
|
log_info "Removed old log file: $log_file"
|
|
fi
|
|
done < <(find "$PARTICLE_LOG_DIR" -name "$pattern.*" -type f -print0)
|
|
done
|
|
|
|
log_success "Cleanup completed: removed $cleanup_count old log files"
|
|
}
|
|
|
|
# Show log statistics
|
|
show_log_stats() {
|
|
log_info "Particle-OS Log Statistics"
|
|
echo "============================"
|
|
echo
|
|
|
|
if [[ ! -d "$PARTICLE_LOG_DIR" ]]; then
|
|
log_warning "Log directory not found: $PARTICLE_LOG_DIR"
|
|
return 1
|
|
fi
|
|
|
|
echo "Log Directory: $PARTICLE_LOG_DIR"
|
|
echo "Max Size: $PARTICLE_LOG_MAX_SIZE"
|
|
echo "Max Files: $PARTICLE_LOG_MAX_FILES"
|
|
echo
|
|
|
|
# Show current log files and their sizes
|
|
echo "Current Log Files:"
|
|
echo "------------------"
|
|
|
|
# Parse log file patterns
|
|
local patterns
|
|
IFS=' ' read -ra patterns <<< "$PARTICLE_LOG_FILES_PATTERN"
|
|
|
|
for pattern in "${patterns[@]}"; do
|
|
while IFS= read -r -d '' log_file; do
|
|
local size
|
|
size=$(get_file_size "$log_file")
|
|
local size_human
|
|
size_human=$(numfmt --to=iec-i --suffix=B "$size" 2>/dev/null || echo "${size}B")
|
|
echo " $(basename "$log_file"): $size_human"
|
|
done < <(find "$PARTICLE_LOG_DIR" -name "$pattern" -type f -print0 | sort -z)
|
|
done
|
|
|
|
echo
|
|
|
|
# Show backup log files
|
|
echo "Backup Log Files:"
|
|
echo "-----------------"
|
|
local backup_count=0
|
|
local backup_size=0
|
|
|
|
for pattern in "${patterns[@]}"; do
|
|
while IFS= read -r -d '' log_file; do
|
|
local size
|
|
size=$(get_file_size "$log_file")
|
|
backup_size=$((backup_size + size))
|
|
backup_count=$((backup_count + 1))
|
|
local size_human
|
|
size_human=$(numfmt --to=iec-i --suffix=B "$size" 2>/dev/null || echo "${size}B")
|
|
echo " $(basename "$log_file"): $size_human"
|
|
done < <(find "$PARTICLE_LOG_DIR" -name "$pattern.*" -type f -print0 | sort -z)
|
|
done
|
|
|
|
if [[ $backup_count -gt 0 ]]; then
|
|
echo
|
|
local backup_size_human
|
|
backup_size_human=$(numfmt --to=iec-i --suffix=B "$backup_size" 2>/dev/null || echo "${backup_size}B")
|
|
echo "Total backup files: $backup_count"
|
|
echo "Total backup size: $backup_size_human"
|
|
else
|
|
echo " No backup files found"
|
|
fi
|
|
}
|
|
|
|
# Main function
|
|
main() {
|
|
case "${1:-}" in
|
|
"rotate")
|
|
rotate_all_logs
|
|
;;
|
|
"cleanup")
|
|
cleanup_old_logs
|
|
;;
|
|
"stats")
|
|
show_log_stats
|
|
;;
|
|
"all")
|
|
rotate_all_logs
|
|
cleanup_old_logs
|
|
;;
|
|
"help"|"-h"|"--help")
|
|
cat << EOF
|
|
Particle-OS Log Rotation Utility
|
|
|
|
Usage: $0 <command> [options]
|
|
|
|
Commands:
|
|
rotate Rotate log files that exceed max size
|
|
cleanup Remove log files older than 30 days
|
|
stats Show log file statistics
|
|
all Run both rotate and cleanup
|
|
help, -h, --help Show this help message
|
|
|
|
Environment Variables:
|
|
PARTICLE_LOG_MAX_SIZE=100M Maximum log file size before rotation
|
|
PARTICLE_LOG_MAX_FILES=5 Maximum number of backup files to keep
|
|
|
|
Examples:
|
|
$0 rotate # Rotate oversized logs
|
|
$0 cleanup # Clean up old logs
|
|
$0 stats # Show log statistics
|
|
$0 all # Run full maintenance
|
|
|
|
This utility manages log rotation for Particle-OS logs, ensuring
|
|
they don't consume excessive disk space while maintaining a history
|
|
of recent activity.
|
|
EOF
|
|
;;
|
|
*)
|
|
log_error "Unknown command: ${1:-}"
|
|
echo "Use '$0 help' for usage information"
|
|
exit 1
|
|
;;
|
|
esac
|
|
}
|
|
|
|
# Run main function
|
|
main "$@" |