feat: more restrictive midnight shutdown

This commit is contained in:
Krzysztof kuhy Rudnicki 2026-01-02 19:05:59 +01:00
parent 29f6fa61dc
commit 4ebd6c52be
3 changed files with 967 additions and 82 deletions

View File

@ -1,57 +1,53 @@
#!/bin/bash #!/bin/bash
# Shutdown countdown status script for i3blocks # Shutdown countdown status script for i3blocks
# Shows time remaining until the next shutdown window # Shows time remaining until the next shutdown window
# Dynamically reads shutdown times from the systemd check script # Reads shutdown times from shared config file written by setup_midnight_shutdown.sh
SHUTDOWN_CHECK_SCRIPT="/usr/local/bin/day-specific-shutdown-check.sh" SHUTDOWN_CONFIG="/etc/shutdown-schedule.conf"
# Function to extract shutdown hour from the check script # Function to show error state in i3blocks and exit
# Parses lines like "if [[ $current_time_minutes -ge 1260 ]]" where 1260 = 21*60 show_error() {
get_shutdown_hours() { local message="$1"
if [[ ! -f "$SHUTDOWN_CHECK_SCRIPT" ]]; then echo "$message"
# Fallback defaults if script not found echo "⏻"
echo "21 22" echo "#FF79C6" # Pink/magenta for config errors
return exit 0
fi
# Extract the minute thresholds from the script (e.g., 1260 for 21:00, 1320 for 22:00)
# The script checks: if [[ $current_time_minutes -ge XXXX ]]
# Get unique values - first is Mon-Wed (1260=21:00), second is Thu-Sun (1320=22:00)
local thresholds
thresholds=$(grep -oP 'current_time_minutes -ge \K\d{4}' "$SHUTDOWN_CHECK_SCRIPT" 2>/dev/null | sort -u)
if [[ -z "$thresholds" ]]; then
echo "21 22"
return
fi
local mon_wed_minutes thu_sun_minutes
mon_wed_minutes=$(echo "$thresholds" | head -1) # 1260 (smaller = earlier = Mon-Wed)
thu_sun_minutes=$(echo "$thresholds" | tail -1) # 1320 (larger = later = Thu-Sun)
# Convert minutes to hours
local mon_wed_hour=$((mon_wed_minutes / 60))
local thu_sun_hour=$((thu_sun_minutes / 60))
echo "$mon_wed_hour $thu_sun_hour"
} }
# Validate and load config file
if [[ ! -f "$SHUTDOWN_CONFIG" ]]; then
show_error "NO CONFIG"
fi
# Source the config file to get MON_WED_HOUR and THU_SUN_HOUR
# shellcheck source=/dev/null
if ! source "$SHUTDOWN_CONFIG" 2>/dev/null; then
show_error "BAD CONFIG"
fi
# Validate that required variables are set
if [[ -z "${MON_WED_HOUR:-}" ]] || [[ -z "${THU_SUN_HOUR:-}" ]]; then
show_error "MISSING VARS"
fi
# Validate that values are numbers
if ! [[ "$MON_WED_HOUR" =~ ^[0-9]+$ ]] || ! [[ "$THU_SUN_HOUR" =~ ^[0-9]+$ ]]; then
show_error "INVALID HOURS"
fi
# Get current time info # Get current time info
current_hour=$(date +%H) current_hour=$(date +%H)
current_minute=$(date +%M) current_minute=$(date +%M)
current_time_minutes=$((10#$current_hour * 60 + 10#$current_minute)) current_time_minutes=$((10#$current_hour * 60 + 10#$current_minute))
day_of_week=$(date +%u) # 1=Monday, 7=Sunday day_of_week=$(date +%u) # 1=Monday, 7=Sunday
# Get shutdown hours dynamically
read -r mon_wed_hour thu_sun_hour <<<"$(get_shutdown_hours)"
# Determine shutdown hour based on day of week # Determine shutdown hour based on day of week
if [[ $day_of_week -ge 1 ]] && [[ $day_of_week -le 3 ]]; then if [[ $day_of_week -ge 1 ]] && [[ $day_of_week -le 3 ]]; then
# Monday-Wednesday # Monday-Wednesday
shutdown_hour=$mon_wed_hour shutdown_hour=$MON_WED_HOUR
else else
# Thursday-Sunday # Thursday-Sunday
shutdown_hour=$thu_sun_hour shutdown_hour=$THU_SUN_HOUR
fi fi
shutdown_time_minutes=$((shutdown_hour * 60)) shutdown_time_minutes=$((shutdown_hour * 60))

View File

@ -11,6 +11,113 @@ SCRIPT_DIR="$(dirname "$(readlink -f "$0")")"
# shellcheck source=../lib/common.sh # shellcheck source=../lib/common.sh
source "$SCRIPT_DIR/../lib/common.sh" source "$SCRIPT_DIR/../lib/common.sh"
# Schedule constants (single source of truth for this script)
# These values are written to /etc/shutdown-schedule.conf during setup
SCHEDULE_MON_WED_HOUR=21
SCHEDULE_THU_SUN_HOUR=22
SCHEDULE_MORNING_END_HOUR=5
# ============================================================================
# SCHEDULE PROTECTION MECHANISM
# ============================================================================
# This prevents easy "cheating" by modifying the script values and re-running.
# If a canonical config already exists, the script compares against it and
# BLOCKS installation if the new values would make the schedule MORE LENIENT
# (i.e., later shutdown hours or earlier morning end).
# To legitimately change the schedule, use: sudo /usr/local/sbin/unlock-shutdown-schedule
# ============================================================================
CANONICAL_CONFIG="/usr/local/share/locked-shutdown-schedule.conf"
# Check if trying to make schedule more lenient (later shutdown / earlier morning end)
check_schedule_protection() {
# Skip check if no canonical config exists (first install)
if [[ ! -f "$CANONICAL_CONFIG" ]]; then
return 0
fi
# Load canonical values
local canonical_mon_wed canonical_thu_sun canonical_morning_end
# shellcheck source=/dev/null
source "$CANONICAL_CONFIG" 2>/dev/null || return 0
canonical_mon_wed="${MON_WED_HOUR:-}"
canonical_thu_sun="${THU_SUN_HOUR:-}"
canonical_morning_end="${MORNING_END_HOUR:-}"
# If canonical values are empty, skip check
if [[ -z "$canonical_mon_wed" ]] || [[ -z "$canonical_thu_sun" ]] || [[ -z "$canonical_morning_end" ]]; then
return 0
fi
local violations=()
# Check if Mon-Wed hour is being made LATER (more lenient)
if [[ $SCHEDULE_MON_WED_HOUR -gt $canonical_mon_wed ]]; then
violations+=("Mon-Wed shutdown: ${canonical_mon_wed}:00 → ${SCHEDULE_MON_WED_HOUR}:00 (later)")
fi
# Check if Thu-Sun hour is being made LATER (more lenient)
if [[ $SCHEDULE_THU_SUN_HOUR -gt $canonical_thu_sun ]]; then
violations+=("Thu-Sun shutdown: ${canonical_thu_sun}:00 → ${SCHEDULE_THU_SUN_HOUR}:00 (later)")
fi
# Check if morning end is being made EARLIER (more lenient - shorter shutdown window)
if [[ $SCHEDULE_MORNING_END_HOUR -lt $canonical_morning_end ]]; then
violations+=("Morning end: 0${canonical_morning_end}:00 → 0${SCHEDULE_MORNING_END_HOUR}:00 (earlier)")
fi
if [[ ${#violations[@]} -gt 0 ]]; then
echo ""
echo "╔══════════════════════════════════════════════════════════════════╗"
echo "║ ❌ SCHEDULE MODIFICATION BLOCKED - CHEATING DETECTED! ❌ ║"
echo "╚══════════════════════════════════════════════════════════════════╝"
echo ""
echo "You modified the script to make the shutdown schedule MORE LENIENT:"
echo ""
for v in "${violations[@]}"; do
echo "$v"
done
echo ""
echo "Current protected schedule:"
echo " Monday-Wednesday: ${canonical_mon_wed}:00 - 0${canonical_morning_end}:00"
echo " Thursday-Sunday: ${canonical_thu_sun}:00 - 0${canonical_morning_end}:00"
echo ""
echo "Nice try! But this is exactly the kind of late-night bargaining"
echo "that this protection is designed to prevent. 😉"
echo ""
echo "If you REALLY need to change the schedule, use the proper unlock:"
echo " sudo /usr/local/sbin/unlock-shutdown-schedule"
echo ""
echo "This requires waiting through a psychological delay to give you"
echo "time to reconsider whether you actually need more screen time."
echo ""
exit 1
fi
# Making schedule STRICTER is always allowed
local stricter=()
if [[ $SCHEDULE_MON_WED_HOUR -lt $canonical_mon_wed ]]; then
stricter+=("Mon-Wed: ${canonical_mon_wed}:00 → ${SCHEDULE_MON_WED_HOUR}:00 (earlier)")
fi
if [[ $SCHEDULE_THU_SUN_HOUR -lt $canonical_thu_sun ]]; then
stricter+=("Thu-Sun: ${canonical_thu_sun}:00 → ${SCHEDULE_THU_SUN_HOUR}:00 (earlier)")
fi
if [[ $SCHEDULE_MORNING_END_HOUR -gt $canonical_morning_end ]]; then
stricter+=("Morning end: 0${canonical_morning_end}:00 → 0${SCHEDULE_MORNING_END_HOUR}:00 (later)")
fi
if [[ ${#stricter[@]} -gt 0 ]]; then
echo ""
echo " Schedule is being made STRICTER (allowed without unlock):"
for s in "${stricter[@]}"; do
echo "$s"
done
echo ""
fi
return 0
}
# 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"
@ -22,8 +129,8 @@ show_usage() {
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: ${SCHEDULE_MON_WED_HOUR}:00-0${SCHEDULE_MORNING_END_HOUR}:00"
echo " Thursday-Sunday: 22:00-05:00" echo " Thursday-Sunday: ${SCHEDULE_THU_SUN_HOUR}:00-0${SCHEDULE_MORNING_END_HOUR}:00"
echo "" echo ""
echo "NOTE: There is no 'disable' option. This is intentional." echo "NOTE: There is no 'disable' option. This is intentional."
echo " The shutdown timer is protected by a monitor service." echo " The shutdown timer is protected by a monitor service."
@ -114,20 +221,328 @@ show_current_status() {
echo "✗ Monitor is not enabled" echo "✗ Monitor is not enabled"
fi fi
echo ""
# Check config file protection status
echo "Config File Protection Status:"
local config_file="/etc/shutdown-schedule.conf"
local canonical_file="/usr/local/share/locked-shutdown-schedule.conf"
if [[ -f "$config_file" ]]; then
echo "✓ Config file exists"
# Check immutable attribute
if lsattr "$config_file" 2>/dev/null | grep -q '^....i'; then
echo "✓ Config file is immutable (chattr +i)"
else
echo "✗ Config file is NOT immutable"
fi
else
echo "✗ Config file missing"
fi
if [[ -f "$canonical_file" ]]; then
echo "✓ Canonical copy exists"
else
echo "✗ Canonical copy missing"
fi
if systemctl is-enabled shutdown-schedule-guard.path &>/dev/null; then
echo "✓ Config path watcher is enabled"
if systemctl is-active shutdown-schedule-guard.path &>/dev/null; then
echo "✓ Config path watcher is active"
else
echo "✗ Config path watcher is not active"
fi
else
echo "✗ Config path watcher is not enabled"
fi
if [[ -f "/usr/local/sbin/unlock-shutdown-schedule" ]]; then
echo "✓ Unlock script exists"
else
echo "✗ Unlock script missing"
fi
echo "" echo ""
echo "Shutdown Schedule:" echo "Shutdown Schedule:"
echo " Monday-Wednesday: 21:00-05:00" echo " Monday-Wednesday: ${SCHEDULE_MON_WED_HOUR}:00-0${SCHEDULE_MORNING_END_HOUR}:00"
echo " Thursday-Sunday: 22:00-05:00" echo " Thursday-Sunday: ${SCHEDULE_THU_SUN_HOUR}:00-0${SCHEDULE_MORNING_END_HOUR}:00"
echo "" echo ""
echo "NOTE: The shutdown timer is protected by a monitor service." 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 " If you try to disable the timer, it will be automatically re-enabled."
echo "" echo ""
echo "NOTE: The config file is protected by:"
echo " - Immutable attribute (chattr +i)"
echo " - Canonical copy that auto-restores on modification"
echo " - Path watcher service"
echo " To modify: sudo /usr/local/sbin/unlock-shutdown-schedule"
echo ""
}
# Function to create shutdown schedule config file (shared with i3blocks countdown)
# Also creates a canonical (protected) copy and sets immutable attribute
create_shutdown_config() {
echo ""
echo "1. Creating Shutdown Schedule Config..."
echo "======================================="
local config_file="/etc/shutdown-schedule.conf"
local canonical_file="/usr/local/share/locked-shutdown-schedule.conf"
# Remove immutable attribute if it exists (to allow update)
chattr -i "$config_file" 2>/dev/null || true
chattr -i "$canonical_file" 2>/dev/null || true
cat >"$config_file" <<EOF
# Shutdown schedule configuration
# This file is managed by setup_midnight_shutdown.sh
# Used by: day-specific-shutdown-check.sh, shutdown_countdown.sh (i3blocks)
#
# WARNING: This file is protected by:
# 1. Immutable attribute (chattr +i)
# 2. Canonical copy at /usr/local/share/locked-shutdown-schedule.conf
# 3. Path watcher service that auto-restores if modified
#
# To modify this file, you need to:
# 1. Run: sudo /usr/local/sbin/unlock-shutdown-schedule
# 2. Wait through the psychological delay
# 3. Edit the file during the brief unlock window
# 4. The file will be re-locked automatically
# Shutdown hour for Monday-Wednesday (24-hour format)
MON_WED_HOUR=${SCHEDULE_MON_WED_HOUR}
# Shutdown hour for Thursday-Sunday (24-hour format)
THU_SUN_HOUR=${SCHEDULE_THU_SUN_HOUR}
# Morning end hour (shutdown window ends at this hour)
MORNING_END_HOUR=${SCHEDULE_MORNING_END_HOUR}
EOF
chmod 644 "$config_file"
echo "✓ Created shutdown schedule config: $config_file"
# Create canonical (protected) copy
install -m 644 -D "$config_file" "$canonical_file"
echo "✓ Created canonical copy: $canonical_file"
# Set immutable attribute on both files
chattr +i "$config_file" || echo "⚠ Warning: Could not set immutable attribute on $config_file"
chattr +i "$canonical_file" || echo "⚠ Warning: Could not set immutable attribute on $canonical_file"
echo "✓ Set immutable attribute (chattr +i) on config files"
}
# Function to create config guard (path watcher + enforcement + unlock script)
create_config_guard() {
echo ""
echo "2. Creating Config Guard (Path Watcher + Enforcement)..."
echo "========================================================"
local enforce_script="/usr/local/sbin/enforce-shutdown-schedule.sh"
local unlock_script="/usr/local/sbin/unlock-shutdown-schedule"
local guard_service="/etc/systemd/system/shutdown-schedule-guard.service"
local guard_path="/etc/systemd/system/shutdown-schedule-guard.path"
# Create enforcement script
cat >"$enforce_script" <<'EOF'
#!/bin/bash
# Enforce canonical /etc/shutdown-schedule.conf contents
# This script restores the config from canonical copy if tampered
set -euo pipefail
CANONICAL_SOURCE="/usr/local/share/locked-shutdown-schedule.conf"
TARGET="/etc/shutdown-schedule.conf"
LOG_FILE="/var/log/shutdown-schedule-guard.log"
log() {
printf '%s - %s\n' "$(date '+%Y-%m-%d %H:%M:%S')" "$*" | tee -a "$LOG_FILE" >&2
}
if [[ ! -f $CANONICAL_SOURCE ]]; then
log "Canonical config not found at $CANONICAL_SOURCE; aborting enforcement"
exit 0
fi
# Remove immutable attr to check/restore
chattr -i -a "$TARGET" 2>/dev/null || true
if ! cmp -s "$CANONICAL_SOURCE" "$TARGET"; then
log "CONFIG TAMPERING DETECTED restoring $TARGET from canonical copy"
cp "$CANONICAL_SOURCE" "$TARGET"
chmod 644 "$TARGET"
log "Config restored successfully"
else
log "No drift detected (contents identical)"
fi
# Re-apply immutable attribute
chattr +i "$TARGET" || log "Failed to set immutable attribute"
log "Enforcement complete"
EOF
chmod +x "$enforce_script"
echo "✓ Created enforcement script: $enforce_script"
# Create unlock script with psychological delay
cat >"$unlock_script" <<'EOF'
#!/bin/bash
# Unlock shutdown schedule config for editing with psychological friction
# This script:
# 1. Makes you wait (psychological friction to discourage casual changes)
# 2. Temporarily removes protection
# 3. Opens the config in an editor
# 4. Re-applies protection after editing
set -euo pipefail
DELAY_SECONDS=45
CONFIG_FILE="/etc/shutdown-schedule.conf"
CANONICAL_FILE="/usr/local/share/locked-shutdown-schedule.conf"
LOG_FILE="/var/log/shutdown-schedule-guard.log"
EDITOR="${EDITOR:-nano}"
log() {
printf '%s - %s\n' "$(date '+%Y-%m-%d %H:%M:%S')" "$*" | tee -a "$LOG_FILE" >&2
}
# Must be root
if [[ $EUID -ne 0 ]]; then
echo "This script must be run as root (sudo)"
exit 1
fi
# Log the unlock attempt
log "=== UNLOCK ATTEMPT by $(logname 2>/dev/null || echo 'unknown') from TTY $(tty 2>/dev/null || echo 'unknown') ==="
echo ""
echo "╔══════════════════════════════════════════════════════════════════╗"
echo "║ SHUTDOWN SCHEDULE CONFIG UNLOCK - PSYCHOLOGICAL FRICTION ║"
echo "╚══════════════════════════════════════════════════════════════════╝"
echo ""
echo "You are about to modify the shutdown schedule configuration."
echo "This file controls when your PC automatically shuts down for"
echo "digital wellbeing purposes."
echo ""
echo "Current schedule:"
if [[ -f "$CONFIG_FILE" ]]; then
chattr -i "$CONFIG_FILE" 2>/dev/null || true
source "$CONFIG_FILE" 2>/dev/null || true
chattr +i "$CONFIG_FILE" 2>/dev/null || true
echo " Monday-Wednesday: ${MON_WED_HOUR:-??}:00 - 0${MORNING_END_HOUR:-?}:00"
echo " Thursday-Sunday: ${THU_SUN_HOUR:-??}:00 - 0${MORNING_END_HOUR:-?}:00"
fi
echo ""
echo "Are you making this change for a good reason, or are you just"
echo "trying to stay up later? Remember why you set these limits."
echo ""
echo "To proceed, you must wait $DELAY_SECONDS seconds..."
echo ""
# Countdown with opportunity to cancel
for ((i=DELAY_SECONDS; i>0; i--)); do
printf "\r ⏳ Waiting: %2d seconds remaining... (Ctrl+C to cancel)" "$i"
sleep 1
done
echo ""
echo ""
log "User waited through delay, proceeding with unlock"
# Stop the path watcher temporarily
systemctl stop shutdown-schedule-guard.path 2>/dev/null || true
# Remove immutable attributes
chattr -i -a "$CONFIG_FILE" 2>/dev/null || true
chattr -i -a "$CANONICAL_FILE" 2>/dev/null || true
echo "Config file unlocked. Opening editor..."
echo "After saving, protection will be re-applied automatically."
echo ""
# Open editor
$EDITOR "$CONFIG_FILE"
echo ""
echo "Re-applying protection..."
# Copy to canonical
cp "$CONFIG_FILE" "$CANONICAL_FILE"
chmod 644 "$CONFIG_FILE"
chmod 644 "$CANONICAL_FILE"
# Re-apply immutable
chattr +i "$CONFIG_FILE" || echo "Warning: Could not set immutable attribute"
chattr +i "$CANONICAL_FILE" || echo "Warning: Could not set immutable attribute"
# Restart path watcher
systemctl start shutdown-schedule-guard.path 2>/dev/null || true
log "Config updated and re-locked by user"
echo ""
echo "✓ Config file updated and re-protected"
echo "✓ Canonical copy updated"
echo "✓ Path watcher re-enabled"
echo ""
echo "New schedule (will take effect on next timer check):"
source "$CONFIG_FILE" 2>/dev/null || true
echo " Monday-Wednesday: ${MON_WED_HOUR:-??}:00 - 0${MORNING_END_HOUR:-?}:00"
echo " Thursday-Sunday: ${THU_SUN_HOUR:-??}:00 - 0${MORNING_END_HOUR:-?}:00"
echo ""
EOF
chmod +x "$unlock_script"
echo "✓ Created unlock script: $unlock_script"
# Create path watcher unit
cat >"$guard_path" <<'EOF'
[Unit]
Description=Watch /etc/shutdown-schedule.conf and trigger enforcement
[Path]
PathChanged=/etc/shutdown-schedule.conf
Unit=shutdown-schedule-guard.service
[Install]
WantedBy=multi-user.target
EOF
echo "✓ Created path watcher: $guard_path"
# Create enforcement service
cat >"$guard_service" <<'EOF'
[Unit]
Description=Enforce canonical /etc/shutdown-schedule.conf contents
After=local-fs.target
[Service]
Type=oneshot
ExecStart=/usr/local/sbin/enforce-shutdown-schedule.sh
Nice=10
IOSchedulingClass=idle
[Install]
WantedBy=multi-user.target
EOF
echo "✓ Created guard service: $guard_service"
# Reload and enable
systemctl daemon-reload
systemctl enable --now shutdown-schedule-guard.path
echo "✓ Enabled and started shutdown-schedule-guard.path"
# Run initial enforcement
"$enforce_script" || echo "⚠ Warning: Initial enforcement returned non-zero"
echo "✓ Ran initial enforcement"
} }
# 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 "3. 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"
@ -152,7 +567,7 @@ EOF
# 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 "4. 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"
@ -163,10 +578,6 @@ Description=Timer for automatic PC shutdown with day-specific windows
Requires=day-specific-shutdown.service Requires=day-specific-shutdown.service
[Timer] [Timer]
OnCalendar=*-*-* 21:00:00
OnCalendar=*-*-* 21:30:00
OnCalendar=*-*-* 22:00:00
OnCalendar=*-*-* 22:30:00
OnCalendar=*-*-* 23:00:00 OnCalendar=*-*-* 23:00:00
OnCalendar=*-*-* 23:30:00 OnCalendar=*-*-* 23:30:00
OnCalendar=*-*-* 00:00:00 OnCalendar=*-*-* 00:00:00
@ -195,7 +606,7 @@ EOF
# Function to create management script # Function to create management script
create_management_script() { create_management_script() {
echo "" echo ""
echo "3. Creating Management Script..." echo "5. 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"
@ -207,6 +618,27 @@ create_management_script() {
TIMER_NAME="day-specific-shutdown.timer" TIMER_NAME="day-specific-shutdown.timer"
SERVICE_NAME="day-specific-shutdown.service" SERVICE_NAME="day-specific-shutdown.service"
CONFIG_FILE="/etc/shutdown-schedule.conf"
# Load config for schedule display
load_config() {
if [[ -f "$CONFIG_FILE" ]]; then
# shellcheck source=/dev/null
source "$CONFIG_FILE"
else
echo "Warning: Config file $CONFIG_FILE not found"
MON_WED_HOUR="??"
THU_SUN_HOUR="??"
MORNING_END_HOUR="??"
fi
}
print_schedule() {
load_config
echo "Shutdown Schedule:"
echo " Monday-Wednesday: ${MON_WED_HOUR}:00-0${MORNING_END_HOUR}:00"
echo " Thursday-Sunday: ${THU_SUN_HOUR}:00-0${MORNING_END_HOUR}:00"
}
show_status() { show_status() {
echo "Day-Specific Auto-Shutdown Status" echo "Day-Specific Auto-Shutdown Status"
@ -224,9 +656,7 @@ show_status() {
fi fi
echo "" echo ""
echo "Shutdown Schedule:" print_schedule
echo " Monday-Wednesday: 21:00-05:00"
echo " Thursday-Sunday: 22:00-05:00"
echo "" echo ""
echo "Next scheduled checks:" echo "Next scheduled checks:"
@ -254,9 +684,7 @@ case "$1" in
echo " status - Show current status and next shutdown checks" echo " status - Show current status and next shutdown checks"
echo " logs - Show recent shutdown logs" echo " logs - Show recent shutdown logs"
echo "" echo ""
echo "Shutdown Schedule:" print_schedule
echo " Monday-Wednesday: 21:00-05:00"
echo " Thursday-Sunday: 22:00-05:00"
echo "" echo ""
show_status show_status
;; ;;
@ -270,7 +698,7 @@ EOF
# 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 "6. 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"
@ -278,9 +706,23 @@ create_shutdown_check_script() {
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: # Reads shutdown windows from /etc/shutdown-schedule.conf
# Monday-Wednesday: 21:00-05:00
# Thursday-Sunday: 22:00-05:00 CONFIG_FILE="/etc/shutdown-schedule.conf"
# Load config
if [[ ! -f "$CONFIG_FILE" ]]; then
logger -t day-specific-shutdown "ERROR: Config file $CONFIG_FILE not found"
exit 1
fi
# shellcheck source=/dev/null
source "$CONFIG_FILE"
# Validate config
if [[ -z "${MON_WED_HOUR:-}" ]] || [[ -z "${THU_SUN_HOUR:-}" ]] || [[ -z "${MORNING_END_HOUR:-}" ]]; then
logger -t day-specific-shutdown "ERROR: Config file missing required variables"
exit 1
fi
# Get current time and day # Get current time and day
current_hour=$(date +%H) current_hour=$(date +%H)
@ -289,9 +731,10 @@ current_time_minutes=$((10#$current_hour * 60 + 10#$current_minute))
day_of_week=$(date +%u) # 1=Monday, 7=Sunday day_of_week=$(date +%u) # 1=Monday, 7=Sunday
day_name=$(date +%A) day_name=$(date +%A)
# Convert time to minutes for easier comparison # Calculate minute thresholds from config
# 21:00 = 1260 minutes, 22:00 = 1320 minutes, 05:00 = 300 minutes mon_wed_minutes=$((MON_WED_HOUR * 60))
# 00:00 = 0 minutes, 05:00 = 300 minutes thu_sun_minutes=$((THU_SUN_HOUR * 60))
morning_end_minutes=$((MORNING_END_HOUR * 60))
logger -t day-specific-shutdown "Checking shutdown conditions at $(date) - Day: $day_name ($day_of_week), Time: $current_hour:$current_minute" logger -t day-specific-shutdown "Checking shutdown conditions at $(date) - Day: $day_name ($day_of_week), Time: $current_hour:$current_minute"
@ -299,36 +742,34 @@ logger -t day-specific-shutdown "Checking shutdown conditions at $(date) - Day:
should_shutdown=false should_shutdown=false
if [[ $day_of_week -ge 1 ]] && [[ $day_of_week -le 3 ]]; then if [[ $day_of_week -ge 1 ]] && [[ $day_of_week -le 3 ]]; then
# Monday (1), Tuesday (2), Wednesday (3): shutdown window 21:00-05:00 # Monday (1), Tuesday (2), Wednesday (3)
logger -t day-specific-shutdown "Today is $day_name - checking 21:00-05:00 window" shutdown_start=$mon_wed_minutes
logger -t day-specific-shutdown "Today is $day_name - checking ${MON_WED_HOUR}:00-0${MORNING_END_HOUR}:00 window"
# Check if time is between 21:00 (1260 minutes) and 23:59 (1439 minutes) if [[ $current_time_minutes -ge $shutdown_start ]] || [[ $current_time_minutes -le $morning_end_minutes ]]; then
# OR between 00:00 (0 minutes) and 05:00 (300 minutes)
if [[ $current_time_minutes -ge 1260 ]] || [[ $current_time_minutes -le 300 ]]; then
should_shutdown=true should_shutdown=true
if [[ $current_time_minutes -ge 1260 ]]; then if [[ $current_time_minutes -ge $shutdown_start ]]; then
logger -t day-specific-shutdown "Time $current_hour:$current_minute is within evening shutdown window (21:00-23:59)" logger -t day-specific-shutdown "Time $current_hour:$current_minute is within evening shutdown window (${MON_WED_HOUR}:00-23:59)"
else else
logger -t day-specific-shutdown "Time $current_hour:$current_minute is within morning shutdown window (00:00-05:00)" logger -t day-specific-shutdown "Time $current_hour:$current_minute is within morning shutdown window (00:00-0${MORNING_END_HOUR}:00)"
fi fi
else else
logger -t day-specific-shutdown "Time $current_hour:$current_minute is outside shutdown window (21:00-05:00)" logger -t day-specific-shutdown "Time $current_hour:$current_minute is outside shutdown window (${MON_WED_HOUR}:00-0${MORNING_END_HOUR}:00)"
fi fi
else else
# Thursday (4), Friday (5), Saturday (6), Sunday (7): shutdown window 22:00-05:00 # Thursday (4), Friday (5), Saturday (6), Sunday (7)
logger -t day-specific-shutdown "Today is $day_name - checking 22:00-05:00 window" shutdown_start=$thu_sun_minutes
logger -t day-specific-shutdown "Today is $day_name - checking ${THU_SUN_HOUR}:00-0${MORNING_END_HOUR}:00 window"
# Check if time is between 22:00 (1320 minutes) and 23:59 (1439 minutes) if [[ $current_time_minutes -ge $shutdown_start ]] || [[ $current_time_minutes -le $morning_end_minutes ]]; then
# OR between 00:00 (0 minutes) and 05:00 (300 minutes)
if [[ $current_time_minutes -ge 1320 ]] || [[ $current_time_minutes -le 300 ]]; then
should_shutdown=true should_shutdown=true
if [[ $current_time_minutes -ge 1320 ]]; then if [[ $current_time_minutes -ge $shutdown_start ]]; then
logger -t day-specific-shutdown "Time $current_hour:$current_minute is within evening shutdown window (22:00-23:59)" logger -t day-specific-shutdown "Time $current_hour:$current_minute is within evening shutdown window (${THU_SUN_HOUR}:00-23:59)"
else else
logger -t day-specific-shutdown "Time $current_hour:$current_minute is within morning shutdown window (00:00-05:00)" logger -t day-specific-shutdown "Time $current_hour:$current_minute is within morning shutdown window (00:00-0${MORNING_END_HOUR}:00)"
fi fi
else else
logger -t day-specific-shutdown "Time $current_hour:$current_minute is outside shutdown window (22:00-05:00)" logger -t day-specific-shutdown "Time $current_hour:$current_minute is outside shutdown window (${THU_SUN_HOUR}:00-0${MORNING_END_HOUR}:00)"
fi fi
fi fi
@ -368,7 +809,7 @@ enable_timer() {
# Function to install the monitor service # Function to install the monitor service
install_monitor_service() { install_monitor_service() {
echo "" echo ""
echo "6. Installing Shutdown Timer Monitor Service..." echo "7. Installing Shutdown Timer Monitor Service..."
echo "==============================================" echo "=============================================="
local monitor_script="/usr/local/bin/shutdown-timer-monitor.sh" local monitor_script="/usr/local/bin/shutdown-timer-monitor.sh"
@ -533,7 +974,7 @@ EOF
# Function to test the setup # Function to test the setup
test_setup() { test_setup() {
echo "" echo ""
echo "7. Testing Setup..." echo "8. Testing Setup..."
echo "==================" echo "=================="
echo "Service files:" echo "Service files:"
@ -597,6 +1038,46 @@ test_setup() {
echo "✗ Watchdog timer is not active" echo "✗ Watchdog timer is not active"
fi fi
echo ""
echo "Config file protection status:"
local config_file="/etc/shutdown-schedule.conf"
local canonical_file="/usr/local/share/locked-shutdown-schedule.conf"
if [[ -f "$config_file" ]]; then
echo "✓ Config file exists"
if lsattr "$config_file" 2>/dev/null | grep -q '^....i'; then
echo "✓ Config file is immutable"
else
echo "✗ Config file is NOT immutable"
fi
else
echo "✗ Config file missing"
fi
if [[ -f "$canonical_file" ]]; then
echo "✓ Canonical copy exists"
else
echo "✗ Canonical copy missing"
fi
if systemctl is-enabled shutdown-schedule-guard.path &>/dev/null; then
echo "✓ Config guard path watcher is enabled"
else
echo "✗ Config guard path watcher is not enabled"
fi
if systemctl is-active shutdown-schedule-guard.path &>/dev/null; then
echo "✓ Config guard path watcher is active"
else
echo "✗ Config guard path watcher is not active"
fi
if [[ -f "/usr/local/sbin/unlock-shutdown-schedule" ]]; then
echo "✓ Unlock script exists"
else
echo "✗ Unlock script missing"
fi
echo "" echo ""
echo "Next scheduled checks:" 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" systemctl list-timers day-specific-shutdown.timer --no-pager 2>/dev/null | head -5 | grep day-specific-shutdown || echo "Timer information not available"
@ -604,9 +1085,23 @@ test_setup() {
# Display the shutdown schedule (used in multiple places) # Display the shutdown schedule (used in multiple places)
print_shutdown_schedule() { print_shutdown_schedule() {
# Convert 24h to 12h format for display
local mon_wed_12h thu_sun_12h morning_12h
if [[ $SCHEDULE_MON_WED_HOUR -gt 12 ]]; then
mon_wed_12h="$((SCHEDULE_MON_WED_HOUR - 12)):00 PM"
else
mon_wed_12h="${SCHEDULE_MON_WED_HOUR}:00 AM"
fi
if [[ $SCHEDULE_THU_SUN_HOUR -gt 12 ]]; then
thu_sun_12h="$((SCHEDULE_THU_SUN_HOUR - 12)):00 PM"
else
thu_sun_12h="${SCHEDULE_THU_SUN_HOUR}:00 AM"
fi
morning_12h="${SCHEDULE_MORNING_END_HOUR}:00 AM"
echo "Shutdown Schedule:" echo "Shutdown Schedule:"
echo " Monday-Wednesday: 21:00-05:00 (9:00 PM to 5:00 AM)" echo " Monday-Wednesday: ${SCHEDULE_MON_WED_HOUR}:00-0${SCHEDULE_MORNING_END_HOUR}:00 (${mon_wed_12h} to ${morning_12h})"
echo " Thursday-Sunday: 22:00-05:00 (10:00 PM to 5:00 AM)" echo " Thursday-Sunday: ${SCHEDULE_THU_SUN_HOUR}:00-0${SCHEDULE_MORNING_END_HOUR}:00 (${thu_sun_12h} to ${morning_12h})"
} }
# Function to show final instructions # Function to show final instructions
@ -623,6 +1118,7 @@ show_instructions() {
echo "✓ Timer enabled and started" echo "✓ Timer enabled and started"
echo "✓ Monitor service installed (protects timer from being disabled)" echo "✓ Monitor service installed (protects timer from being disabled)"
echo "✓ Watchdog timer installed (restarts monitor if stopped)" echo "✓ Watchdog timer installed (restarts monitor if stopped)"
echo "✓ Config file protected (immutable + path watcher + canonical copy)"
echo "" echo ""
print_shutdown_schedule print_shutdown_schedule
echo "" echo ""
@ -630,12 +1126,19 @@ show_instructions() {
echo " sudo day-specific-shutdown-manager.sh status - Check status" echo " sudo day-specific-shutdown-manager.sh status - Check status"
echo " sudo day-specific-shutdown-manager.sh logs - View shutdown logs" echo " sudo day-specific-shutdown-manager.sh logs - View shutdown logs"
echo "" echo ""
echo "To modify shutdown hours (with psychological friction):"
echo " sudo /usr/local/sbin/unlock-shutdown-schedule"
echo ""
echo "How it works:" echo "How it works:"
echo "• Timer checks every 30 minutes during potential shutdown windows" echo "• Timer checks every 30 minutes during potential shutdown windows"
echo "• Smart logic determines shutdown eligibility based on day and time" echo "• Smart logic determines shutdown eligibility based on day and time"
echo "• Monitor service watches the timer and re-enables it if disabled" echo "• Monitor service watches the timer and re-enables it if disabled"
echo "• Watchdog timer restarts the monitor every 60 seconds if stopped" echo "• Watchdog timer restarts the monitor every 60 seconds if stopped"
echo "• Monitor has RefuseManualStop=true to prevent easy stopping" echo "• Monitor has RefuseManualStop=true to prevent easy stopping"
echo "• Config file is protected by:"
echo " - Immutable attribute (chattr +i)"
echo " - Canonical copy at /usr/local/share/locked-shutdown-schedule.conf"
echo " - Path watcher that auto-restores if you modify the file"
echo "• There is NO disable option - this is intentional for digital wellbeing" echo "• There is NO disable option - this is intentional for digital wellbeing"
echo "" echo ""
echo "WARNING: This will automatically shutdown your PC during designated hours." echo "WARNING: This will automatically shutdown your PC during designated hours."
@ -683,9 +1186,18 @@ enable_midnight_shutdown() {
echo "Target user: $ACTUAL_USER" echo "Target user: $ACTUAL_USER"
echo "User home: $USER_HOME" echo "User home: $USER_HOME"
# Check if trying to cheat by making schedule more lenient
check_schedule_protection
# Confirm setup # Confirm setup
confirm_setup confirm_setup
# Create config file (shared with i3blocks countdown script)
create_shutdown_config
# Create config guard (path watcher, enforcement, unlock script)
create_config_guard
# Create systemd files # Create systemd files
create_shutdown_service create_shutdown_service
create_shutdown_timer create_shutdown_timer

377
scripts/fixes/fix_thorium.sh Executable file
View File

@ -0,0 +1,377 @@
#!/usr/bin/env bash
# Fix Thorium Browser crashes and startup issues
#
# Common causes addressed:
# - Corrupted Local State file (most common)
# - Stale singleton lock files
# - Corrupted GPU/shader cache
# - Profile database corruption
#
# Usage:
# ./fix_thorium.sh # Auto-fix common issues
# ./fix_thorium.sh --aggressive # Also clear more caches (may lose some settings)
# ./fix_thorium.sh --test # Test if Thorium starts after fix
set -euo pipefail
SCRIPT_DIR="$(dirname "$(readlink -f "$0")")"
# shellcheck source=../lib/common.sh
source "$SCRIPT_DIR/../lib/common.sh"
# Configuration
THORIUM_CONFIG_DIR="${HOME}/.config/thorium"
BACKUP_SUFFIX=".bak.$(date +%Y%m%d_%H%M%S)"
AGGRESSIVE=false
TEST_AFTER=false
# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m' # No Color
usage() {
cat <<EOF
fix_thorium.sh - Fix Thorium Browser crashes and startup issues
Usage: $(basename "$0") [OPTIONS]
Options:
--aggressive Clear additional caches (IndexedDB, Service Worker, etc.)
May cause loss of some site data but more thorough fix
--test Test if Thorium starts successfully after applying fixes
--dry-run Show what would be done without making changes
-h, --help Show this help message
Common issues fixed:
- Corrupted 'Local State' file (causes immediate segfault)
- Stale singleton lock files (prevents startup)
- Corrupted GPU/shader cache
- Crashpad errors
Examples:
$(basename "$0") # Apply standard fixes
$(basename "$0") --test # Fix and verify browser starts
$(basename "$0") --aggressive # Deep clean (use if standard fix fails)
EOF
}
DRY_RUN=false
while [[ $# -gt 0 ]]; do
case "$1" in
--aggressive)
AGGRESSIVE=true
shift
;;
--test)
TEST_AFTER=true
shift
;;
--dry-run)
DRY_RUN=true
shift
;;
-h | --help)
usage
exit 0
;;
*)
log_error "Unknown option: $1"
usage
exit 1
;;
esac
done
# Check if Thorium is installed
check_thorium_installed() {
if ! command -v thorium-browser &>/dev/null; then
log_error "thorium-browser not found in PATH"
echo -e "${YELLOW}Install with: yay -S thorium-browser-bin${NC}"
exit 1
fi
log_info "Found Thorium: $(thorium-browser --version 2>/dev/null | head -1)"
}
# Check if config directory exists
check_config_exists() {
if [[ ! -d "$THORIUM_CONFIG_DIR" ]]; then
log_warn "Thorium config directory not found: $THORIUM_CONFIG_DIR"
log_info "This may be a fresh install - try running thorium-browser directly"
exit 0
fi
}
# Kill any running Thorium processes
kill_thorium() {
local count
count=$(pgrep -c thorium 2>/dev/null || true)
count=${count:-0}
if [[ $count -gt 0 ]]; then
log_info "Stopping $count running Thorium process(es)..."
if [[ $DRY_RUN == true ]]; then
echo " [dry-run] Would kill thorium processes"
else
pkill -9 thorium 2>/dev/null || true
sleep 1
fi
fi
}
# Backup a file/directory if it exists
backup_if_exists() {
local path="$1"
local name
name=$(basename "$path")
if [[ -e "$path" ]]; then
local backup_path="${path}${BACKUP_SUFFIX}"
if [[ $DRY_RUN == true ]]; then
echo " [dry-run] Would backup: $name"
else
mv "$path" "$backup_path"
log_ok "Backed up: $name -> $(basename "$backup_path")"
fi
return 0
fi
return 1
}
# Remove file/directory if it exists
remove_if_exists() {
local path="$1"
local name
name=$(basename "$path")
if [[ -e "$path" ]]; then
if [[ $DRY_RUN == true ]]; then
echo " [dry-run] Would remove: $name"
else
rm -rf "$path"
log_ok "Removed: $name"
fi
return 0
fi
return 1
}
# Fix 1: Handle corrupted Local State file (most common crash cause)
fix_local_state() {
log_info "Checking Local State file..."
local local_state="$THORIUM_CONFIG_DIR/Local State"
if [[ -f "$local_state" ]]; then
# Check if it's valid JSON
if ! python3 -c "import json; json.load(open('$local_state'))" 2>/dev/null; then
log_warn "Local State file appears corrupted"
backup_if_exists "$local_state"
else
# Even if valid JSON, back it up as it can still cause crashes
log_info "Local State exists - backing up (common crash source)"
backup_if_exists "$local_state"
fi
else
log_info "No Local State file found (OK for fresh install)"
fi
}
# Fix 2: Clear singleton lock files
fix_singleton_locks() {
log_info "Clearing singleton lock files..."
local locks=(
"$THORIUM_CONFIG_DIR/SingletonLock"
"$THORIUM_CONFIG_DIR/SingletonSocket"
"$THORIUM_CONFIG_DIR/SingletonCookie"
)
local cleared=0
for lock in "${locks[@]}"; do
if remove_if_exists "$lock"; then
((cleared++)) || true
fi
done
if [[ $cleared -eq 0 ]]; then
log_info "No stale lock files found"
fi
}
# Fix 3: Clear GPU cache
fix_gpu_cache() {
log_info "Clearing GPU cache..."
local gpu_paths=(
"$THORIUM_CONFIG_DIR/GPUCache"
"$THORIUM_CONFIG_DIR/Default/GPUCache"
"$THORIUM_CONFIG_DIR/ShaderCache"
"$THORIUM_CONFIG_DIR/Default/ShaderCache"
)
local cleared=0
for cache in "${gpu_paths[@]}"; do
if remove_if_exists "$cache"; then
((cleared++)) || true
fi
done
if [[ $cleared -eq 0 ]]; then
log_info "No GPU cache to clear"
fi
}
# Fix 4: Clear crash reports (can accumulate and cause issues)
fix_crash_reports() {
log_info "Clearing old crash reports..."
local crash_dir="$THORIUM_CONFIG_DIR/Crash Reports"
if [[ -d "$crash_dir" ]]; then
local crash_count
crash_count=$(find "$crash_dir" -type f 2>/dev/null | wc -l)
if [[ $crash_count -gt 0 ]]; then
if [[ $DRY_RUN == true ]]; then
echo " [dry-run] Would clear $crash_count crash report(s)"
else
rm -rf "$crash_dir"
log_ok "Cleared $crash_count crash report(s)"
fi
fi
fi
}
# Fix 5: Aggressive cleaning (optional)
fix_aggressive() {
if [[ $AGGRESSIVE != true ]]; then
return
fi
log_warn "Applying aggressive fixes (may lose some site data)..."
local aggressive_paths=(
"$THORIUM_CONFIG_DIR/Default/Service Worker"
"$THORIUM_CONFIG_DIR/Default/Cache"
"$THORIUM_CONFIG_DIR/Default/Code Cache"
"$THORIUM_CONFIG_DIR/Default/IndexedDB"
"$THORIUM_CONFIG_DIR/BrowserMetrics"
"$THORIUM_CONFIG_DIR/component_crx_cache"
)
for path in "${aggressive_paths[@]}"; do
remove_if_exists "$path"
done
# Backup potentially corrupted databases
local db_files=(
"$THORIUM_CONFIG_DIR/Default/Web Data"
"$THORIUM_CONFIG_DIR/Default/History"
)
for db in "${db_files[@]}"; do
if [[ -f "$db" ]]; then
log_info "Checking database: $(basename "$db")"
# Simple corruption check - if sqlite3 can't open it, back it up
if command -v sqlite3 &>/dev/null; then
if ! sqlite3 "$db" "PRAGMA integrity_check;" &>/dev/null; then
log_warn "Database may be corrupted: $(basename "$db")"
backup_if_exists "$db"
fi
fi
fi
done
}
# Test if Thorium starts successfully
test_thorium() {
if [[ $TEST_AFTER != true ]]; then
return
fi
log_info "Testing Thorium startup..."
if [[ $DRY_RUN == true ]]; then
echo " [dry-run] Would test thorium-browser startup"
return
fi
# Start Thorium in background
thorium-browser &>/dev/null &
local pid=$!
# Wait a few seconds and check if it's still running
sleep 4
if kill -0 "$pid" 2>/dev/null; then
log_ok "Thorium started successfully! (PID: $pid)"
echo -e "${GREEN}Fix successful!${NC} Thorium is now running."
# Offer to keep it running or kill it
read -r -p "Keep browser running? [Y/n] " response
case "$response" in
[nN]*)
kill "$pid" 2>/dev/null || true
log_info "Browser closed"
;;
*)
log_info "Browser left running"
;;
esac
else
log_error "Thorium still crashing after fixes"
echo -e "${RED}Standard fixes did not resolve the issue.${NC}"
echo ""
echo "Try these additional steps:"
echo " 1. Run with --aggressive flag for deeper cleaning"
echo " 2. Test with fresh profile: thorium-browser --user-data-dir=/tmp/thorium-test"
echo " 3. Reinstall: yay -S thorium-browser-bin"
echo " 4. Check NVIDIA drivers: nvidia-smi"
exit 1
fi
}
# Main execution
main() {
echo "========================================"
echo " Thorium Browser Fix Script"
echo "========================================"
echo ""
if [[ $DRY_RUN == true ]]; then
echo -e "${YELLOW}[DRY RUN MODE - no changes will be made]${NC}"
echo ""
fi
check_thorium_installed
check_config_exists
echo ""
log_info "Applying fixes to: $THORIUM_CONFIG_DIR"
echo ""
kill_thorium
fix_local_state
fix_singleton_locks
fix_gpu_cache
fix_crash_reports
fix_aggressive
echo ""
echo "========================================"
log_ok "Fixes applied!"
echo "========================================"
if [[ $DRY_RUN != true ]]; then
echo ""
echo "Backups created with suffix: $BACKUP_SUFFIX"
echo "To restore: mv ~/.config/thorium/Local\\ State${BACKUP_SUFFIX} ~/.config/thorium/Local\\ State"
fi
test_thorium
if [[ $TEST_AFTER != true ]]; then
echo ""
echo "Run 'thorium-browser' to test, or use: $(basename "$0") --test"
fi
}
main "$@"