Add shutdown timer monitor service to prevent disabling

- Remove 'disable' option from setup_midnight_shutdown.sh
- Add shutdown-timer-monitor.sh that watches the timer every 30s
- Re-enables timer automatically if someone tries to disable it
- Monitor service installed alongside the timer
- Makes it significantly harder to bypass the shutdown schedule
- Similar pattern to hosts-file-monitor.service
This commit is contained in:
Krzysztof kuhy Rudnicki 2025-12-07 14:08:13 +01:00
parent 4cb3a62491
commit a1b9200d19
3 changed files with 559 additions and 337 deletions

View File

@ -8,186 +8,132 @@ set -e # Exit on any error
# Function to show usage
show_usage() {
echo "Day-Specific Auto-Shutdown Setup for Arch Linux"
echo "==============================================="
echo "Usage: $0 [enable|disable|status]"
echo ""
echo "Commands:"
echo " enable - Set up automatic shutdown with day-specific windows (default)"
echo " disable - Remove automatic shutdown"
echo " status - Show current status"
echo ""
echo "Shutdown Schedule:"
echo " Monday-Wednesday: 21:00-05:00"
echo " Thursday-Sunday: 22:00-05:00"
echo ""
echo "Day-Specific Auto-Shutdown Setup for Arch Linux"
echo "==============================================="
echo "Usage: $0 [enable|status]"
echo ""
echo "Commands:"
echo " enable - Set up automatic shutdown with day-specific windows (default)"
echo " status - Show current status"
echo ""
echo "Shutdown Schedule:"
echo " Monday-Wednesday: 21:00-05:00"
echo " Thursday-Sunday: 22:00-05:00"
echo ""
echo "NOTE: There is no 'disable' option. This is intentional."
echo " The shutdown timer is protected by a monitor service."
echo ""
}
# Function to check and request sudo privileges
check_sudo() {
if [[ $EUID -ne 0 ]]; then
echo "This script requires sudo privileges to manage systemd services."
echo "Requesting sudo access..."
exec sudo "$0" "$@"
fi
if [[ $EUID -ne 0 ]]; then
echo "This script requires sudo privileges to manage systemd services."
echo "Requesting sudo access..."
exec sudo "$0" "$@"
fi
}
# Get the actual user (even when running with sudo)
if [[ -n $SUDO_USER ]]; then
ACTUAL_USER="$SUDO_USER"
USER_HOME="/home/$SUDO_USER"
ACTUAL_USER="$SUDO_USER"
USER_HOME="/home/$SUDO_USER"
else
ACTUAL_USER="$USER"
USER_HOME="$HOME"
ACTUAL_USER="$USER"
USER_HOME="$HOME"
fi
# Function to disable and remove midnight shutdown
disable_midnight_shutdown() {
echo "Disabling Day-Specific Auto-Shutdown"
echo "===================================="
echo "Current Date: $(date)"
echo "User: $ACTUAL_USER"
echo ""
local timer_file="/etc/systemd/system/day-specific-shutdown.timer"
local service_file="/etc/systemd/system/day-specific-shutdown.service"
local script_file="/usr/local/bin/day-specific-shutdown-manager.sh"
local check_script="/usr/local/bin/day-specific-shutdown-check.sh"
local removed_files=()
# Stop and disable timer if it exists
if systemctl is-active day-specific-shutdown.timer &> /dev/null; then
echo "Stopping day-specific-shutdown timer..."
systemctl stop day-specific-shutdown.timer
echo "✓ Timer stopped"
fi
if systemctl is-enabled day-specific-shutdown.timer &> /dev/null; then
echo "Disabling day-specific-shutdown timer..."
systemctl disable day-specific-shutdown.timer
echo "✓ Timer disabled"
fi
# Remove timer file
if [[ -f $timer_file ]]; then
rm -f "$timer_file"
removed_files+=("$timer_file")
echo "✓ Removed timer file: $timer_file"
fi
# Remove service file
if [[ -f $service_file ]]; then
rm -f "$service_file"
removed_files+=("$service_file")
echo "✓ Removed service file: $service_file"
fi
# Remove management script
if [[ -f $script_file ]]; then
rm -f "$script_file"
removed_files+=("$script_file")
echo "✓ Removed management script: $script_file"
fi
# Remove check script
if [[ -f $check_script ]]; then
rm -f "$check_script"
removed_files+=("$check_script")
echo "✓ Removed check script: $check_script"
fi
# Reload systemd daemon
if [[ ${#removed_files[@]} -gt 0 ]]; then
echo "Reloading systemd daemon..."
systemctl daemon-reload
echo "✓ Systemd daemon reloaded"
fi
echo ""
echo "============================================="
echo "Day-Specific Auto-Shutdown Removal Complete"
echo "============================================="
if [[ ${#removed_files[@]} -gt 0 ]]; then
echo "Removed files:"
printf " %s\n" "${removed_files[@]}"
echo ""
echo "✓ Automatic day-specific shutdown has been completely disabled"
echo "✓ Your PC will no longer shutdown automatically"
else
echo "No day-specific shutdown configuration was found to remove."
fi
echo ""
}
# Function to show current status
show_current_status() {
echo "Day-Specific Auto-Shutdown Status"
echo "================================="
echo "Current Date: $(date)"
echo "User: $ACTUAL_USER"
echo ""
echo "Day-Specific Auto-Shutdown Status"
echo "================================="
echo "Current Date: $(date)"
echo "User: $ACTUAL_USER"
echo ""
local timer_exists=false
local timer_exists=false
# Check if files exist
if [[ -f "/etc/systemd/system/day-specific-shutdown.timer" ]]; then
timer_exists=true
echo "✓ Timer file exists"
else
echo "✗ Timer file missing"
fi
# Check if files exist
if [[ -f "/etc/systemd/system/day-specific-shutdown.timer" ]]; then
timer_exists=true
echo "✓ Timer file exists"
else
echo "✗ Timer file missing"
fi
if [[ -f "/etc/systemd/system/day-specific-shutdown.service" ]]; then
echo "✓ Service file exists"
else
echo "✗ Service file missing"
fi
if [[ -f "/etc/systemd/system/day-specific-shutdown.service" ]]; then
echo "✓ Service file exists"
else
echo "✗ Service file missing"
fi
if [[ -f "/usr/local/bin/day-specific-shutdown-manager.sh" ]]; then
echo "✓ Management script exists"
else
echo "✗ Management script missing"
fi
if [[ -f "/usr/local/bin/day-specific-shutdown-manager.sh" ]]; then
echo "✓ Management script exists"
else
echo "✗ Management script missing"
fi
echo ""
if [[ -f "/usr/local/bin/shutdown-timer-monitor.sh" ]]; then
echo "✓ Monitor script exists"
else
echo "✗ Monitor script missing"
fi
# Check systemd status
if $timer_exists; then
if systemctl is-enabled day-specific-shutdown.timer &> /dev/null; then
echo "✓ Timer is enabled"
if systemctl is-active day-specific-shutdown.timer &> /dev/null; then
echo "✓ Timer is active"
echo ""
echo "Next scheduled shutdown check:"
systemctl list-timers day-specific-shutdown.timer --no-pager 2> /dev/null | grep day-specific-shutdown || echo "Timer information not available"
else
echo "✗ Timer is not active"
fi
else
echo "✗ Timer is not enabled"
fi
else
echo "Status: NOT CONFIGURED"
fi
echo ""
echo ""
echo "Shutdown Schedule:"
echo " Monday-Wednesday: 21:00-05:00"
echo " Thursday-Sunday: 22:00-05:00"
echo ""
# Check systemd status
if $timer_exists; then
if systemctl is-enabled day-specific-shutdown.timer &>/dev/null; then
echo "✓ Timer is enabled"
if systemctl is-active day-specific-shutdown.timer &>/dev/null; then
echo "✓ Timer is active"
echo ""
echo "Next scheduled shutdown check:"
systemctl list-timers day-specific-shutdown.timer --no-pager 2>/dev/null | grep day-specific-shutdown || echo "Timer information not available"
else
echo "✗ Timer is not active"
fi
else
echo "✗ Timer is not enabled"
fi
else
echo "Status: NOT CONFIGURED"
fi
echo ""
# Check monitor service status
echo "Monitor Service Status:"
if systemctl is-enabled shutdown-timer-monitor.service &>/dev/null; then
echo "✓ Monitor is enabled"
if systemctl is-active shutdown-timer-monitor.service &>/dev/null; then
echo "✓ Monitor is active (will re-enable timer if disabled)"
else
echo "✗ Monitor is not active"
fi
else
echo "✗ Monitor is not enabled"
fi
echo ""
echo "Shutdown Schedule:"
echo " Monday-Wednesday: 21:00-05:00"
echo " Thursday-Sunday: 22:00-05:00"
echo ""
echo "NOTE: The shutdown timer is protected by a monitor service."
echo " If you try to disable the timer, it will be automatically re-enabled."
echo ""
}
# Function to create the shutdown service
create_shutdown_service() {
echo ""
echo "1. Creating Systemd Shutdown Service..."
echo "======================================"
echo ""
echo "1. Creating Systemd Shutdown Service..."
echo "======================================"
local service_file="/etc/systemd/system/day-specific-shutdown.service"
local service_file="/etc/systemd/system/day-specific-shutdown.service"
cat > "$service_file" << 'EOF'
cat >"$service_file" <<'EOF'
[Unit]
Description=Automatic PC shutdown with day-specific time windows
DefaultDependencies=false
@ -201,18 +147,18 @@ StandardOutput=journal
StandardError=journal
EOF
echo "✓ Created systemd service: $service_file"
echo "✓ Created systemd service: $service_file"
}
# Function to create the shutdown timer
create_shutdown_timer() {
echo ""
echo "2. Creating Systemd Shutdown Timer..."
echo "==================================="
echo ""
echo "2. Creating Systemd Shutdown Timer..."
echo "==================================="
local timer_file="/etc/systemd/system/day-specific-shutdown.timer"
local timer_file="/etc/systemd/system/day-specific-shutdown.timer"
cat > "$timer_file" << 'EOF'
cat >"$timer_file" <<'EOF'
[Unit]
Description=Timer for automatic PC shutdown with day-specific windows
Requires=day-specific-shutdown.service
@ -244,18 +190,18 @@ RandomizedDelaySec=0
WantedBy=timers.target
EOF
echo "✓ Created systemd timer: $timer_file"
echo "✓ Created systemd timer: $timer_file"
}
# Function to create management script
create_management_script() {
echo ""
echo "3. Creating Management Script..."
echo "=============================="
echo ""
echo "3. Creating Management Script..."
echo "=============================="
local script_file="/usr/local/bin/day-specific-shutdown-manager.sh"
local script_file="/usr/local/bin/day-specific-shutdown-manager.sh"
cat > "$script_file" << 'EOF'
cat >"$script_file" <<'EOF'
#!/bin/bash
# Day-Specific Auto-Shutdown Manager
# Provides easy management of the day-specific shutdown feature
@ -318,19 +264,19 @@ case "$1" in
esac
EOF
chmod +x "$script_file"
echo "✓ Created management script: $script_file"
chmod +x "$script_file"
echo "✓ Created management script: $script_file"
}
# Function to create smart shutdown check script
create_shutdown_check_script() {
echo ""
echo "4. Creating Smart Shutdown Check Script..."
echo "========================================"
echo ""
echo "4. Creating Smart Shutdown Check Script..."
echo "========================================"
local check_script="/usr/local/bin/day-specific-shutdown-check.sh"
local check_script="/usr/local/bin/day-specific-shutdown-check.sh"
cat > "$check_script" << 'EOF'
cat >"$check_script" <<'EOF'
#!/bin/bash
# Smart day-specific shutdown check script
# Different shutdown windows based on day of week:
@ -397,206 +343,324 @@ else
fi
EOF
chmod +x "$check_script"
echo "✓ Created smart shutdown check script: $check_script"
chmod +x "$check_script"
echo "✓ Created smart shutdown check script: $check_script"
}
# Function to enable the timer
enable_timer() {
echo ""
echo "5. Enabling Shutdown Timer..."
echo "============================"
echo ""
echo "5. Enabling Shutdown Timer..."
echo "============================"
# Reload systemd daemon
systemctl daemon-reload
echo "✓ Reloaded systemd daemon"
# Reload systemd daemon
systemctl daemon-reload
echo "✓ Reloaded systemd daemon"
# Enable the timer
systemctl enable day-specific-shutdown.timer
echo "✓ Enabled day-specific-shutdown timer"
# Enable the timer
systemctl enable day-specific-shutdown.timer
echo "✓ Enabled day-specific-shutdown timer"
# Start the timer
systemctl start day-specific-shutdown.timer
echo "✓ Started day-specific-shutdown timer"
# Start the timer
systemctl start day-specific-shutdown.timer
echo "✓ Started day-specific-shutdown timer"
}
# Function to install the monitor service
install_monitor_service() {
echo ""
echo "6. Installing Shutdown Timer Monitor Service..."
echo "=============================================="
local monitor_script="/usr/local/bin/shutdown-timer-monitor.sh"
local monitor_service="/etc/systemd/system/shutdown-timer-monitor.service"
# Create the monitor script
cat >"$monitor_script" <<'EOF'
#!/bin/bash
# Shutdown timer monitor script
# Watches the day-specific-shutdown timer and re-enables it if disabled
set -euo pipefail
LOG_FILE="/var/log/shutdown-timer-monitor.log"
TIMER_NAME="day-specific-shutdown.timer"
SERVICE_NAME="day-specific-shutdown.service"
CHECK_INTERVAL=30
log_message() {
echo "$(date '+%Y-%m-%d %H:%M:%S') - $1" | tee -a "$LOG_FILE" >&2
}
timer_needs_restoration() {
if ! systemctl is-enabled "$TIMER_NAME" &>/dev/null; then
log_message "Timer $TIMER_NAME is not enabled"
return 0
fi
if ! systemctl is-active "$TIMER_NAME" &>/dev/null; then
log_message "Timer $TIMER_NAME is not active"
return 0
fi
if [[ ! -f "/etc/systemd/system/$TIMER_NAME" ]]; then
log_message "Timer unit file missing"
return 0
fi
if [[ ! -f "/etc/systemd/system/$SERVICE_NAME" ]]; then
log_message "Service unit file missing"
return 0
fi
if [[ ! -f "/usr/local/bin/day-specific-shutdown-check.sh" ]]; then
log_message "Check script missing"
return 0
fi
return 1
}
restore_timer() {
log_message "Shutdown timer tampering detected - initiating restoration"
systemctl daemon-reload
if ! systemctl is-enabled "$TIMER_NAME" &>/dev/null; then
log_message "Re-enabling $TIMER_NAME"
systemctl enable "$TIMER_NAME" 2>/dev/null || true
fi
if ! systemctl is-active "$TIMER_NAME" &>/dev/null; then
log_message "Re-starting $TIMER_NAME"
systemctl start "$TIMER_NAME" 2>/dev/null || true
fi
if systemctl is-active "$TIMER_NAME" &>/dev/null; then
log_message "Timer restoration completed successfully"
else
log_message "WARNING: Timer restoration may have failed"
fi
}
log_message "=== Shutdown Timer Monitor Started ==="
log_message "Monitoring timer: $TIMER_NAME"
if timer_needs_restoration; then
log_message "Initial check: Timer needs restoration"
restore_timer
else
log_message "Initial check: Timer is properly configured"
fi
while true; do
if timer_needs_restoration; then
restore_timer
fi
sleep "$CHECK_INTERVAL"
done
EOF
chmod +x "$monitor_script"
echo "✓ Created monitor script: $monitor_script"
# Create the monitor service
cat >"$monitor_service" <<'EOF'
[Unit]
Description=Shutdown Timer Monitor and Auto-Restore Service
After=network-online.target day-specific-shutdown.timer
Wants=network-online.target
[Service]
Type=simple
User=root
ExecStart=/usr/local/bin/shutdown-timer-monitor.sh
Restart=always
RestartSec=10
StandardOutput=journal
StandardError=journal
Environment=PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
NoNewPrivileges=false
PrivateTmp=true
MemoryMax=50M
CPUQuota=10%
[Install]
WantedBy=multi-user.target
EOF
echo "✓ Created monitor service: $monitor_service"
# Reload and enable monitor
systemctl daemon-reload
systemctl enable shutdown-timer-monitor.service
systemctl start shutdown-timer-monitor.service
echo "✓ Enabled and started shutdown-timer-monitor.service"
}
# Function to test the setup
test_setup() {
echo ""
echo "6. Testing Setup..."
echo "=================="
echo ""
echo "7. Testing Setup..."
echo "=================="
echo "Service files:"
if [[ -f "/etc/systemd/system/day-specific-shutdown.service" ]]; then
echo "✓ Service file exists"
else
echo "✗ Service file missing"
fi
echo "Service files:"
if [[ -f "/etc/systemd/system/day-specific-shutdown.service" ]]; then
echo "✓ Service file exists"
else
echo "✗ Service file missing"
fi
if [[ -f "/etc/systemd/system/day-specific-shutdown.timer" ]]; then
echo "✓ Timer file exists"
else
echo "✗ Timer file missing"
fi
if [[ -f "/etc/systemd/system/day-specific-shutdown.timer" ]]; then
echo "✓ Timer file exists"
else
echo "✗ Timer file missing"
fi
echo ""
echo "Timer status:"
if systemctl is-enabled day-specific-shutdown.timer &> /dev/null; then
echo "✓ Timer is enabled"
else
echo "✗ Timer is not enabled"
fi
if [[ -f "/etc/systemd/system/shutdown-timer-monitor.service" ]]; then
echo "✓ Monitor service file exists"
else
echo "✗ Monitor service file missing"
fi
if systemctl is-active day-specific-shutdown.timer &> /dev/null; then
echo "✓ Timer is active"
else
echo "✗ Timer is not active"
fi
echo ""
echo "Timer status:"
if systemctl is-enabled day-specific-shutdown.timer &>/dev/null; then
echo "✓ Timer is enabled"
else
echo "✗ Timer is not enabled"
fi
echo ""
echo "Next scheduled checks:"
systemctl list-timers day-specific-shutdown.timer --no-pager 2> /dev/null | head -5 | grep day-specific-shutdown || echo "Timer information not available"
if systemctl is-active day-specific-shutdown.timer &>/dev/null; then
echo "✓ Timer is active"
else
echo "✗ Timer is not active"
fi
echo ""
echo "Monitor status:"
if systemctl is-enabled shutdown-timer-monitor.service &>/dev/null; then
echo "✓ Monitor is enabled"
else
echo "✗ Monitor is not enabled"
fi
if systemctl is-active shutdown-timer-monitor.service &>/dev/null; then
echo "✓ Monitor is active"
else
echo "✗ Monitor is not active"
fi
echo ""
echo "Next scheduled checks:"
systemctl list-timers day-specific-shutdown.timer --no-pager 2>/dev/null | head -5 | grep day-specific-shutdown || echo "Timer information not available"
}
# Function to show final instructions
show_instructions() {
echo ""
echo "================================================="
echo "Day-Specific Auto-Shutdown Setup Complete"
echo "================================================="
echo "Summary:"
echo "✓ Systemd service created (/etc/systemd/system/day-specific-shutdown.service)"
echo "✓ Systemd timer created (/etc/systemd/system/day-specific-shutdown.timer)"
echo "✓ Management script created (/usr/local/bin/day-specific-shutdown-manager.sh)"
echo "✓ Smart check script created (/usr/local/bin/day-specific-shutdown-check.sh)"
echo "✓ Timer enabled and started"
echo ""
echo "Shutdown Schedule:"
echo " Monday-Wednesday: 21:00-05:00 (9:00 PM to 5:00 AM)"
echo " Thursday-Sunday: 22:00-05:00 (10:00 PM to 5:00 AM)"
echo ""
echo "Management commands:"
echo " sudo day-specific-shutdown-manager.sh status - Check status"
echo " sudo day-specific-shutdown-manager.sh logs - View shutdown logs"
echo ""
echo "How it works:"
echo "• Timer checks every 30 minutes during potential shutdown windows"
echo "• Smart logic determines shutdown eligibility based on day and time"
echo "• Prevents accidental shutdowns outside designated time windows"
echo ""
echo "WARNING: This will automatically shutdown your PC during designated hours."
echo "Make sure to save your work before the shutdown windows!"
echo ""
echo ""
echo "================================================="
echo "Day-Specific Auto-Shutdown Setup Complete"
echo "================================================="
echo "Summary:"
echo "✓ Systemd service created (/etc/systemd/system/day-specific-shutdown.service)"
echo "✓ Systemd timer created (/etc/systemd/system/day-specific-shutdown.timer)"
echo "✓ Management script created (/usr/local/bin/day-specific-shutdown-manager.sh)"
echo "✓ Smart check script created (/usr/local/bin/day-specific-shutdown-check.sh)"
echo "✓ Timer enabled and started"
echo "✓ Monitor service installed and started (protects timer from being disabled)"
echo ""
echo "Shutdown Schedule:"
echo " Monday-Wednesday: 21:00-05:00 (9:00 PM to 5:00 AM)"
echo " Thursday-Sunday: 22:00-05:00 (10:00 PM to 5:00 AM)"
echo ""
echo "Management commands:"
echo " sudo day-specific-shutdown-manager.sh status - Check status"
echo " sudo day-specific-shutdown-manager.sh logs - View shutdown logs"
echo ""
echo "How it works:"
echo "• Timer checks every 30 minutes during potential shutdown windows"
echo "• Smart logic determines shutdown eligibility based on day and time"
echo "• Monitor service watches the timer and re-enables it if disabled"
echo "• There is NO disable option - this is intentional for digital wellbeing"
echo ""
echo "WARNING: This will automatically shutdown your PC during designated hours."
echo "Make sure to save your work before the shutdown windows!"
echo ""
}
# Function to prompt for confirmation
confirm_setup() {
echo ""
echo "WARNING: Day-Specific Auto-Shutdown Confirmation"
echo "==============================================="
echo "This will set up your PC to automatically shutdown during specific time windows."
echo ""
echo "Shutdown Schedule:"
echo " Monday-Wednesday: 21:00-05:00 (9:00 PM to 5:00 AM)"
echo " Thursday-Sunday: 22:00-05:00 (10:00 PM to 5:00 AM)"
echo ""
echo "Important considerations:"
echo "- Any unsaved work will be lost during shutdown windows"
echo "- Running processes will be terminated"
echo "- Downloads/uploads in progress will be interrupted"
echo "- You'll need to manually power on your PC each day"
echo "- Timer checks every 30 minutes during potential shutdown windows"
echo ""
read -r -p "Do you want to proceed? (y/N): " confirm
echo ""
echo "WARNING: Day-Specific Auto-Shutdown Confirmation"
echo "==============================================="
echo "This will set up your PC to automatically shutdown during specific time windows."
echo ""
echo "Shutdown Schedule:"
echo " Monday-Wednesday: 21:00-05:00 (9:00 PM to 5:00 AM)"
echo " Thursday-Sunday: 22:00-05:00 (10:00 PM to 5:00 AM)"
echo ""
echo "Important considerations:"
echo "- Any unsaved work will be lost during shutdown windows"
echo "- Running processes will be terminated"
echo "- Downloads/uploads in progress will be interrupted"
echo "- You'll need to manually power on your PC each day"
echo "- Timer checks every 30 minutes during potential shutdown windows"
echo "- There is NO disable option - this is protected by a monitor service"
echo ""
read -r -p "Do you want to proceed? (y/N): " confirm
case "$confirm" in
[yY] | [yY][eE][sS])
echo "Proceeding with setup..."
return 0
;;
*)
echo "Setup cancelled."
exit 0
;;
esac
}
# Function to confirm disable
confirm_disable() {
echo ""
echo "Disable Day-Specific Auto-Shutdown Confirmation"
echo "==============================================="
echo "This will completely remove the automatic day-specific shutdown configuration."
echo ""
echo "After disabling:"
echo "- Your PC will no longer shutdown automatically during any time windows"
echo "- All related systemd services and timers will be removed"
echo "- The management and check scripts will be deleted"
echo ""
read -r -p "Do you want to proceed with disabling? (y/N): " confirm
case "$confirm" in
[yY] | [yY][eE][sS])
echo "Proceeding with disable..."
return 0
;;
*)
echo "Disable cancelled."
exit 0
;;
esac
case "$confirm" in
[yY] | [yY][eE][sS])
echo "Proceeding with setup..."
return 0
;;
*)
echo "Setup cancelled."
exit 0
;;
esac
}
# Main execution flow for enable
enable_midnight_shutdown() {
echo "Day-Specific Auto-Shutdown Setup for Arch Linux"
echo "==============================================="
echo "Current Date: $(date)"
echo "User: $ACTUAL_USER"
echo "Target user: $ACTUAL_USER"
echo "User home: $USER_HOME"
echo "Day-Specific Auto-Shutdown Setup for Arch Linux"
echo "==============================================="
echo "Current Date: $(date)"
echo "User: $ACTUAL_USER"
echo "Target user: $ACTUAL_USER"
echo "User home: $USER_HOME"
# Confirm setup
confirm_setup
# Confirm setup
confirm_setup
# Create systemd files
create_shutdown_service
create_shutdown_timer
create_management_script
create_shutdown_check_script
# Create systemd files
create_shutdown_service
create_shutdown_timer
create_management_script
create_shutdown_check_script
# Enable and start timer
enable_timer
# Enable and start timer
enable_timer
# Test setup
test_setup
# Install monitor service (protects timer from being disabled)
install_monitor_service
# Show instructions
show_instructions
# Test setup
test_setup
# Show instructions
show_instructions
}
# Parse command line arguments
case "${1:-enable}" in
"enable")
check_sudo "$@"
enable_midnight_shutdown
;;
"disable")
check_sudo "$@"
confirm_disable
disable_midnight_shutdown
;;
"status")
check_sudo "$@"
show_current_status
;;
"help" | "-h" | "--help")
show_usage
;;
*)
echo "Error: Unknown command '$1'"
echo ""
show_usage
exit 1
;;
"enable")
check_sudo "$@"
enable_midnight_shutdown
;;
"status")
check_sudo "$@"
show_current_status
;;
"help" | "-h" | "--help")
show_usage
;;
*)
echo "Error: Unknown command '$1'"
echo ""
show_usage
exit 1
;;
esac

