Improve automatic Snap upgrades.

Thanks to xet7 !
This commit is contained in:
Lauri Ojansivu 2025-10-11 05:52:41 +03:00
parent d64aeb25d5
commit aab671398c
3 changed files with 570 additions and 8 deletions

188
snap-src/bin/logrotate-mongodb Executable file
View file

@ -0,0 +1,188 @@
#!/bin/bash
# MongoDB Log Rotation Script for Wekan Snap
# This script handles log rotation for MongoDB logs in the Wekan snap environment
set -e
# Source settings if available, otherwise use defaults
if [ -f "$SNAP/bin/wekan-read-settings" ]; then
source $SNAP/bin/wekan-read-settings
else
# Default values when wekan-read-settings is not available
SNAP_COMMON="/var/snap/wekan/common"
SNAP_NAME="wekan"
fi
# Configuration
MONGODB_LOG="${SNAP_COMMON}/mongodb.log"
MAX_SIZE_MB=100
KEEP_COPIES=10
COMPRESS_LOGS=true
# Logging functions
log_message() {
local message="$1"
local timestamp=$(date '+%Y-%m-%d %H:%M:%S')
echo "[$timestamp] $message"
}
log_error() {
local message="$1"
log_message "ERROR: $message"
}
log_success() {
local message="$1"
log_message "SUCCESS: $message"
}
log_warning() {
local message="$1"
log_message "WARNING: $message"
}
# Check if log file exists and is large enough to rotate
check_rotation_needed() {
if [ ! -f "$MONGODB_LOG" ]; then
log_message "MongoDB log file not found: $MONGODB_LOG"
return 1
fi
# Get log file size in MB
local log_size_mb=$(du -m "$MONGODB_LOG" | cut -f1)
if [ "$log_size_mb" -lt "$MAX_SIZE_MB" ]; then
log_message "MongoDB log size (${log_size_mb}MB) is below rotation threshold (${MAX_SIZE_MB}MB)"
return 1
fi
log_message "MongoDB log size (${log_size_mb}MB) exceeds rotation threshold (${MAX_SIZE_MB}MB)"
return 0
}
# Rotate MongoDB log file
rotate_log() {
local mongodb_log="$1"
local max_size_mb="$2"
local keep_copies="$3"
local compress="$4"
log_message "Starting MongoDB log rotation"
# Create rotated log file with timestamp
local timestamp=$(date +%Y%m%d-%H%M%S)
local rotated_log="${mongodb_log}.${timestamp}"
# Copy current log to rotated file
if cp "$mongodb_log" "$rotated_log"; then
log_message "Created rotated log file: $rotated_log"
# Truncate original log file
if > "$mongodb_log"; then
log_message "Truncated original log file"
else
log_error "Failed to truncate original log file"
return 1
fi
# Compress rotated log file if requested
if [ "$compress" = "true" ]; then
if gzip "$rotated_log"; then
log_message "Compressed rotated log file: ${rotated_log}.gz"
else
log_warning "Failed to compress rotated log file"
fi
fi
# Clean up old rotated logs (keep only specified number)
local old_logs=$(ls -t "${mongodb_log}".* 2>/dev/null | tail -n +$((keep_copies + 1)))
if [ -n "$old_logs" ]; then
echo "$old_logs" | xargs rm -f
log_message "Cleaned up old rotated log files"
fi
log_success "MongoDB log rotation completed successfully"
return 0
else
log_error "Failed to create rotated log file"
return 1
fi
}
# Show log file statistics
show_log_stats() {
if [ ! -f "$MONGODB_LOG" ]; then
log_message "MongoDB log file not found: $MONGODB_LOG"
return 1
fi
local log_size_mb=$(du -m "$MONGODB_LOG" | cut -f1)
local log_lines=$(wc -l < "$MONGODB_LOG" 2>/dev/null || echo "0")
local rotated_count=$(ls -1 "${MONGODB_LOG}".* 2>/dev/null | wc -l)
log_message "MongoDB Log Statistics:"
log_message " Current log size: ${log_size_mb}MB"
log_message " Current log lines: ${log_lines}"
log_message " Rotated log files: ${rotated_count}"
log_message " Rotation threshold: ${MAX_SIZE_MB}MB"
log_message " Keep copies: ${KEEP_COPIES}"
}
# Force rotation regardless of size
force_rotation() {
log_message "Force rotating MongoDB log file"
if [ ! -f "$MONGODB_LOG" ]; then
log_error "MongoDB log file not found: $MONGODB_LOG"
return 1
fi
rotate_log "$MONGODB_LOG" "$MAX_SIZE_MB" "$KEEP_COPIES" "$COMPRESS_LOGS"
}
# Main function
main() {
local action="${1:-check}"
case "$action" in
"check")
log_message "Checking if MongoDB log rotation is needed"
if check_rotation_needed; then
log_message "Log rotation is needed"
rotate_log "$MONGODB_LOG" "$MAX_SIZE_MB" "$KEEP_COPIES" "$COMPRESS_LOGS"
else
log_message "Log rotation is not needed"
fi
;;
"force")
force_rotation
;;
"stats")
show_log_stats
;;
"help"|"-h"|"--help")
echo "Usage: $0 [check|force|stats|help]"
echo ""
echo "Commands:"
echo " check - Check if rotation is needed and rotate if so (default)"
echo " force - Force rotation regardless of log size"
echo " stats - Show log file statistics"
echo " help - Show this help message"
echo ""
echo "Configuration:"
echo " Log file: $MONGODB_LOG"
echo " Max size: ${MAX_SIZE_MB}MB"
echo " Keep copies: $KEEP_COPIES"
echo " Compress: $COMPRESS_LOGS"
;;
*)
log_error "Unknown action: $action"
echo "Use '$0 help' for usage information"
exit 1
;;
esac
}
# Run main function
main "$@"

