feat: split periodic system maintaneanse into smaller scripts

This commit is contained in:
Krzysztof Rudnicki 2025-09-06 14:16:17 +02:00
parent 8ddb573bd2
commit 0ade08c6e2
8 changed files with 320 additions and 296 deletions

View File

@ -68,6 +68,21 @@ echo "Pacman wrapper script: $PACMAN_WRAPPER_SCRIPT"
echo "Pacman wrapper installer: $PACMAN_WRAPPER_INSTALL"
echo "Hosts install script: $HOSTS_INSTALL_SCRIPT"
# Templates directory (version-controlled files)
TEMPLATES_BASE="$CONFIG_DIR/scripts/system-maintenance"
BIN_TEMPLATES="$TEMPLATES_BASE/bin"
SYSTEMD_TEMPLATES="$TEMPLATES_BASE/systemd"
LOGROTATE_TEMPLATES="$TEMPLATES_BASE/logrotate"
# Template files
TEMPLATE_MAINT_SCRIPT="$BIN_TEMPLATES/periodic-system-maintenance.sh"
TEMPLATE_HOSTS_MONITOR="$BIN_TEMPLATES/hosts-file-monitor.sh"
TEMPLATE_SVC_MAINT="$SYSTEMD_TEMPLATES/periodic-system-maintenance.service"
TEMPLATE_TIMER="$SYSTEMD_TEMPLATES/periodic-system-maintenance.timer"
TEMPLATE_STARTUP="$SYSTEMD_TEMPLATES/periodic-system-startup.service"
TEMPLATE_HOSTS_SVC="$SYSTEMD_TEMPLATES/hosts-file-monitor.service"
TEMPLATE_LOGROTATE="$LOGROTATE_TEMPLATES/periodic-system-maintenance"
# Function to verify required files exist
verify_files() {
echo ""
@ -88,6 +103,20 @@ verify_files() {
missing_files+=("$HOSTS_INSTALL_SCRIPT")
fi
# Check template files as well
for tmpl in \
"$TEMPLATE_MAINT_SCRIPT" \
"$TEMPLATE_HOSTS_MONITOR" \
"$TEMPLATE_SVC_MAINT" \
"$TEMPLATE_TIMER" \
"$TEMPLATE_STARTUP" \
"$TEMPLATE_HOSTS_SVC" \
"$TEMPLATE_LOGROTATE"; do
if [[ ! -f "$tmpl" ]]; then
missing_files+=("$tmpl")
fi
done
if [[ ${#missing_files[@]} -gt 0 ]]; then
echo "Error: The following required files are missing:"
for file in "${missing_files[@]}"; do
@ -106,59 +135,15 @@ create_execution_script() {
echo "======================================="
local exec_script="/usr/local/bin/periodic-system-maintenance.sh"
cat > "$exec_script" << EOF
#!/bin/bash
# Periodic system maintenance script
# Installs pacman wrapper and updates hosts file
# Created by setup_periodic_system.sh on $(date)
set -e
LOG_FILE="/var/log/periodic-system-maintenance.log"
# Function to log with timestamp
log_message() {
echo "\$(date '+%Y-%m-%d %H:%M:%S') - \$1" >> "\$LOG_FILE"
}
# Function to execute with logging
execute_with_log() {
local script_path="\$1"
local script_name="\$2"
log_message "Starting \$script_name"
echo "Executing \$script_name..." >&2
if [[ -f "\$script_path" ]]; then
if bash "\$script_path" >> "\$LOG_FILE" 2>&1; then
log_message "\$script_name completed successfully"
echo "✓ \$script_name completed successfully" >&2
else
log_message "\$script_name failed with exit code \$?"
echo "✗ \$script_name failed" >&2
fi
else
log_message "\$script_name not found at \$script_path"
echo "✗ \$script_name not found at \$script_path" >&2
fi
}
# Start maintenance
log_message "=== Periodic System Maintenance Started ==="
# Install pacman wrapper
execute_with_log "$PACMAN_WRAPPER_INSTALL" "Pacman Wrapper Installation"
# Update hosts file
execute_with_log "$HOSTS_INSTALL_SCRIPT" "Hosts File Update"
log_message "=== Periodic System Maintenance Completed ==="
echo "Periodic system maintenance completed. Check $LOG_FILE for details." >&2
EOF
# Install from template with path substitutions
sed \
-e "s|__PACMAN_WRAPPER_INSTALL__|$PACMAN_WRAPPER_INSTALL|g" \
-e "s|__HOSTS_INSTALL_SCRIPT__|$HOSTS_INSTALL_SCRIPT|g" \
"$TEMPLATE_MAINT_SCRIPT" > "$exec_script"
chmod +x "$exec_script"
echo "Created execution script: $exec_script"
echo "✓ Installed execution script from template: $exec_script"
}
# Function to create systemd service
@ -168,32 +153,8 @@ create_systemd_service() {
echo "============================="
local service_file="/etc/systemd/system/periodic-system-maintenance.service"
cat > "$service_file" << EOF
[Unit]
Description=Periodic System Maintenance (Pacman Wrapper & Hosts File)
After=network-online.target
Wants=network-online.target
[Service]
Type=oneshot
User=root
ExecStart=/usr/local/bin/periodic-system-maintenance.sh
StandardOutput=journal
StandardError=journal
# Timeout settings
TimeoutStartSec=300
TimeoutStopSec=30
# Restart settings
Restart=no
[Install]
WantedBy=multi-user.target
EOF
echo "✓ Created systemd service: $service_file"
install -m 0644 "$TEMPLATE_SVC_MAINT" "$service_file"
echo "✓ Installed systemd service from template: $service_file"
}
# Function to create systemd timer for hourly execution
@ -203,27 +164,8 @@ create_systemd_timer() {
echo "============================"
local timer_file="/etc/systemd/system/periodic-system-maintenance.timer"
cat > "$timer_file" << EOF
[Unit]
Description=Run Periodic System Maintenance every hour
Requires=periodic-system-maintenance.service
[Timer]
# Run every hour
OnCalendar=hourly
# Run on system startup (5 minutes after boot)
OnBootSec=5min
# Add randomization to prevent all systems from running simultaneously
RandomizedDelaySec=300
# Ensure timer persists across reboots
Persistent=true
[Install]
WantedBy=timers.target
EOF
echo "✓ Created systemd timer: $timer_file"
install -m 0644 "$TEMPLATE_TIMER" "$timer_file"
echo "✓ Installed systemd timer from template: $timer_file"
}
# Function to create startup service (additional to timer)
@ -233,30 +175,8 @@ create_startup_service() {
echo "=============================="
local startup_service="/etc/systemd/system/periodic-system-startup.service"
cat > "$startup_service" << EOF
[Unit]
Description=System Maintenance on Startup (Pacman Wrapper & Hosts File)
After=network-online.target systemd-resolved.service
Wants=network-online.target
[Service]
Type=oneshot
User=root
ExecStart=/usr/local/bin/periodic-system-maintenance.sh
StandardOutput=journal
StandardError=journal
RemainAfterExit=yes
# Timeout settings
TimeoutStartSec=300
TimeoutStopSec=30
[Install]
WantedBy=multi-user.target
EOF
echo "✓ Created startup service: $startup_service"
install -m 0644 "$TEMPLATE_STARTUP" "$startup_service"
echo "✓ Installed startup service from template: $startup_service"
}
# Function to create hosts file monitor service
@ -267,154 +187,16 @@ create_hosts_monitor_service() {
local monitor_script="/usr/local/bin/hosts-file-monitor.sh"
local monitor_service="/etc/systemd/system/hosts-file-monitor.service"
# Create the monitor script
cat > "$monitor_script" << EOF
#!/bin/bash
# Hosts file monitor script
# Watches /etc/hosts for changes and restores it if needed
# Created by setup_periodic_system.sh on $(date)
LOG_FILE="/var/log/hosts-file-monitor.log"
HOSTS_FILE="/etc/hosts"
HOSTS_INSTALL_SCRIPT="$HOSTS_INSTALL_SCRIPT"
# Function to log with timestamp
log_message() {
echo "\$(date '+%Y-%m-%d %H:%M:%S') - \$1" >> "\$LOG_FILE"
echo "\$(date '+%Y-%m-%d %H:%M:%S') - \$1" >&2
}
# Function to check if hosts file needs restoration
needs_restoration() {
# Check if file exists
if [[ ! -f "\$HOSTS_FILE" ]]; then
return 0 # File missing, needs restoration
fi
# Check if file is empty or too small (less than 1000 lines indicates tampering)
local line_count=\$(wc -l < "\$HOSTS_FILE" 2>/dev/null || echo "0")
if [[ \$line_count -lt 1000 ]]; then
return 0 # File too small, likely tampered with
fi
# Check if our custom entries are missing
if ! grep -q "Custom blocking entries" "\$HOSTS_FILE" 2>/dev/null; then
return 0 # Our custom entries missing, needs restoration
fi
# Check if StevenBlack entries are missing
if ! grep -q "StevenBlack" "\$HOSTS_FILE" 2>/dev/null; then
return 0 # StevenBlack entries missing, needs restoration
fi
return 1 # File seems intact
}
# Function to restore hosts file
restore_hosts_file() {
log_message "Hosts file modification detected - initiating restoration"
if [[ -f "\$HOSTS_INSTALL_SCRIPT" ]]; then
log_message "Running hosts installation script: \$HOSTS_INSTALL_SCRIPT"
if bash "\$HOSTS_INSTALL_SCRIPT" >> "\$LOG_FILE" 2>&1; then
log_message "Hosts file restoration completed successfully"
else
log_message "Hosts file restoration failed with exit code \$?"
fi
else
log_message "ERROR: Hosts install script not found at \$HOSTS_INSTALL_SCRIPT"
fi
}
# Function to monitor with inotifywait
monitor_with_inotify() {
log_message "Starting hosts file monitoring with inotify"
# Monitor the hosts file and its directory for various events
inotifywait -m -e delete,move,modify,attrib,create --format '%w%f %e %T' --timefmt '%Y-%m-%d %H:%M:%S' "\$HOSTS_FILE" /etc/ 2>/dev/null | \
while read file event time; do
# Check if the event is related to our hosts file
if [[ "\$file" == "\$HOSTS_FILE" ]] || [[ "\$file" == "/etc/hosts" ]]; then
log_message "Event detected: \$event on \$file at \$time"
# Small delay to avoid rapid-fire events
sleep 2
# Check if restoration is needed
if needs_restoration; then
restore_hosts_file
else
log_message "Hosts file check passed - no restoration needed"
fi
fi
done
}
# Function to monitor with polling (fallback)
monitor_with_polling() {
log_message "Starting hosts file monitoring with polling (fallback method)"
while true; do
if needs_restoration; then
restore_hosts_file
fi
# Check every 30 seconds
sleep 30
done
}
# Main execution
log_message "=== Hosts File Monitor Started ==="
# Check if inotify-tools is available
if command -v inotifywait >/dev/null 2>&1; then
log_message "Using inotify for file monitoring"
monitor_with_inotify
else
log_message "inotify-tools not available, using polling method"
log_message "Consider installing inotify-tools for better performance: pacman -S inotify-tools"
monitor_with_polling
fi
EOF
# Install the monitor script from template with substitution
sed -e "s|__HOSTS_INSTALL_SCRIPT__|$HOSTS_INSTALL_SCRIPT|g" \
"$TEMPLATE_HOSTS_MONITOR" > "$monitor_script"
chmod +x "$monitor_script"
echo "✓ Created hosts monitor script: $monitor_script"
# Create the systemd service
cat > "$monitor_service" << EOF
[Unit]
Description=Hosts File Monitor and Auto-Restore Service
After=network-online.target
Wants=network-online.target
echo "✓ Installed hosts monitor script from template: $monitor_script"
[Service]
Type=simple
User=root
ExecStart=$monitor_script
Restart=always
RestartSec=10
StandardOutput=journal
StandardError=journal
# Environment
Environment=PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
# Security settings
NoNewPrivileges=false
PrivateTmp=true
# Resource limits
MemoryLimit=50M
CPUQuota=10%
[Install]
WantedBy=multi-user.target
EOF
echo "✓ Created hosts monitor service: $monitor_service"
# Install the systemd service from template
install -m 0644 "$TEMPLATE_HOSTS_SVC" "$monitor_service"
echo "✓ Installed hosts monitor service from template: $monitor_service"
}
# Function to enable and start services
@ -462,36 +244,8 @@ create_log_rotation() {
echo "============================="
local logrotate_conf="/etc/logrotate.d/periodic-system-maintenance"
cat > "$logrotate_conf" << EOF
/var/log/periodic-system-maintenance.log {
weekly
rotate 4
compress
delaycompress
missingok
notifempty
create 644 root root
postrotate
systemctl reload-or-restart rsyslog > /dev/null 2>&1 || true
endscript
}
/var/log/hosts-file-monitor.log {
weekly
rotate 4
compress
delaycompress
missingok
notifempty
create 644 root root
postrotate
systemctl reload-or-restart rsyslog > /dev/null 2>&1 || true
endscript
}
EOF
echo "✓ Created log rotation configuration: $logrotate_conf"
install -m 0644 "$TEMPLATE_LOGROTATE" "$logrotate_conf"
echo "✓ Installed log rotation configuration from template: $logrotate_conf"
}
# Function to run initial execution

View File

@ -0,0 +1,110 @@
#!/bin/bash
# Hosts file monitor script
# Watches /etc/hosts for changes and restores it if needed
# This file is installed by setup_periodic_system.sh
set -euo pipefail
LOG_FILE="/var/log/hosts-file-monitor.log"
HOSTS_FILE="/etc/hosts"
HOSTS_INSTALL_SCRIPT="__HOSTS_INSTALL_SCRIPT__"
# Function to log with timestamp
log_message() {
echo "$(date '+%Y-%m-%d %H:%M:%S') - $1" | tee -a "$LOG_FILE" >&2
}
# Function to check if hosts file needs restoration
needs_restoration() {
# Check if file exists
if [[ ! -f "$HOSTS_FILE" ]]; then
return 0 # File missing, needs restoration
fi
# Check if file is empty or too small (less than 1000 lines indicates tampering)
local line_count
line_count=$(wc -l < "$HOSTS_FILE" 2>/dev/null || echo "0")
if [[ "$line_count" -lt 1000 ]]; then
return 0 # File too small, likely tampered with
fi
# Check if our custom entries are missing
if ! grep -q "Custom blocking entries" "$HOSTS_FILE" 2>/dev/null; then
return 0 # Our custom entries missing, needs restoration
fi
# Check if StevenBlack entries are missing
if ! grep -q "StevenBlack" "$HOSTS_FILE" 2>/dev/null; then
return 0 # StevenBlack entries missing, needs restoration
fi
return 1 # File seems intact
}
# Function to restore hosts file
restore_hosts_file() {
log_message "Hosts file modification detected - initiating restoration"
if [[ -f "$HOSTS_INSTALL_SCRIPT" ]]; then
log_message "Running hosts installation script: $HOSTS_INSTALL_SCRIPT"
if bash "$HOSTS_INSTALL_SCRIPT" >> "$LOG_FILE" 2>&1; then
log_message "Hosts file restoration completed successfully"
else
log_message "Hosts file restoration failed with exit code $?"
fi
else
log_message "ERROR: Hosts install script not found at $HOSTS_INSTALL_SCRIPT"
fi
}
# Function to monitor with inotifywait
monitor_with_inotify() {
log_message "Starting hosts file monitoring with inotify"
# Monitor the hosts file and its directory for various events
inotifywait -m -e delete,move,modify,attrib,create --format '%w%f %e %T' --timefmt '%Y-%m-%d %H:%M:%S' "$HOSTS_FILE" /etc/ 2>/dev/null | \
while read -r file event time; do
# Check if the event is related to our hosts file
if [[ "$file" == "$HOSTS_FILE" ]] || [[ "$file" == "/etc/hosts" ]]; then
log_message "Event detected: $event on $file at $time"
# Small delay to avoid rapid-fire events
sleep 2
# Check if restoration is needed
if needs_restoration; then
restore_hosts_file
else
log_message "Hosts file check passed - no restoration needed"
fi
fi
done
}
# Function to monitor with polling (fallback)
monitor_with_polling() {
log_message "Starting hosts file monitoring with polling (fallback method)"
while true; do
if needs_restoration; then
restore_hosts_file
fi
# Check every 30 seconds
sleep 30
done
}
# Main execution
log_message "=== Hosts File Monitor Started ==="
# Check if inotify-tools is available
if command -v inotifywait >/dev/null 2>&1; then
log_message "Using inotify for file monitoring"
monitor_with_inotify
else
log_message "inotify-tools not available, using polling method"
log_message "Consider installing inotify-tools for better performance: pacman -S inotify-tools"
monitor_with_polling
fi

View File

@ -0,0 +1,52 @@
#!/bin/bash
# Periodic system maintenance script
# Installs pacman wrapper and updates hosts file
# This file is installed by setup_periodic_system.sh
set -e
LOG_FILE="/var/log/periodic-system-maintenance.log"
# Path placeholders replaced at install time
PACMAN_WRAPPER_INSTALL="__PACMAN_WRAPPER_INSTALL__"
HOSTS_INSTALL_SCRIPT="__HOSTS_INSTALL_SCRIPT__"
# Function to log with timestamp
log_message() {
echo "$(date '+%Y-%m-%d %H:%M:%S') - $1" >> "$LOG_FILE"
}
# Function to execute with logging
execute_with_log() {
local script_path="$1"
local script_name="$2"
log_message "Starting $script_name"
echo "Executing $script_name..." >&2
if [[ -f "$script_path" ]]; then
if bash "$script_path" >> "$LOG_FILE" 2>&1; then
log_message "$script_name completed successfully"
echo "$script_name completed successfully" >&2
else
local ec=$?
log_message "$script_name failed with exit code $ec"
echo "$script_name failed (exit $ec)" >&2
fi
else
log_message "$script_name not found at $script_path"
echo "$script_name not found at $script_path" >&2
fi
}
# Start maintenance
log_message "=== Periodic System Maintenance Started ==="
# Install pacman wrapper
execute_with_log "$PACMAN_WRAPPER_INSTALL" "Pacman Wrapper Installation"
# Update hosts file
execute_with_log "$HOSTS_INSTALL_SCRIPT" "Hosts File Update"
log_message "=== Periodic System Maintenance Completed ==="
echo "Periodic system maintenance completed. Check $LOG_FILE for details." >&2

View File

@ -0,0 +1,25 @@
/var/log/periodic-system-maintenance.log {
weekly
rotate 4
compress
delaycompress
missingok
notifempty
create 644 root root
postrotate
systemctl reload-or-restart rsyslog > /dev/null 2>&1 || true
endscript
}
/var/log/hosts-file-monitor.log {
weekly
rotate 4
compress
delaycompress
missingok
notifempty
create 644 root root
postrotate
systemctl reload-or-restart rsyslog > /dev/null 2>&1 || true
endscript
}

View File

@ -0,0 +1,27 @@
[Unit]
Description=Hosts File Monitor and Auto-Restore Service
After=network-online.target
Wants=network-online.target
[Service]
Type=simple
User=root
ExecStart=/usr/local/bin/hosts-file-monitor.sh
Restart=always
RestartSec=10
StandardOutput=journal
StandardError=journal
# Environment
Environment=PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
# Security settings
NoNewPrivileges=false
PrivateTmp=true
# Resource limits
MemoryMax=50M
CPUQuota=10%
[Install]
WantedBy=multi-user.target

View File

@ -0,0 +1,21 @@
[Unit]
Description=Periodic System Maintenance (Pacman Wrapper & Hosts File)
After=network-online.target
Wants=network-online.target
[Service]
Type=oneshot
User=root
ExecStart=/usr/local/bin/periodic-system-maintenance.sh
StandardOutput=journal
StandardError=journal
# Timeout settings
TimeoutStartSec=300
TimeoutStopSec=30
# Restart settings
Restart=no
[Install]
WantedBy=multi-user.target

View File

@ -0,0 +1,16 @@
[Unit]
Description=Run Periodic System Maintenance every hour
Requires=periodic-system-maintenance.service
[Timer]
# Run every hour
OnCalendar=hourly
# Run on system startup (5 minutes after boot)
OnBootSec=5min
# Add randomization to prevent all systems from running simultaneously
RandomizedDelaySec=300
# Ensure timer persists across reboots
Persistent=true
[Install]
WantedBy=timers.target

View File

@ -0,0 +1,19 @@
[Unit]
Description=System Maintenance on Startup (Pacman Wrapper & Hosts File)
After=network-online.target systemd-resolved.service
Wants=network-online.target
[Service]
Type=oneshot
User=root
ExecStart=/usr/local/bin/periodic-system-maintenance.sh
StandardOutput=journal
StandardError=journal
RemainAfterExit=yes
# Timeout settings
TimeoutStartSec=300
TimeoutStopSec=30
[Install]
WantedBy=multi-user.target