View File

@ -0,0 +1,131 @@
#!/bin/bash
# Shutdown timer monitor script
# Watches the day-specific-shutdown timer and re-enables it if disabled
# This file is installed by setup_midnight_shutdown.sh
set -euo pipefail
LOG_FILE="/var/log/shutdown-timer-monitor.log"
TIMER_NAME="day-specific-shutdown.timer"
SERVICE_NAME="day-specific-shutdown.service"
CHECK_INTERVAL=30
# 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 timer needs to be re-enabled
timer_needs_restoration() {
# Check if timer is enabled
if ! systemctl is-enabled "$TIMER_NAME" &>/dev/null; then
log_message "Timer $TIMER_NAME is not enabled"
return 0
fi
# Check if timer is active
if ! systemctl is-active "$TIMER_NAME" &>/dev/null; then
log_message "Timer $TIMER_NAME is not active"
return 0
fi
# Check if timer unit file exists
if [[ ! -f "/etc/systemd/system/$TIMER_NAME" ]]; then
log_message "Timer unit file missing: /etc/systemd/system/$TIMER_NAME"
return 0
fi
# Check if service unit file exists
if [[ ! -f "/etc/systemd/system/$SERVICE_NAME" ]]; then
log_message "Service unit file missing: /etc/systemd/system/$SERVICE_NAME"
return 0
fi
# Check if check script exists
if [[ ! -f "/usr/local/bin/day-specific-shutdown-check.sh" ]]; then
log_message "Check script missing: /usr/local/bin/day-specific-shutdown-check.sh"
return 0
fi
return 1 # Timer is properly configured
}
# Function to restore timer
restore_timer() {
log_message "Shutdown timer tampering detected - initiating restoration"
# Reload systemd daemon in case unit files were modified
systemctl daemon-reload
# Re-enable timer if disabled
if ! systemctl is-enabled "$TIMER_NAME" &>/dev/null; then
log_message "Re-enabling $TIMER_NAME"
systemctl enable "$TIMER_NAME" 2>/dev/null || true
fi
# Re-start timer if not active
if ! systemctl is-active "$TIMER_NAME" &>/dev/null; then
log_message "Re-starting $TIMER_NAME"
systemctl start "$TIMER_NAME" 2>/dev/null || true
fi
# Verify restoration
if systemctl is-active "$TIMER_NAME" &>/dev/null; then
log_message "Timer restoration completed successfully"
else
log_message "WARNING: Timer restoration may have failed"
fi
}
# Function to monitor timer with systemd events
monitor_with_dbus() {
log_message "Starting shutdown timer monitoring with D-Bus events"
# Use busctl to monitor systemd unit changes
# Fall back to polling if this fails
if command -v busctl &>/dev/null; then
# Monitor for unit state changes
busctl monitor --system org.freedesktop.systemd1 2>/dev/null |
while read -r line; do
# Check if the line mentions our timer
if echo "$line" | grep -q "$TIMER_NAME\|$SERVICE_NAME"; then
log_message "Systemd event detected for shutdown timer"
sleep 2
if timer_needs_restoration; then
restore_timer
fi
fi
done
else
log_message "busctl not available, falling back to polling"
monitor_with_polling
fi
}
# Function to monitor with polling (primary method for reliability)
monitor_with_polling() {
log_message "Starting shutdown timer monitoring with polling (interval: ${CHECK_INTERVAL}s)"
while true; do
if timer_needs_restoration; then
restore_timer
fi
sleep "$CHECK_INTERVAL"
done
}
# Main execution
log_message "=== Shutdown Timer Monitor Started ==="
log_message "Monitoring timer: $TIMER_NAME"
log_message "Monitoring service: $SERVICE_NAME"
# Initial check
if timer_needs_restoration; then
log_message "Initial check: Timer needs restoration"
restore_timer
else
log_message "Initial check: Timer is properly configured"
fi
# Use polling for reliability (D-Bus monitoring can miss events)
monitor_with_polling

View File

@ -0,0 +1,27 @@
[Unit]
Description=Shutdown Timer Monitor and Auto-Restore Service
After=network-online.target day-specific-shutdown.timer
Wants=network-online.target
[Service]
Type=simple
User=root
ExecStart=/usr/local/bin/shutdown-timer-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