From fc3b202042bc122a9a7ad8574c8babcfbbf0974a Mon Sep 17 00:00:00 2001 From: Krzysztof kuhy Rudnicki Date: Wed, 23 Jul 2025 16:27:24 +0200 Subject: [PATCH] feat: made midnight shutdown more restrictive --- scripts/setup_midnight_shutdown.sh | 281 +++++++++++++++++++---------- 1 file changed, 185 insertions(+), 96 deletions(-) diff --git a/scripts/setup_midnight_shutdown.sh b/scripts/setup_midnight_shutdown.sh index 7117dea..b1ebc46 100755 --- a/scripts/setup_midnight_shutdown.sh +++ b/scripts/setup_midnight_shutdown.sh @@ -1,21 +1,26 @@ #!/bin/bash -# Script to set up automatic PC shutdown at midnight on Arch Linux -# Creates systemd timer and service for daily shutdown at 00:00 +# Script to set up automatic PC shutdown with day-specific time windows +# Saturday-Thursday: Shutdown between 21:30-05:00 +# Friday/Sunday: Shutdown between 00:00-05:00 # Handles sudo privileges automatically set -e # Exit on any error # Function to show usage show_usage() { - echo "Midnight Auto-Shutdown Setup for Arch Linux" - echo "===========================================" + echo "Day-Specific Auto-Shutdown Setup for Arch Linux" + echo "===============================================" echo "Usage: $0 [enable|disable|status]" echo "" echo "Commands:" - echo " enable - Set up automatic midnight shutdown (default)" - echo " disable - Remove automatic midnight shutdown" + 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 " Saturday-Thursday: 21:30-05:00" + echo " Friday/Sunday: 00:00-05:00" + echo "" } # Function to check and request sudo privileges @@ -38,27 +43,28 @@ fi # Function to disable and remove midnight shutdown disable_midnight_shutdown() { - echo "Disabling Midnight Auto-Shutdown" - echo "===============================" + echo "Disabling Day-Specific Auto-Shutdown" + echo "====================================" echo "Current Date: $(date)" echo "User: $ACTUAL_USER" echo "" - local timer_file="/etc/systemd/system/midnight-shutdown.timer" - local service_file="/etc/systemd/system/midnight-shutdown.service" - local script_file="/usr/local/bin/midnight-shutdown-manager.sh" + 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 midnight-shutdown.timer &>/dev/null; then - echo "Stopping midnight-shutdown timer..." - systemctl stop midnight-shutdown.timer + 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 midnight-shutdown.timer &>/dev/null; then - echo "Disabling midnight-shutdown timer..." - systemctl disable midnight-shutdown.timer + 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 @@ -83,6 +89,13 @@ disable_midnight_shutdown() { 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..." @@ -91,18 +104,18 @@ disable_midnight_shutdown() { fi echo "" - echo "==========================================" - echo "Midnight Auto-Shutdown Removal Complete" - 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 midnight shutdown has been completely disabled" - echo "✓ Your PC will no longer shutdown automatically at midnight" + echo "✓ Automatic day-specific shutdown has been completely disabled" + echo "✓ Your PC will no longer shutdown automatically" else - echo "No midnight shutdown configuration was found to remove." + echo "No day-specific shutdown configuration was found to remove." fi echo "" @@ -110,8 +123,8 @@ disable_midnight_shutdown() { # Function to show current status show_current_status() { - echo "Midnight Auto-Shutdown Status" - echo "============================" + echo "Day-Specific Auto-Shutdown Status" + echo "=================================" echo "Current Date: $(date)" echo "User: $ACTUAL_USER" echo "" @@ -121,21 +134,21 @@ show_current_status() { local script_exists=false # Check if files exist - if [[ -f "/etc/systemd/system/midnight-shutdown.timer" ]]; then + 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/midnight-shutdown.service" ]]; then + if [[ -f "/etc/systemd/system/day-specific-shutdown.service" ]]; then service_exists=true echo "✓ Service file exists" else echo "✗ Service file missing" fi - if [[ -f "/usr/local/bin/midnight-shutdown-manager.sh" ]]; then + if [[ -f "/usr/local/bin/day-specific-shutdown-manager.sh" ]]; then script_exists=true echo "✓ Management script exists" else @@ -146,13 +159,13 @@ show_current_status() { # Check systemd status if $timer_exists; then - if systemctl is-enabled midnight-shutdown.timer &>/dev/null; then + if systemctl is-enabled day-specific-shutdown.timer &>/dev/null; then echo "✓ Timer is enabled" - if systemctl is-active midnight-shutdown.timer &>/dev/null; then + if systemctl is-active day-specific-shutdown.timer &>/dev/null; then echo "✓ Timer is active" echo "" - echo "Next scheduled shutdown:" - systemctl list-timers midnight-shutdown.timer --no-pager 2>/dev/null | grep midnight-shutdown || echo "Timer information not available" + 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 @@ -164,6 +177,10 @@ show_current_status() { fi echo "" + echo "Shutdown Schedule:" + echo " Saturday-Thursday: 21:30-05:00" + echo " Friday/Sunday: 00:00-05:00" + echo "" } # Function to create the shutdown service @@ -172,17 +189,17 @@ create_shutdown_service() { echo "1. Creating Systemd Shutdown Service..." echo "======================================" - local service_file="/etc/systemd/system/midnight-shutdown.service" + local service_file="/etc/systemd/system/day-specific-shutdown.service" cat > "$service_file" << 'EOF' [Unit] -Description=Automatic PC shutdown at midnight +Description=Automatic PC shutdown with day-specific time windows DefaultDependencies=false Before=shutdown.target reboot.target halt.target [Service] Type=oneshot -ExecStart=/usr/local/bin/midnight-shutdown-check.sh +ExecStart=/usr/local/bin/day-specific-shutdown-check.sh TimeoutStartSec=0 StandardOutput=journal StandardError=journal @@ -197,15 +214,30 @@ create_shutdown_timer() { echo "2. Creating Systemd Shutdown Timer..." echo "===================================" - local timer_file="/etc/systemd/system/midnight-shutdown.timer" + local timer_file="/etc/systemd/system/day-specific-shutdown.timer" cat > "$timer_file" << 'EOF' [Unit] -Description=Timer for automatic PC shutdown at midnight -Requires=midnight-shutdown.service +Description=Timer for automatic PC shutdown with day-specific windows +Requires=day-specific-shutdown.service [Timer] +OnCalendar=*-*-* 21:30:00 +OnCalendar=*-*-* 22:00:00 +OnCalendar=*-*-* 22:30:00 +OnCalendar=*-*-* 23:00:00 +OnCalendar=*-*-* 23:30:00 OnCalendar=*-*-* 00:00:00 +OnCalendar=*-*-* 00:30:00 +OnCalendar=*-*-* 01:00:00 +OnCalendar=*-*-* 01:30:00 +OnCalendar=*-*-* 02:00:00 +OnCalendar=*-*-* 02:30:00 +OnCalendar=*-*-* 03:00:00 +OnCalendar=*-*-* 03:30:00 +OnCalendar=*-*-* 04:00:00 +OnCalendar=*-*-* 04:30:00 +OnCalendar=*-*-* 05:00:00 Persistent=false AccuracySec=1s WakeSystem=false @@ -224,19 +256,19 @@ create_management_script() { echo "3. Creating Management Script..." echo "==============================" - local script_file="/usr/local/bin/midnight-shutdown-manager.sh" + local script_file="/usr/local/bin/day-specific-shutdown-manager.sh" cat > "$script_file" << 'EOF' #!/bin/bash -# Midnight Auto-Shutdown Manager -# Provides easy management of the midnight shutdown feature +# Day-Specific Auto-Shutdown Manager +# Provides easy management of the day-specific shutdown feature -TIMER_NAME="midnight-shutdown.timer" -SERVICE_NAME="midnight-shutdown.service" +TIMER_NAME="day-specific-shutdown.timer" +SERVICE_NAME="day-specific-shutdown.service" show_status() { - echo "Midnight Auto-Shutdown Status" - echo "============================" + echo "Day-Specific Auto-Shutdown Status" + echo "=================================" if systemctl is-enabled "$TIMER_NAME" &>/dev/null; then echo "Status: ENABLED" @@ -250,7 +282,12 @@ show_status() { fi echo "" - echo "Next scheduled shutdown:" + echo "Shutdown Schedule:" + echo " Saturday-Thursday: 21:30-05:00" + echo " Friday/Sunday: 00:00-05:00" + + echo "" + echo "Next scheduled checks:" systemctl list-timers "$TIMER_NAME" --no-pager 2>/dev/null | grep "$TIMER_NAME" || echo "Timer not active" echo "" @@ -263,18 +300,22 @@ case "$1" in show_status ;; "logs") - echo "Midnight Auto-Shutdown Logs" - echo "==========================" + echo "Day-Specific Auto-Shutdown Logs" + echo "===============================" journalctl -u "$SERVICE_NAME" --no-pager -n 20 ;; *) - echo "Midnight Auto-Shutdown Manager" + echo "Day-Specific Auto-Shutdown Manager" echo "Usage: $0 {status|logs}" echo "" echo "Commands:" - echo " status - Show current status and next shutdown time" + echo " status - Show current status and next shutdown checks" echo " logs - Show recent shutdown logs" echo "" + echo "Shutdown Schedule:" + echo " Saturday-Thursday: 21:30-05:00" + echo " Friday/Sunday: 00:00-05:00" + echo "" show_status ;; esac @@ -290,29 +331,66 @@ create_shutdown_check_script() { echo "4. Creating Smart Shutdown Check Script..." echo "========================================" - local check_script="/usr/local/bin/midnight-shutdown-check.sh" + local check_script="/usr/local/bin/day-specific-shutdown-check.sh" cat > "$check_script" << 'EOF' #!/bin/bash -# Smart midnight shutdown check script -# Only shuts down if the current time is actually close to midnight -# Prevents shutdown on boot if system was off during scheduled time +# Smart day-specific shutdown check script +# Different shutdown windows based on day of week: +# Saturday-Thursday: 21:30-05:00 +# Friday/Sunday: 00:00-05:00 -# Get current time components +# Get current time and day current_hour=$(date +%H) current_minute=$(date +%M) current_time_minutes=$((10#$current_hour * 60 + 10#$current_minute)) +day_of_week=$(date +%u) # 1=Monday, 7=Sunday +day_name=$(date +%A) -# Midnight is 0 minutes (00:00) -# Allow shutdown if we're within 5 minutes of midnight -# This covers 23:55-00:05 range -if [[ $current_time_minutes -le 5 ]] || [[ $current_time_minutes -ge 1435 ]]; then - echo "$(date): Executing midnight shutdown - current time is within shutdown window" - logger -t midnight-shutdown "Executing scheduled shutdown at $(date)" +# Convert time to minutes for easier comparison +# 21:30 = 1290 minutes, 05:00 = 300 minutes +# 00:00 = 0 minutes, 05:00 = 300 minutes + +logger -t day-specific-shutdown "Checking shutdown conditions at $(date) - Day: $day_name ($day_of_week), Time: $current_hour:$current_minute" + +# Determine if we should shutdown based on day and time +should_shutdown=false + +if [[ $day_of_week -eq 5 ]] || [[ $day_of_week -eq 7 ]]; then + # Friday (5) or Sunday (7): shutdown window 00:00-05:00 + logger -t day-specific-shutdown "Today is $day_name - checking 00:00-05:00 window" + + if [[ $current_time_minutes -ge 0 ]] && [[ $current_time_minutes -le 300 ]]; then + should_shutdown=true + logger -t day-specific-shutdown "Time $current_hour:$current_minute is within Friday/Sunday shutdown window (00:00-05:00)" + else + logger -t day-specific-shutdown "Time $current_hour:$current_minute is outside Friday/Sunday shutdown window (00:00-05:00)" + fi +else + # Monday(1), Tuesday(2), Wednesday(3), Thursday(4), Saturday(6): shutdown window 21:30-05:00 + logger -t day-specific-shutdown "Today is $day_name - checking 21:30-05:00 window" + + # Check if time is between 21:30 (1290 minutes) and 23:59 (1439 minutes) + # OR between 00:00 (0 minutes) and 05:00 (300 minutes) + if [[ $current_time_minutes -ge 1290 ]] || [[ $current_time_minutes -le 300 ]]; then + should_shutdown=true + if [[ $current_time_minutes -ge 1290 ]]; then + logger -t day-specific-shutdown "Time $current_hour:$current_minute is within evening shutdown window (21:30-23:59)" + else + logger -t day-specific-shutdown "Time $current_hour:$current_minute is within morning shutdown window (00:00-05:00)" + fi + else + logger -t day-specific-shutdown "Time $current_hour:$current_minute is outside shutdown window (21:30-05:00)" + fi +fi + +if [[ $should_shutdown == true ]]; then + echo "$(date): Executing shutdown - current time $current_hour:$current_minute is within shutdown window for $day_name" + logger -t day-specific-shutdown "Executing scheduled shutdown at $(date)" /usr/bin/systemctl poweroff else - echo "$(date): Skipping shutdown - not within midnight window (current: $current_hour:$current_minute)" - logger -t midnight-shutdown "Skipped shutdown - not within midnight window (current: $current_hour:$current_minute)" + echo "$(date): Skipping shutdown - not within shutdown window for $day_name (current: $current_hour:$current_minute)" + logger -t day-specific-shutdown "Skipped shutdown - not within shutdown window for $day_name (current: $current_hour:$current_minute)" fi EOF @@ -331,12 +409,12 @@ enable_timer() { echo "✓ Reloaded systemd daemon" # Enable the timer - systemctl enable midnight-shutdown.timer - echo "✓ Enabled midnight-shutdown timer" + systemctl enable day-specific-shutdown.timer + echo "✓ Enabled day-specific-shutdown timer" # Start the timer - systemctl start midnight-shutdown.timer - echo "✓ Started midnight-shutdown timer" + systemctl start day-specific-shutdown.timer + echo "✓ Started day-specific-shutdown timer" } # Function to test the setup @@ -346,13 +424,13 @@ test_setup() { echo "==================" echo "Service files:" - if [[ -f "/etc/systemd/system/midnight-shutdown.service" ]]; then + 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/midnight-shutdown.timer" ]]; then + if [[ -f "/etc/systemd/system/day-specific-shutdown.timer" ]]; then echo "✓ Timer file exists" else echo "✗ Timer file missing" @@ -360,60 +438,71 @@ test_setup() { echo "" echo "Timer status:" - if systemctl is-enabled midnight-shutdown.timer &>/dev/null; then + if systemctl is-enabled day-specific-shutdown.timer &>/dev/null; then echo "✓ Timer is enabled" else echo "✗ Timer is not enabled" fi - if systemctl is-active midnight-shutdown.timer &>/dev/null; then + if systemctl is-active day-specific-shutdown.timer &>/dev/null; then echo "✓ Timer is active" else echo "✗ Timer is not active" fi echo "" - echo "Next scheduled shutdown:" - systemctl list-timers midnight-shutdown.timer --no-pager 2>/dev/null | grep midnight-shutdown || echo "Timer information not available" + 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 "Midnight Auto-Shutdown Setup Complete" - echo "==========================================" + echo "=================================================" + echo "Day-Specific Auto-Shutdown Setup Complete" + echo "=================================================" echo "Summary:" - echo "✓ Systemd service created (/etc/systemd/system/midnight-shutdown.service)" - echo "✓ Systemd timer created (/etc/systemd/system/midnight-shutdown.timer)" - echo "✓ Management script created (/usr/local/bin/midnight-shutdown-manager.sh)" + 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 "Your PC will now automatically shutdown at 00:00 (midnight) every day." + echo "Shutdown Schedule:" + echo " Saturday-Thursday: 21:30-05:00 (evening to early morning)" + echo " Friday/Sunday: 00:00-05:00 (midnight to early morning)" echo "" echo "Management commands:" - echo " sudo midnight-shutdown-manager.sh status - Check status" - echo " sudo midnight-shutdown-manager.sh logs - View shutdown logs" + echo " sudo day-specific-shutdown-manager.sh status - Check status" + echo " sudo day-specific-shutdown-manager.sh logs - View shutdown logs" echo "" - echo "Next shutdown: Tonight at 00:00" + 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 permanently shutdown your PC every night at midnight." - echo "Make sure to save your work before midnight!" + 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: Auto-Shutdown Confirmation" - echo "==================================" - echo "This will set up your PC to automatically shutdown every day at midnight (00:00)." + 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 " Saturday-Thursday: 21:30-05:00 (9:30 PM to 5:00 AM)" + echo " Friday/Sunday: 00:00-05:00 (Midnight to 5:00 AM)" echo "" echo "Important considerations:" - echo "- Any unsaved work will be lost" + 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 -p "Do you want to proceed? (y/N): " confirm @@ -432,14 +521,14 @@ confirm_setup() { # Function to confirm disable confirm_disable() { echo "" - echo "Disable Auto-Shutdown Confirmation" - echo "=================================" - echo "This will completely remove the automatic midnight shutdown configuration." + 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 at midnight" + 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 script will be deleted" + echo "- The management and check scripts will be deleted" echo "" read -p "Do you want to proceed with disabling? (y/N): " confirm @@ -457,8 +546,8 @@ confirm_disable() { # Main execution flow for enable enable_midnight_shutdown() { - echo "Midnight Auto-Shutdown Setup for Arch Linux" - echo "===========================================" + echo "Day-Specific Auto-Shutdown Setup for Arch Linux" + echo "===============================================" echo "Current Date: $(date)" echo "User: $ACTUAL_USER" echo "Target user: $ACTUAL_USER"