scripts/scripts/setup_pc_startup_monitor.sh

572 lines
18 KiB
Bash
Executable File

#!/bin/bash
# Script to monitor PC startup times on specific days
# Checks if PC was turned on between 5AM-8AM on Monday, Friday, Saturday, Sunday
# Handles sudo privileges automatically
set -e # Exit on any error
# Default to non-interactive mode
INTERACTIVE_MODE=false
# Parse command line arguments
while [[ $# -gt 0 ]]; do
case $1 in
-i|--interactive)
INTERACTIVE_MODE=true
shift
;;
-h|--help)
echo "Usage: $0 [OPTIONS]"
echo "Options:"
echo " -i, --interactive Enable interactive prompts (default: auto-yes)"
echo " -h, --help Show this help message"
exit 0
;;
*)
echo "Unknown option: $1"
echo "Use -h or --help for usage information"
exit 1
;;
esac
done
echo "PC Startup Time Monitor for Arch Linux"
echo "======================================"
echo "Current Date: $(date)"
echo "User: ${SUDO_USER:-$USER}"
if [[ "$INTERACTIVE_MODE" == "true" ]]; then
echo "Mode: Interactive (prompts enabled)"
else
echo "Mode: Automatic (auto-yes, use --interactive for prompts)"
fi
# Function to check and request sudo privileges
check_sudo() {
if [[ $EUID -ne 0 ]]; then
echo "This script requires sudo privileges to access system logs and create 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"
else
ACTUAL_USER="$USER"
USER_HOME="$HOME"
fi
echo "Target user: $ACTUAL_USER"
echo "User home: $USER_HOME"
# Function to check if today is a monitored day
is_monitored_day() {
local day_of_week=$(date +%u) # 1=Monday, 7=Sunday
# Check if today is Monday (1), Friday (5), Saturday (6), or Sunday (7)
if [[ "$day_of_week" == "1" ]] || [[ "$day_of_week" == "5" ]] || [[ "$day_of_week" == "6" ]] || [[ "$day_of_week" == "7" ]]; then
return 0 # Yes, it's a monitored day
else
return 1 # No, it's not a monitored day
fi
}
# Function to check if current time is between 5AM and 8AM
is_current_time_in_window() {
local current_hour=$(date +%H)
local current_hour_num=$((10#$current_hour)) # Convert to decimal to avoid octal issues
if [[ $current_hour_num -ge 5 ]] && [[ $current_hour_num -lt 8 ]]; then
return 0 # Yes, current time is in the 5AM-8AM window
else
return 1 # No, current time is outside the window
fi
}
# Function to check if PC was booted between 5AM-8AM today
was_booted_in_window_today() {
local today=$(date +%Y-%m-%d)
local boot_time=""
# Get the last boot time using multiple methods for reliability
if command -v uptime &>/dev/null; then
# Method 1: Calculate boot time from uptime
local uptime_seconds=$(awk '{print int($1)}' /proc/uptime 2>/dev/null || echo "0")
if [[ $uptime_seconds -gt 0 ]]; then
boot_time=$(date -d "@$(($(date +%s) - uptime_seconds))" +"%Y-%m-%d %H:%M:%S")
fi
fi
# Method 2: Use systemd if available (fallback)
if [[ -z "$boot_time" ]] && command -v systemctl &>/dev/null; then
boot_time=$(systemd-analyze | grep "Startup finished" | sed -n 's/.*finished in .* = \(.*\)$/\1/p' 2>/dev/null || echo "")
if [[ -n "$boot_time" ]]; then
# This gives us relative time, need to calculate absolute time
local current_time=$(date +%s)
local uptime_sec=$(awk '{print int($1)}' /proc/uptime 2>/dev/null || echo "0")
boot_time=$(date -d "@$((current_time - uptime_sec))" +"%Y-%m-%d %H:%M:%S")
fi
fi
# Method 3: Use who -b (fallback)
if [[ -z "$boot_time" ]] && command -v who &>/dev/null; then
boot_time=$(who -b | awk '{print $3, $4}' 2>/dev/null || echo "")
if [[ -n "$boot_time" ]]; then
boot_time="$today $boot_time"
fi
fi
# Method 4: Use /proc/uptime as final fallback
if [[ -z "$boot_time" ]]; then
local uptime_seconds=$(awk '{print int($1)}' /proc/uptime 2>/dev/null || echo "0")
boot_time=$(date -d "@$(($(date +%s) - uptime_seconds))" +"%Y-%m-%d %H:%M:%S")
fi
echo "Boot time detected: $boot_time"
# Check if boot time is from today
local boot_date=$(echo "$boot_time" | cut -d' ' -f1)
if [[ "$boot_date" != "$today" ]]; then
echo "PC was not booted today (boot date: $boot_date, today: $today)"
return 1 # Not booted today
fi
# Extract hour from boot time
local boot_hour=$(echo "$boot_time" | cut -d' ' -f2 | cut -d':' -f1)
local boot_hour_num=$((10#$boot_hour)) # Convert to decimal
echo "Boot hour: $boot_hour_num"
# Check if boot time was between 5AM (5) and 8AM (7, since we want before 8AM)
if [[ $boot_hour_num -ge 5 ]] && [[ $boot_hour_num -lt 8 ]]; then
echo "PC was booted in the expected window (5AM-8AM)"
return 0 # Yes, booted in window
else
echo "PC was NOT booted in the expected window (5AM-8AM)"
return 1 # No, not booted in window
fi
}
# Function to show notification/warning
show_startup_warning() {
local day_name=$(date +%A)
local current_time=$(date +"%H:%M")
local today=$(date +%Y-%m-%d)
echo ""
echo "⚠️ PC STARTUP TIME WARNING"
echo "=========================="
echo "Date: $today ($day_name)"
echo "Current time: $current_time"
echo ""
echo "This PC was expected to be turned on between 5:00 AM and 8:00 AM today,"
echo "but it was not turned on during that time window."
echo ""
echo "Expected: Monday, Friday, Saturday, Sunday between 5:00-8:00 AM"
echo "Actual: PC was turned on outside the expected window"
echo ""
# Log the warning
logger -t pc-startup-monitor "WARNING: PC was not turned on during expected window (5AM-8AM) on $day_name $today"
# Try to show desktop notification if possible
if command -v notify-send &>/dev/null && [[ -n "$DISPLAY" ]]; then
if [[ $EUID -eq 0 ]]; then
# Running as root, send notification as user
sudo -u "$ACTUAL_USER" DISPLAY="$DISPLAY" notify-send "PC Startup Warning" "PC was not turned on between 5AM-8AM as expected on $day_name" --urgency=normal --expire-time=10000 2>/dev/null || true
else
notify-send "PC Startup Warning" "PC was not turned on between 5AM-8AM as expected on $day_name" --urgency=normal --expire-time=10000 2>/dev/null || true
fi
fi
echo "This warning has been logged to the system journal."
echo "You can view startup logs with: journalctl -t pc-startup-monitor"
echo ""
}
# Function to create the monitoring service
create_monitoring_service() {
echo ""
echo "1. Creating PC Startup Monitor Service..."
echo "======================================="
local service_file="/etc/systemd/system/pc-startup-monitor.service"
cat > "$service_file" << 'EOF'
[Unit]
Description=PC Startup Time Monitor
After=multi-user.target
Wants=network.target
[Service]
Type=oneshot
ExecStart=/usr/local/bin/pc-startup-check.sh
StandardOutput=journal
StandardError=journal
RemainAfterExit=true
[Install]
WantedBy=multi-user.target
EOF
echo "✓ Created monitoring service: $service_file"
}
# Function to create the monitoring timer
create_monitoring_timer() {
echo ""
echo "2. Creating PC Startup Monitor Timer..."
echo "====================================="
local timer_file="/etc/systemd/system/pc-startup-monitor.timer"
cat > "$timer_file" << 'EOF'
[Unit]
Description=Timer for PC startup monitoring
Requires=pc-startup-monitor.service
[Timer]
OnCalendar=*-*-* 08:30:00
Persistent=false
AccuracySec=1m
[Install]
WantedBy=timers.target
EOF
echo "✓ Created monitoring timer: $timer_file"
}
# Function to create the main monitoring script
create_monitoring_script() {
echo ""
echo "3. Creating PC Startup Monitor Script..."
echo "======================================"
local script_file="/usr/local/bin/pc-startup-check.sh"
cat > "$script_file" << 'EOF'
#!/bin/bash
# PC Startup Time Monitor Check Script
# Monitors if PC was turned on during expected hours on specific days
# Function to check if today is a monitored day
is_monitored_day() {
local day_of_week=$(date +%u) # 1=Monday, 7=Sunday
# Check if today is Monday (1), Friday (5), Saturday (6), or Sunday (7)
if [[ "$day_of_week" == "1" ]] || [[ "$day_of_week" == "5" ]] || [[ "$day_of_week" == "6" ]] || [[ "$day_of_week" == "7" ]]; then
return 0 # Yes, it's a monitored day
else
return 1 # No, it's not a monitored day
fi
}
# Function to check if current time is between 5AM and 8AM
is_current_time_in_window() {
local current_hour=$(date +%H)
local current_hour_num=$((10#$current_hour))
if [[ $current_hour_num -ge 5 ]] && [[ $current_hour_num -lt 8 ]]; then
return 0 # Yes, current time is in the 5AM-8AM window
else
return 1 # No, current time is outside the window
fi
}
# Function to check if PC was booted between 5AM-8AM today
was_booted_in_window_today() {
local today=$(date +%Y-%m-%d)
# Calculate boot time from uptime
local uptime_seconds=$(awk '{print int($1)}' /proc/uptime 2>/dev/null || echo "0")
local boot_time=$(date -d "@$(($(date +%s) - uptime_seconds))" +"%Y-%m-%d %H:%M:%S")
# Check if boot time is from today
local boot_date=$(echo "$boot_time" | cut -d' ' -f1)
if [[ "$boot_date" != "$today" ]]; then
return 1 # Not booted today
fi
# Extract hour from boot time
local boot_hour=$(echo "$boot_time" | cut -d' ' -f2 | cut -d':' -f1)
local boot_hour_num=$((10#$boot_hour))
# Check if boot time was between 5AM and 8AM
if [[ $boot_hour_num -ge 5 ]] && [[ $boot_hour_num -lt 8 ]]; then
return 0 # Yes, booted in window
else
return 1 # No, not booted in window
fi
}
# Function to show notification/warning
show_startup_warning() {
local day_name=$(date +%A)
local current_time=$(date +"%H:%M")
local today=$(date +%Y-%m-%d)
echo "⚠️ PC STARTUP TIME WARNING"
echo "Date: $today ($day_name)"
echo "Current time: $current_time"
echo "This PC was expected to be turned on between 5:00 AM and 8:00 AM today, but was not."
# Log the warning
logger -t pc-startup-monitor "WARNING: PC was not turned on during expected window (5AM-8AM) on $day_name $today"
}
# Main logic
echo "$(date): PC Startup Monitor Check"
logger -t pc-startup-monitor "Running startup time check at $(date)"
# Step 0: Check if today is a monitored day
if ! is_monitored_day; then
day_name=$(date +%A)
echo "$(date): Today is $day_name - not a monitored day. Skipping check."
logger -t pc-startup-monitor "Skipping check - today ($day_name) is not a monitored day"
exit 0
fi
# Step 1 & 2: Check if current time is between 5AM and 8AM
if is_current_time_in_window; then
echo "$(date): Current time is within 5AM-8AM window. No action needed."
logger -t pc-startup-monitor "Current time is within monitored window (5AM-8AM) - no action needed"
exit 0
fi
# Step 4: Check if PC was turned on between 5AM-8AM today
if was_booted_in_window_today; then
echo "$(date): PC was booted in expected window (5AM-8AM). All good."
logger -t pc-startup-monitor "PC was booted in expected window (5AM-8AM) - compliance OK"
else
echo "$(date): PC was NOT booted in expected window (5AM-8AM). Showing warning."
show_startup_warning
fi
EOF
chmod +x "$script_file"
echo "✓ Created monitoring script: $script_file"
}
# Function to create management script
create_management_script() {
echo ""
echo "4. Creating Management Script..."
echo "=============================="
local script_file="/usr/local/bin/pc-startup-monitor-manager.sh"
cat > "$script_file" << 'EOF'
#!/bin/bash
# PC Startup Monitor Manager
# Provides easy management of the PC startup monitoring feature
TIMER_NAME="pc-startup-monitor.timer"
SERVICE_NAME="pc-startup-monitor.service"
show_status() {
echo "PC Startup Monitor Status"
echo "========================"
if systemctl is-enabled "$TIMER_NAME" &>/dev/null; then
echo "Status: ENABLED"
if systemctl is-active "$TIMER_NAME" &>/dev/null; then
echo "Timer: ACTIVE"
else
echo "Timer: INACTIVE"
fi
else
echo "Status: NOT ENABLED"
fi
echo ""
echo "Next check scheduled:"
systemctl list-timers "$TIMER_NAME" --no-pager 2>/dev/null | grep "$TIMER_NAME" || echo "Timer not active"
echo ""
echo "Recent logs:"
journalctl -t pc-startup-monitor --no-pager -n 10 2>/dev/null || echo "No recent logs"
}
test_now() {
echo "Running startup monitor check now..."
/usr/local/bin/pc-startup-check.sh
}
case "$1" in
"status")
show_status
;;
"logs")
echo "PC Startup Monitor Logs"
echo "======================"
journalctl -t pc-startup-monitor --no-pager -n 30
;;
"test")
test_now
;;
*)
echo "PC Startup Monitor Manager"
echo "Usage: $0 {status|logs|test}"
echo ""
echo "Commands:"
echo " status - Show current status and next check time"
echo " logs - Show recent monitoring logs"
echo " test - Run a startup check now (for testing)"
echo ""
show_status
;;
esac
EOF
chmod +x "$script_file"
echo "✓ Created management script: $script_file"
}
# Function to enable the services
enable_services() {
echo ""
echo "5. Enabling PC Startup Monitor..."
echo "==============================="
# Reload systemd daemon
systemctl daemon-reload
echo "✓ Reloaded systemd daemon"
# Enable and start the timer
systemctl enable pc-startup-monitor.timer
echo "✓ Enabled pc-startup-monitor timer"
systemctl start pc-startup-monitor.timer
echo "✓ Started pc-startup-monitor timer"
}
# Function to test the setup
test_setup() {
echo ""
echo "6. Testing Setup..."
echo "=================="
echo "Service files:"
if [[ -f "/etc/systemd/system/pc-startup-monitor.service" ]]; then
echo "✓ Service file exists"
else
echo "✗ Service file missing"
fi
if [[ -f "/etc/systemd/system/pc-startup-monitor.timer" ]]; then
echo "✓ Timer file exists"
else
echo "✗ Timer file missing"
fi
echo ""
echo "Timer status:"
if systemctl is-enabled pc-startup-monitor.timer &>/dev/null; then
echo "✓ Timer is enabled"
else
echo "✗ Timer is not enabled"
fi
if systemctl is-active pc-startup-monitor.timer &>/dev/null; then
echo "✓ Timer is active"
else
echo "✗ Timer is not active"
fi
echo ""
echo "Testing current logic:"
/usr/local/bin/pc-startup-check.sh
}
# Function to show final instructions
show_instructions() {
echo ""
echo "=========================================="
echo "PC Startup Monitor Setup Complete"
echo "=========================================="
echo "Summary:"
echo "✓ Monitoring service created (/etc/systemd/system/pc-startup-monitor.service)"
echo "✓ Monitoring timer created (/etc/systemd/system/pc-startup-monitor.timer)"
echo "✓ Monitor script created (/usr/local/bin/pc-startup-check.sh)"
echo "✓ Management script created (/usr/local/bin/pc-startup-monitor-manager.sh)"
echo "✓ Timer enabled and started"
echo ""
echo "How it works:"
echo "• Monitors PC startup times on Monday, Friday, Saturday, Sunday"
echo "• Expects PC to be turned on between 5:00 AM - 8:00 AM"
echo "• Checks daily at 8:30 AM if PC was turned on in expected window"
echo "• Shows warning if PC was not turned on during expected time"
echo ""
echo "Management commands:"
echo " sudo pc-startup-monitor-manager.sh status - Check status"
echo " sudo pc-startup-monitor-manager.sh logs - View monitor logs"
echo " sudo pc-startup-monitor-manager.sh test - Test monitor now"
echo ""
echo "Next check: Tomorrow at 8:30 AM (if it's a monitored day)"
echo ""
}
# Function to prompt for confirmation
confirm_setup() {
echo ""
echo "PC Startup Monitor Setup"
echo "======================="
echo "This will set up monitoring for PC startup times."
echo ""
echo "Monitoring schedule:"
echo "- Days: Monday, Friday, Saturday, Sunday"
echo "- Expected startup time: 5:00 AM - 8:00 AM"
echo "- Check time: 8:30 AM daily"
echo "- Action: Show warning if PC wasn't started in expected window"
echo ""
if [[ "$INTERACTIVE_MODE" == "true" ]]; then
read -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
else
echo "Auto-proceeding with setup (use --interactive to prompt)"
echo "Proceeding with setup..."
return 0
fi
}
# Main execution flow
main() {
# Check for sudo privileges
check_sudo "$@"
# Confirm setup
confirm_setup
# Create all components
create_monitoring_service
create_monitoring_timer
create_monitoring_script
create_management_script
# Enable services
enable_services
# Test setup
test_setup
# Show instructions
show_instructions
}
# Run main function
main "$@"