View file

@ -0,0 +1,175 @@
#!/bin/bash
# Wekan Log Rotation Setup Script
# This script sets up log rotation for Wekan snap installation
set -e
# Configuration
SNAP_NAME="wekan"
SNAP_COMMON="/var/snap/${SNAP_NAME}/common"
LOGROTATE_DIR="/etc/logrotate.d"
WEKAN_LOGROTATE_CONF="${LOGROTATE_DIR}/${SNAP_NAME}"
# Log file paths
MONGODB_LOG="${SNAP_COMMON}/mongodb.log"
WEKAN_APP_LOG="${SNAP_COMMON}/wekan-app.log"
WEKAN_ERROR_LOG="${SNAP_COMMON}/wekan-error.log"
# Log rotation configuration
ROTATE_SIZE="100M"
KEEP_DAYS="30"
KEEP_COPIES="10"
log_message() {
echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1"
}
log_error() {
echo "[$(date '+%Y-%m-%d %H:%M:%S')] ERROR: $1" >&2
}
# Check if running as root
if [ "$EUID" -ne 0 ]; then
log_error "This script must be run as root"
exit 1
fi
# Check if snap is installed
if ! snap list | grep -q "^${SNAP_NAME} "; then
log_error "Snap ${SNAP_NAME} is not installed"
exit 1
fi
log_message "Setting up log rotation for Wekan snap..."
# Create logrotate configuration
cat > "${WEKAN_LOGROTATE_CONF}" << EOF
# Wekan Snap Log Rotation Configuration
# Generated by wekan logrotate-setup script
# MongoDB logs
${MONGODB_LOG} {
daily
missingok
rotate ${KEEP_COPIES}
compress
delaycompress
notifempty
create 644 root root
postrotate
# Send SIGUSR1 to MongoDB to reopen log file
if [ -f "${SNAP_COMMON}/mongodb.pid" ]; then
kill -USR1 \$(cat "${SNAP_COMMON}/mongodb.pid") 2>/dev/null || true
fi
# Alternative: restart MongoDB service if PID file doesn't exist
if [ ! -f "${SNAP_COMMON}/mongodb.pid" ]; then
snap restart ${SNAP_NAME}.mongodb 2>/dev/null || true
fi
endscript
}
# Wekan application logs
${WEKAN_APP_LOG} {
daily
missingok
rotate ${KEEP_COPIES}
compress
delaycompress
notifempty
create 644 root root
postrotate
# Send SIGUSR1 to Wekan application to reopen log file
if [ -f "${SNAP_COMMON}/wekan.pid" ]; then
kill -USR1 \$(cat "${SNAP_COMMON}/wekan.pid") 2>/dev/null || true
fi
# Alternative: restart Wekan service if PID file doesn't exist
if [ ! -f "${SNAP_COMMON}/wekan.pid" ]; then
snap restart ${SNAP_NAME}.wekan 2>/dev/null || true
fi
endscript
}
# Wekan error logs
${WEKAN_ERROR_LOG} {
daily
missingok
rotate ${KEEP_COPIES}
compress
delaycompress
notifempty
create 644 root root
postrotate
# Send SIGUSR1 to Wekan application to reopen log file
if [ -f "${SNAP_COMMON}/wekan.pid" ]; then
kill -USR1 \$(cat "${SNAP_COMMON}/wekan.pid") 2>/dev/null || true
fi
# Alternative: restart Wekan service if PID file doesn't exist
if [ ! -f "${SNAP_COMMON}/wekan.pid" ]; then
snap restart ${SNAP_NAME}.wekan 2>/dev/null || true
fi
endscript
}
# Size-based rotation for large log files
${SNAP_COMMON}/*.log {
size ${ROTATE_SIZE}
missingok
rotate ${KEEP_COPIES}
compress
delaycompress
notifempty
create 644 root root
sharedscripts
postrotate
# Generic postrotate for all log files
# Try to signal processes to reopen log files
for pidfile in "${SNAP_COMMON}"/*.pid; do
if [ -f "\$pidfile" ]; then
kill -USR1 \$(cat "\$pidfile") 2>/dev/null || true
fi
done
# Restart services if no PID files found
if [ ! -f "${SNAP_COMMON}/mongodb.pid" ] && [ ! -f "${SNAP_COMMON}/wekan.pid" ]; then
snap restart ${SNAP_NAME}.mongodb 2>/dev/null || true
snap restart ${SNAP_NAME}.wekan 2>/dev/null || true
fi
endscript
}
EOF
log_message "Created logrotate configuration: ${WEKAN_LOGROTATE_CONF}"
# Test logrotate configuration
if logrotate -d "${WEKAN_LOGROTATE_CONF}" >/dev/null 2>&1; then
log_message "Logrotate configuration test passed"
else
log_error "Logrotate configuration test failed"
exit 1
fi
# Create log directory if it doesn't exist
mkdir -p "${SNAP_COMMON}"
# Set proper permissions
chown root:root "${WEKAN_LOGROTATE_CONF}"
chmod 644 "${WEKAN_LOGROTATE_CONF}"
# Create initial log files if they don't exist
touch "${MONGODB_LOG}" "${WEKAN_APP_LOG}" "${WEKAN_ERROR_LOG}"
chown root:root "${SNAP_COMMON}"/*.log
chmod 644 "${SNAP_COMMON}"/*.log
log_message "Log rotation setup completed successfully"
log_message "Configuration file: ${WEKAN_LOGROTATE_CONF}"
log_message "Log files will be rotated daily and when they exceed ${ROTATE_SIZE}"
log_message "Log files will be kept for ${KEEP_DAYS} days (${KEEP_COPIES} copies)"
log_message "To test log rotation manually: sudo logrotate -f ${WEKAN_LOGROTATE_CONF}"
log_message "To view logrotate status: sudo logrotate -d ${WEKAN_LOGROTATE_CONF}"
echo ""
echo "Next steps:"
echo "1. Configure MongoDB to log to file: sudo snap set ${SNAP_NAME} mongo-log-destination=snapcommon"
echo "2. Configure Wekan to log to file (if not already done)"
echo "3. Test log rotation: sudo logrotate -f ${WEKAN_LOGROTATE_CONF}"
echo "4. Monitor log files: ls -la ${SNAP_COMMON}/*.log*"

View file

@ -77,6 +77,11 @@ log_success() {
log_message "SUCCESS: $message"
}
log_warning() {
local message="$1"
log_message "WARNING: $message"
}
# Disk space checking functions
check_disk_space() {
local required_space_gb="$1"
@ -222,6 +227,28 @@ check_migration_needed() {
return 1
}
# Display MongoDB log content for debugging
display_mongodb_log_content() {
local mongodb_log="${SNAP_COMMON}/mongodb.log"
if [ ! -f "$mongodb_log" ]; then
log_message "MongoDB log file not found: $mongodb_log"
return 1
fi
log_message "MongoDB log file content (last 50 lines):"
if [ -r "$mongodb_log" ]; then
tail -50 "$mongodb_log" | while read -r line; do
log_message "LOG: $line"
done
else
log_message "MongoDB log file not readable, trying with sudo"
sudo tail -50 "$mongodb_log" 2>/dev/null | while read -r line; do
log_message "LOG: $line"
done
fi
}
# Detect if MongoDB upgrade is needed by checking log file
detect_mongodb_upgrade_needed() {
local mongodb_log="${SNAP_COMMON}/mongodb.log"
@ -232,20 +259,168 @@ detect_mongodb_upgrade_needed() {
return 1
fi
# Check for the specific error message indicating upgrade is needed
if grep -q "This version of MongoDB is too recent to start up on the existing data files. Try MongoDB 4.2 or earlier." "$mongodb_log"; then
log_message "MongoDB upgrade needed detected in log file"
# Display log content for debugging
display_mongodb_log_content
# Check file permissions and try to read with appropriate method
if [ ! -r "$mongodb_log" ]; then
log_message "MongoDB log file not readable, trying with sudo"
# Try to read with sudo if not readable
if ! sudo grep -q "too recent to start up on the existing data files" "$mongodb_log" 2>/dev/null; then
log_message "No MongoDB upgrade needed detected in log file (via sudo)"
return 1
fi
else
# Check for various error messages that indicate upgrade is needed
# The exact message may vary between MongoDB versions
local upgrade_patterns=(
"This version of MongoDB is too recent to start up on the existing data files"
"too recent to start up on the existing data files"
"Try MongoDB 4.2 or earlier"
"unsupported format version"
"data files are incompatible"
"database files are incompatible"
"version too new"
"version too recent"
)
local found_upgrade_needed=false
for pattern in "${upgrade_patterns[@]}"; do
if grep -q "$pattern" "$mongodb_log" 2>/dev/null; then
log_message "Found upgrade pattern in log: '$pattern'"
found_upgrade_needed=true
break
fi
done
if [ "$found_upgrade_needed" = false ]; then
log_message "No MongoDB upgrade needed detected in log file"
return 1
fi
fi
log_message "MongoDB upgrade needed detected in log file"
return 0
}
# Log rotation function for MongoDB logs
rotate_mongodb_logs() {
local mongodb_log="${SNAP_COMMON}/mongodb.log"
local max_size_mb=100
local keep_copies=10
# Check if log file exists and is large enough to rotate
if [ ! -f "$mongodb_log" ]; then
log_message "MongoDB log file not found, skipping rotation"
return 0
fi
# Also check for similar error messages that might indicate upgrade issues
if grep -q "too recent to start up on the existing data files" "$mongodb_log"; then
log_message "MongoDB upgrade needed detected in log file (alternative message)"
# Get log file size in MB
local log_size_mb=$(du -m "$mongodb_log" | cut -f1)
if [ "$log_size_mb" -lt "$max_size_mb" ]; then
log_message "MongoDB log size (${log_size_mb}MB) is below rotation threshold (${max_size_mb}MB)"
return 0
fi
log_message "No MongoDB upgrade needed detected in log file"
return 1
log_message "Rotating MongoDB log file (size: ${log_size_mb}MB)"
# Create rotated log file with timestamp
local timestamp=$(date +%Y%m%d-%H%M%S)
local rotated_log="${mongodb_log}.${timestamp}"
# Copy current log to rotated file
if cp "$mongodb_log" "$rotated_log"; then
log_message "Created rotated log file: $rotated_log"
# Truncate original log file
if > "$mongodb_log"; then
log_message "Truncated original log file"
else
log_error "Failed to truncate original log file"
return 1
fi
# Compress rotated log file
if gzip "$rotated_log"; then
log_message "Compressed rotated log file: ${rotated_log}.gz"
else
log_warning "Failed to compress rotated log file"
fi
# Clean up old rotated logs (keep only specified number)
local old_logs=$(ls -t "${mongodb_log}".* 2>/dev/null | tail -n +$((keep_copies + 1)))
if [ -n "$old_logs" ]; then
echo "$old_logs" | xargs rm -f
log_message "Cleaned up old rotated log files"
fi
log_success "MongoDB log rotation completed successfully"
return 0
else
log_error "Failed to create rotated log file"
return 1
fi
}
# Enhanced log rotation function for migration logs
rotate_migration_logs() {
local migration_log="${SNAP_COMMON}/mongodb-migration-log.txt"
local max_size_mb=50
local keep_copies=5
# Check if migration log file exists and is large enough to rotate
if [ ! -f "$migration_log" ]; then
log_message "Migration log file not found, skipping rotation"
return 0
fi
# Get log file size in MB
local log_size_mb=$(du -m "$migration_log" | cut -f1)
if [ "$log_size_mb" -lt "$max_size_mb" ]; then
log_message "Migration log size (${log_size_mb}MB) is below rotation threshold (${max_size_mb}MB)"
return 0
fi
log_message "Rotating migration log file (size: ${log_size_mb}MB)"
# Create rotated log file with timestamp
local timestamp=$(date +%Y%m%d-%H%M%S)
local rotated_log="${migration_log}.${timestamp}"
# Copy current log to rotated file
if cp "$migration_log" "$rotated_log"; then
log_message "Created rotated migration log file: $rotated_log"
# Truncate original log file
if > "$migration_log"; then
log_message "Truncated original migration log file"
else
log_error "Failed to truncate original migration log file"
return 1
fi
# Compress rotated log file
if gzip "$rotated_log"; then
log_message "Compressed rotated migration log file: ${rotated_log}.gz"
else
log_warning "Failed to compress rotated migration log file"
fi
# Clean up old rotated logs (keep only specified number)
local old_logs=$(ls -t "${migration_log}".* 2>/dev/null | tail -n +$((keep_copies + 1)))
if [ -n "$old_logs" ]; then
echo "$old_logs" | xargs rm -f
log_message "Cleaned up old rotated migration log files"
fi
log_success "Migration log rotation completed successfully"
return 0
else
log_error "Failed to create rotated migration log file"
return 1
fi
}
# Reset MONGO_LOG_DESTINATION to devnull after successful migration
@ -493,6 +668,18 @@ perform_migration() {
log_message "Starting MongoDB migration from version 3 to 7"
# Rotate MongoDB logs before migration if needed
log_message "Checking if MongoDB log rotation is needed"
if ! rotate_mongodb_logs; then
log_warning "MongoDB log rotation failed, continuing with migration"
fi
# Rotate migration logs before migration if needed
log_message "Checking if migration log rotation is needed"
if ! rotate_migration_logs; then
log_warning "Migration log rotation failed, continuing with migration"
fi
# Create backup before migration
log_message "Creating backup before migration"
if ! create_backup; then
@ -572,6 +759,18 @@ EOF
log_success "MongoDB migration completed successfully"
# Rotate MongoDB logs after successful migration
log_message "Rotating MongoDB logs after successful migration"
if ! rotate_mongodb_logs; then
log_warning "MongoDB log rotation after migration failed"
fi
# Rotate migration logs after successful migration
log_message "Rotating migration logs after successful migration"
if ! rotate_migration_logs; then
log_warning "Migration log rotation after migration failed"
fi
# Reset MONGO_LOG_DESTINATION to devnull after successful migration
reset_mongo_log_destination