mirror of
https://github.com/kuhyx/scripts.git
synced 2026-07-04 15:23:11 +02:00
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:
parent
4cb3a62491
commit
a1b9200d19
@ -8,186 +8,132 @@ set -e # Exit on any error
|
|||||||
|
|
||||||
# Function to show usage
|
# Function to show usage
|
||||||
show_usage() {
|
show_usage() {
|
||||||
echo "Day-Specific Auto-Shutdown Setup for Arch Linux"
|
echo "Day-Specific Auto-Shutdown Setup for Arch Linux"
|
||||||
echo "==============================================="
|
echo "==============================================="
|
||||||
echo "Usage: $0 [enable|disable|status]"
|
echo "Usage: $0 [enable|status]"
|
||||||
echo ""
|
echo ""
|
||||||
echo "Commands:"
|
echo "Commands:"
|
||||||
echo " enable - Set up automatic shutdown with day-specific windows (default)"
|
echo " enable - Set up automatic shutdown with day-specific windows (default)"
|
||||||
echo " disable - Remove automatic shutdown"
|
echo " status - Show current status"
|
||||||
echo " status - Show current status"
|
echo ""
|
||||||
echo ""
|
echo "Shutdown Schedule:"
|
||||||
echo "Shutdown Schedule:"
|
echo " Monday-Wednesday: 21:00-05:00"
|
||||||
echo " Monday-Wednesday: 21:00-05:00"
|
echo " Thursday-Sunday: 22:00-05:00"
|
||||||
echo " Thursday-Sunday: 22:00-05:00"
|
echo ""
|
||||||
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
|
# Function to check and request sudo privileges
|
||||||
check_sudo() {
|
check_sudo() {
|
||||||
if [[ $EUID -ne 0 ]]; then
|
if [[ $EUID -ne 0 ]]; then
|
||||||
echo "This script requires sudo privileges to manage systemd services."
|
echo "This script requires sudo privileges to manage systemd services."
|
||||||
echo "Requesting sudo access..."
|
echo "Requesting sudo access..."
|
||||||
exec sudo "$0" "$@"
|
exec sudo "$0" "$@"
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
# Get the actual user (even when running with sudo)
|
# Get the actual user (even when running with sudo)
|
||||||
if [[ -n $SUDO_USER ]]; then
|
if [[ -n $SUDO_USER ]]; then
|
||||||
ACTUAL_USER="$SUDO_USER"
|
ACTUAL_USER="$SUDO_USER"
|
||||||
USER_HOME="/home/$SUDO_USER"
|
USER_HOME="/home/$SUDO_USER"
|
||||||
else
|
else
|
||||||
ACTUAL_USER="$USER"
|
ACTUAL_USER="$USER"
|
||||||
USER_HOME="$HOME"
|
USER_HOME="$HOME"
|
||||||
fi
|
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
|
# Function to show current status
|
||||||
show_current_status() {
|
show_current_status() {
|
||||||
echo "Day-Specific Auto-Shutdown Status"
|
echo "Day-Specific Auto-Shutdown Status"
|
||||||
echo "================================="
|
echo "================================="
|
||||||
echo "Current Date: $(date)"
|
echo "Current Date: $(date)"
|
||||||
echo "User: $ACTUAL_USER"
|
echo "User: $ACTUAL_USER"
|
||||||
echo ""
|
echo ""
|
||||||
|
|
||||||
local timer_exists=false
|
local timer_exists=false
|
||||||
|
|
||||||
# Check if files exist
|
# Check if files exist
|
||||||
if [[ -f "/etc/systemd/system/day-specific-shutdown.timer" ]]; then
|
if [[ -f "/etc/systemd/system/day-specific-shutdown.timer" ]]; then
|
||||||
timer_exists=true
|
timer_exists=true
|
||||||
echo "✓ Timer file exists"
|
echo "✓ Timer file exists"
|
||||||
else
|
else
|
||||||
echo "✗ Timer file missing"
|
echo "✗ Timer file missing"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [[ -f "/etc/systemd/system/day-specific-shutdown.service" ]]; then
|
if [[ -f "/etc/systemd/system/day-specific-shutdown.service" ]]; then
|
||||||
echo "✓ Service file exists"
|
echo "✓ Service file exists"
|
||||||
else
|
else
|
||||||
echo "✗ Service file missing"
|
echo "✗ Service file missing"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [[ -f "/usr/local/bin/day-specific-shutdown-manager.sh" ]]; then
|
if [[ -f "/usr/local/bin/day-specific-shutdown-manager.sh" ]]; then
|
||||||
echo "✓ Management script exists"
|
echo "✓ Management script exists"
|
||||||
else
|
else
|
||||||
echo "✗ Management script missing"
|
echo "✗ Management script missing"
|
||||||
fi
|
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
|
echo ""
|
||||||
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 systemd status
|
||||||
echo "Shutdown Schedule:"
|
if $timer_exists; then
|
||||||
echo " Monday-Wednesday: 21:00-05:00"
|
if systemctl is-enabled day-specific-shutdown.timer &>/dev/null; then
|
||||||
echo " Thursday-Sunday: 22:00-05:00"
|
echo "✓ Timer is enabled"
|
||||||
echo ""
|
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
|
# Function to create the shutdown service
|
||||||
create_shutdown_service() {
|
create_shutdown_service() {
|
||||||
echo ""
|
echo ""
|
||||||
echo "1. Creating Systemd Shutdown Service..."
|
echo "1. Creating Systemd Shutdown Service..."
|
||||||
echo "======================================"
|
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]
|
[Unit]
|
||||||
Description=Automatic PC shutdown with day-specific time windows
|
Description=Automatic PC shutdown with day-specific time windows
|
||||||
DefaultDependencies=false
|
DefaultDependencies=false
|
||||||
@ -201,18 +147,18 @@ StandardOutput=journal
|
|||||||
StandardError=journal
|
StandardError=journal
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
echo "✓ Created systemd service: $service_file"
|
echo "✓ Created systemd service: $service_file"
|
||||||
}
|
}
|
||||||
|
|
||||||
# Function to create the shutdown timer
|
# Function to create the shutdown timer
|
||||||
create_shutdown_timer() {
|
create_shutdown_timer() {
|
||||||
echo ""
|
echo ""
|
||||||
echo "2. Creating Systemd Shutdown Timer..."
|
echo "2. Creating Systemd Shutdown Timer..."
|
||||||
echo "==================================="
|
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]
|
[Unit]
|
||||||
Description=Timer for automatic PC shutdown with day-specific windows
|
Description=Timer for automatic PC shutdown with day-specific windows
|
||||||
Requires=day-specific-shutdown.service
|
Requires=day-specific-shutdown.service
|
||||||
@ -244,18 +190,18 @@ RandomizedDelaySec=0
|
|||||||
WantedBy=timers.target
|
WantedBy=timers.target
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
echo "✓ Created systemd timer: $timer_file"
|
echo "✓ Created systemd timer: $timer_file"
|
||||||
}
|
}
|
||||||
|
|
||||||
# Function to create management script
|
# Function to create management script
|
||||||
create_management_script() {
|
create_management_script() {
|
||||||
echo ""
|
echo ""
|
||||||
echo "3. Creating Management Script..."
|
echo "3. Creating Management Script..."
|
||||||
echo "=============================="
|
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
|
#!/bin/bash
|
||||||
# Day-Specific Auto-Shutdown Manager
|
# Day-Specific Auto-Shutdown Manager
|
||||||
# Provides easy management of the day-specific shutdown feature
|
# Provides easy management of the day-specific shutdown feature
|
||||||
@ -318,19 +264,19 @@ case "$1" in
|
|||||||
esac
|
esac
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
chmod +x "$script_file"
|
chmod +x "$script_file"
|
||||||
echo "✓ Created management script: $script_file"
|
echo "✓ Created management script: $script_file"
|
||||||
}
|
}
|
||||||
|
|
||||||
# Function to create smart shutdown check script
|
# Function to create smart shutdown check script
|
||||||
create_shutdown_check_script() {
|
create_shutdown_check_script() {
|
||||||
echo ""
|
echo ""
|
||||||
echo "4. Creating Smart Shutdown Check Script..."
|
echo "4. Creating Smart Shutdown Check Script..."
|
||||||
echo "========================================"
|
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
|
#!/bin/bash
|
||||||
# Smart day-specific shutdown check script
|
# Smart day-specific shutdown check script
|
||||||
# Different shutdown windows based on day of week:
|
# Different shutdown windows based on day of week:
|
||||||
@ -397,206 +343,324 @@ else
|
|||||||
fi
|
fi
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
chmod +x "$check_script"
|
chmod +x "$check_script"
|
||||||
echo "✓ Created smart shutdown check script: $check_script"
|
echo "✓ Created smart shutdown check script: $check_script"
|
||||||
}
|
}
|
||||||
|
|
||||||
# Function to enable the timer
|
# Function to enable the timer
|
||||||
enable_timer() {
|
enable_timer() {
|
||||||
echo ""
|
echo ""
|
||||||
echo "5. Enabling Shutdown Timer..."
|
echo "5. Enabling Shutdown Timer..."
|
||||||
echo "============================"
|
echo "============================"
|
||||||
|
|
||||||
# Reload systemd daemon
|
# Reload systemd daemon
|
||||||
systemctl daemon-reload
|
systemctl daemon-reload
|
||||||
echo "✓ Reloaded systemd daemon"
|
echo "✓ Reloaded systemd daemon"
|
||||||
|
|
||||||
# Enable the timer
|
# Enable the timer
|
||||||
systemctl enable day-specific-shutdown.timer
|
systemctl enable day-specific-shutdown.timer
|
||||||
echo "✓ Enabled day-specific-shutdown timer"
|
echo "✓ Enabled day-specific-shutdown timer"
|
||||||
|
|
||||||
# Start the timer
|
# Start the timer
|
||||||
systemctl start day-specific-shutdown.timer
|
systemctl start day-specific-shutdown.timer
|
||||||
echo "✓ Started 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
|
# Function to test the setup
|
||||||
test_setup() {
|
test_setup() {
|
||||||
echo ""
|
echo ""
|
||||||
echo "6. Testing Setup..."
|
echo "7. Testing Setup..."
|
||||||
echo "=================="
|
echo "=================="
|
||||||
|
|
||||||
echo "Service files:"
|
echo "Service files:"
|
||||||
if [[ -f "/etc/systemd/system/day-specific-shutdown.service" ]]; then
|
if [[ -f "/etc/systemd/system/day-specific-shutdown.service" ]]; then
|
||||||
echo "✓ Service file exists"
|
echo "✓ Service file exists"
|
||||||
else
|
else
|
||||||
echo "✗ Service file missing"
|
echo "✗ Service file missing"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [[ -f "/etc/systemd/system/day-specific-shutdown.timer" ]]; then
|
if [[ -f "/etc/systemd/system/day-specific-shutdown.timer" ]]; then
|
||||||
echo "✓ Timer file exists"
|
echo "✓ Timer file exists"
|
||||||
else
|
else
|
||||||
echo "✗ Timer file missing"
|
echo "✗ Timer file missing"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo ""
|
if [[ -f "/etc/systemd/system/shutdown-timer-monitor.service" ]]; then
|
||||||
echo "Timer status:"
|
echo "✓ Monitor service file exists"
|
||||||
if systemctl is-enabled day-specific-shutdown.timer &> /dev/null; then
|
else
|
||||||
echo "✓ Timer is enabled"
|
echo "✗ Monitor service file missing"
|
||||||
else
|
fi
|
||||||
echo "✗ Timer is not enabled"
|
|
||||||
fi
|
|
||||||
|
|
||||||
if systemctl is-active day-specific-shutdown.timer &> /dev/null; then
|
echo ""
|
||||||
echo "✓ Timer is active"
|
echo "Timer status:"
|
||||||
else
|
if systemctl is-enabled day-specific-shutdown.timer &>/dev/null; then
|
||||||
echo "✗ Timer is not active"
|
echo "✓ Timer is enabled"
|
||||||
fi
|
else
|
||||||
|
echo "✗ Timer is not enabled"
|
||||||
|
fi
|
||||||
|
|
||||||
echo ""
|
if systemctl is-active day-specific-shutdown.timer &>/dev/null; then
|
||||||
echo "Next scheduled checks:"
|
echo "✓ Timer is active"
|
||||||
systemctl list-timers day-specific-shutdown.timer --no-pager 2> /dev/null | head -5 | grep day-specific-shutdown || echo "Timer information not available"
|
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
|
# Function to show final instructions
|
||||||
show_instructions() {
|
show_instructions() {
|
||||||
echo ""
|
echo ""
|
||||||
echo "================================================="
|
echo "================================================="
|
||||||
echo "Day-Specific Auto-Shutdown Setup Complete"
|
echo "Day-Specific Auto-Shutdown Setup Complete"
|
||||||
echo "================================================="
|
echo "================================================="
|
||||||
echo "Summary:"
|
echo "Summary:"
|
||||||
echo "✓ Systemd service created (/etc/systemd/system/day-specific-shutdown.service)"
|
echo "✓ Systemd service created (/etc/systemd/system/day-specific-shutdown.service)"
|
||||||
echo "✓ Systemd timer created (/etc/systemd/system/day-specific-shutdown.timer)"
|
echo "✓ Systemd timer created (/etc/systemd/system/day-specific-shutdown.timer)"
|
||||||
echo "✓ Management script created (/usr/local/bin/day-specific-shutdown-manager.sh)"
|
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 "✓ Smart check script created (/usr/local/bin/day-specific-shutdown-check.sh)"
|
||||||
echo "✓ Timer enabled and started"
|
echo "✓ Timer enabled and started"
|
||||||
echo ""
|
echo "✓ Monitor service installed and started (protects timer from being disabled)"
|
||||||
echo "Shutdown Schedule:"
|
echo ""
|
||||||
echo " Monday-Wednesday: 21:00-05:00 (9:00 PM to 5:00 AM)"
|
echo "Shutdown Schedule:"
|
||||||
echo " Thursday-Sunday: 22:00-05:00 (10:00 PM to 5:00 AM)"
|
echo " Monday-Wednesday: 21:00-05:00 (9:00 PM to 5:00 AM)"
|
||||||
echo ""
|
echo " Thursday-Sunday: 22:00-05:00 (10:00 PM to 5:00 AM)"
|
||||||
echo "Management commands:"
|
echo ""
|
||||||
echo " sudo day-specific-shutdown-manager.sh status - Check status"
|
echo "Management commands:"
|
||||||
echo " sudo day-specific-shutdown-manager.sh logs - View shutdown logs"
|
echo " sudo day-specific-shutdown-manager.sh status - Check status"
|
||||||
echo ""
|
echo " sudo day-specific-shutdown-manager.sh logs - View shutdown logs"
|
||||||
echo "How it works:"
|
echo ""
|
||||||
echo "• Timer checks every 30 minutes during potential shutdown windows"
|
echo "How it works:"
|
||||||
echo "• Smart logic determines shutdown eligibility based on day and time"
|
echo "• Timer checks every 30 minutes during potential shutdown windows"
|
||||||
echo "• Prevents accidental shutdowns outside designated time windows"
|
echo "• Smart logic determines shutdown eligibility based on day and time"
|
||||||
echo ""
|
echo "• Monitor service watches the timer and re-enables it if disabled"
|
||||||
echo "WARNING: This will automatically shutdown your PC during designated hours."
|
echo "• There is NO disable option - this is intentional for digital wellbeing"
|
||||||
echo "Make sure to save your work before the shutdown windows!"
|
echo ""
|
||||||
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
|
# Function to prompt for confirmation
|
||||||
confirm_setup() {
|
confirm_setup() {
|
||||||
echo ""
|
echo ""
|
||||||
echo "WARNING: Day-Specific Auto-Shutdown Confirmation"
|
echo "WARNING: Day-Specific Auto-Shutdown Confirmation"
|
||||||
echo "==============================================="
|
echo "==============================================="
|
||||||
echo "This will set up your PC to automatically shutdown during specific time windows."
|
echo "This will set up your PC to automatically shutdown during specific time windows."
|
||||||
echo ""
|
echo ""
|
||||||
echo "Shutdown Schedule:"
|
echo "Shutdown Schedule:"
|
||||||
echo " Monday-Wednesday: 21:00-05:00 (9:00 PM to 5:00 AM)"
|
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 " Thursday-Sunday: 22:00-05:00 (10:00 PM to 5:00 AM)"
|
||||||
echo ""
|
echo ""
|
||||||
echo "Important considerations:"
|
echo "Important considerations:"
|
||||||
echo "- Any unsaved work will be lost during shutdown windows"
|
echo "- Any unsaved work will be lost during shutdown windows"
|
||||||
echo "- Running processes will be terminated"
|
echo "- Running processes will be terminated"
|
||||||
echo "- Downloads/uploads in progress will be interrupted"
|
echo "- Downloads/uploads in progress will be interrupted"
|
||||||
echo "- You'll need to manually power on your PC each day"
|
echo "- You'll need to manually power on your PC each day"
|
||||||
echo "- Timer checks every 30 minutes during potential shutdown windows"
|
echo "- Timer checks every 30 minutes during potential shutdown windows"
|
||||||
echo ""
|
echo "- There is NO disable option - this is protected by a monitor service"
|
||||||
read -r -p "Do you want to proceed? (y/N): " confirm
|
echo ""
|
||||||
|
read -r -p "Do you want to proceed? (y/N): " confirm
|
||||||
|
|
||||||
case "$confirm" in
|
case "$confirm" in
|
||||||
[yY] | [yY][eE][sS])
|
[yY] | [yY][eE][sS])
|
||||||
echo "Proceeding with setup..."
|
echo "Proceeding with setup..."
|
||||||
return 0
|
return 0
|
||||||
;;
|
;;
|
||||||
*)
|
*)
|
||||||
echo "Setup cancelled."
|
echo "Setup cancelled."
|
||||||
exit 0
|
exit 0
|
||||||
;;
|
;;
|
||||||
esac
|
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
|
|
||||||
}
|
}
|
||||||
|
|
||||||
# Main execution flow for enable
|
# Main execution flow for enable
|
||||||
enable_midnight_shutdown() {
|
enable_midnight_shutdown() {
|
||||||
echo "Day-Specific Auto-Shutdown Setup for Arch Linux"
|
echo "Day-Specific Auto-Shutdown Setup for Arch Linux"
|
||||||
echo "==============================================="
|
echo "==============================================="
|
||||||
echo "Current Date: $(date)"
|
echo "Current Date: $(date)"
|
||||||
echo "User: $ACTUAL_USER"
|
echo "User: $ACTUAL_USER"
|
||||||
echo "Target user: $ACTUAL_USER"
|
echo "Target user: $ACTUAL_USER"
|
||||||
echo "User home: $USER_HOME"
|
echo "User home: $USER_HOME"
|
||||||
|
|
||||||
# Confirm setup
|
# Confirm setup
|
||||||
confirm_setup
|
confirm_setup
|
||||||
|
|
||||||
# Create systemd files
|
# Create systemd files
|
||||||
create_shutdown_service
|
create_shutdown_service
|
||||||
create_shutdown_timer
|
create_shutdown_timer
|
||||||
create_management_script
|
create_management_script
|
||||||
create_shutdown_check_script
|
create_shutdown_check_script
|
||||||
|
|
||||||
# Enable and start timer
|
# Enable and start timer
|
||||||
enable_timer
|
enable_timer
|
||||||
|
|
||||||
# Test setup
|
# Install monitor service (protects timer from being disabled)
|
||||||
test_setup
|
install_monitor_service
|
||||||
|
|
||||||
# Show instructions
|
# Test setup
|
||||||
show_instructions
|
test_setup
|
||||||
|
|
||||||
|
# Show instructions
|
||||||
|
show_instructions
|
||||||
}
|
}
|
||||||
|
|
||||||
# Parse command line arguments
|
# Parse command line arguments
|
||||||
case "${1:-enable}" in
|
case "${1:-enable}" in
|
||||||
"enable")
|
"enable")
|
||||||
check_sudo "$@"
|
check_sudo "$@"
|
||||||
enable_midnight_shutdown
|
enable_midnight_shutdown
|
||||||
;;
|
;;
|
||||||
"disable")
|
"status")
|
||||||
check_sudo "$@"
|
check_sudo "$@"
|
||||||
confirm_disable
|
show_current_status
|
||||||
disable_midnight_shutdown
|
;;
|
||||||
;;
|
"help" | "-h" | "--help")
|
||||||
"status")
|
show_usage
|
||||||
check_sudo "$@"
|
;;
|
||||||
show_current_status
|
*)
|
||||||
;;
|
echo "Error: Unknown command '$1'"
|
||||||
"help" | "-h" | "--help")
|
echo ""
|
||||||
show_usage
|
show_usage
|
||||||
;;
|
exit 1
|
||||||
*)
|
;;
|
||||||
echo "Error: Unknown command '$1'"
|
|
||||||
echo ""
|
|
||||||
show_usage
|
|
||||||
exit 1
|
|
||||||
;;
|
|
||||||
esac
|
esac
|
||||||
|
|||||||
131
scripts/system-maintenance/bin/shutdown-timer-monitor.sh
Normal file
131
scripts/system-maintenance/bin/shutdown-timer-monitor.sh
Normal 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
|
||||||
@ -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
|
||||||
Loading…
Reference in New Issue
Block a user