#!/bin/bash # PC Monitor Service Fix Script # Fixes notification issues with systemd service set -euo pipefail RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' BLUE='\033[0;34m' NC='\033[0m' print_status() { echo -e "${GREEN}[FIX]${NC} $1" } print_error() { echo -e "${RED}[ERROR]${NC} $1" } print_header() { echo -e "${BLUE}================================${NC}" echo -e "${BLUE} PC Monitor Service Fixer${NC}" echo -e "${BLUE}================================${NC}" } # Check if running as root if [[ $EUID -ne 0 ]]; then print_error "This script must be run as root (use sudo)" exit 1 fi print_header # Stop the failing service print_status "Stopping current service..." systemctl stop pc-monitor.service 2>/dev/null || true # Create fixed version of the script print_status "Creating fixed PC Monitor script..." cat > /usr/local/bin/pc-monitor << 'EOF' #!/bin/bash # PC Anti-Freeze Monitor - Fixed for Systemd set -euo pipefail readonly CONFIG_FILE="/etc/pc-monitor.conf" readonly LOG_FILE="/var/log/pc-monitor.log" readonly PID_FILE="/var/run/pc-monitor.pid" # Default thresholds CPU_THRESHOLD=85 MEMORY_THRESHOLD=90 TEMP_THRESHOLD=80 DISK_THRESHOLD=95 PROCESS_HANG_TIME=30 SWAP_THRESHOLD=80 LOAD_AVG_THRESHOLD=10 # Initialize logging exec 1> >(tee -a "$LOG_FILE") exec 2>&1 log() { echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1" } # Fixed notification system for systemd send_notification() { local title="$1" local message="$2" local urgency="${3:-normal}" log "NOTIFICATION: $title - $message" # Find active user sessions using loginctl (systemd-aware) if command -v loginctl >/dev/null 2>&1; then loginctl list-sessions --no-header 2>/dev/null | while read session_info; do local session_id=$(echo "$session_info" | awk '{print $1}') # Get session details local user_name=$(loginctl show-session "$session_id" -p Name --value 2>/dev/null || continue) local session_type=$(loginctl show-session "$session_id" -p Type --value 2>/dev/null || continue) # Only send to graphical sessions if [[ "$session_type" == "x11" || "$session_type" == "wayland" ]]; then # Try to find the user's DISPLAY local display_var="" if pgrep -u "$user_name" -x "Xorg\|X" >/dev/null 2>&1; then display_var=":0" elif pgrep -u "$user_name" -f "wayland\|weston" >/dev/null 2>&1; then display_var="wayland-0" fi if [[ -n "$display_var" ]]; then sudo -u "$user_name" DISPLAY="$display_var" \ notify-send --urgency="$urgency" --expire-time=5000 \ --icon="dialog-warning" "$title" "$message" 2>/dev/null || true fi fi done fi # Fallback: try to find any active X session for display_file in /tmp/.X11-unix/X*; do if [[ -e "$display_file" ]]; then local display_num="${display_file##*/X}" # Find user running X session local x_user=$(ps aux | grep "[X]org.*:$display_num" | awk '{print $1}' | head -1) if [[ -n "$x_user" && "$x_user" != "root" ]]; then sudo -u "$x_user" DISPLAY=":$display_num" \ notify-send --urgency="$urgency" --expire-time=5000 \ --icon="dialog-warning" "$title" "$message" 2>/dev/null || true fi fi done } # Get process information get_process_info() { local pid="$1" if [[ ! -d "/proc/$pid" ]]; then return 1 fi local name=$(ps -p "$pid" -o comm= 2>/dev/null || echo "unknown") local cpu_percent=$(ps -p "$pid" -o %cpu= 2>/dev/null || echo "0") local mem_percent=$(ps -p "$pid" -o %mem= 2>/dev/null || echo "0") local mem_mb=$(awk '/VmRSS:/ {print int($2/1024)}' "/proc/$pid/status" 2>/dev/null || echo "0") echo "NAME:$name CPU:$cpu_percent MEM:$mem_percent MEM_MB:$mem_mb" } # Kill process with notification kill_process_with_notification() { local pid="$1" local reason="$2" local resource_info="$3" local process_info=$(get_process_info "$pid") if [[ $? -eq 0 ]]; then local name=$(echo "$process_info" | grep -o 'NAME:[^[:space:]]*' | cut -d: -f2) local cpu=$(echo "$process_info" | grep -o 'CPU:[^[:space:]]*' | cut -d: -f2) local mem=$(echo "$process_info" | grep -o 'MEM:[^[:space:]]*' | cut -d: -f2) local mem_mb=$(echo "$process_info" | grep -o 'MEM_MB:[^[:space:]]*' | cut -d: -f2) if kill -9 "$pid" 2>/dev/null; then local notification_title="⚠️ Process Terminated - System Protected" local notification_message="Killed '$name' (PID: $pid) Reason: $reason Resource Usage: CPU: ${cpu}%, RAM: ${mem}% (${mem_mb}MB) $resource_info" send_notification "$notification_title" "$notification_message" "critical" log "KILLED PROCESS: PID=$pid NAME=$name REASON=$reason CPU=${cpu}% MEM=${mem}% (${mem_mb}MB)" return 0 fi fi return 1 } # Monitor CPU usage monitor_cpu() { local cpu_usage=$(top -bn1 | grep "Cpu(s)" | awk '{print $2}' | sed 's/%us,//' | cut -d. -f1) if [[ "$cpu_usage" -gt "$CPU_THRESHOLD" ]]; then log "HIGH CPU USAGE: ${cpu_usage}%" # Find top CPU consuming processes ps aux --sort=-%cpu | head -6 | tail -5 | while read line; do local pid=$(echo "$line" | awk '{print $2}') local cpu_percent=$(echo "$line" | awk '{print $3}') if (( $(echo "$cpu_percent > 20" | bc -l) )); then kill_process_with_notification "$pid" "High CPU Usage" "System CPU: ${cpu_usage}%, Process CPU: ${cpu_percent}%" fi done fi } # Monitor memory usage monitor_memory() { local mem_info=$(free | grep '^Mem:') local total=$(echo "$mem_info" | awk '{print $2}') local used=$(echo "$mem_info" | awk '{print $3}') local mem_percent=$(( (used * 100) / total )) if [[ "$mem_percent" -gt "$MEMORY_THRESHOLD" ]]; then log "HIGH MEMORY USAGE: ${mem_percent}%" # Find top memory consuming processes ps aux --sort=-%mem | head -6 | tail -5 | while read line; do local pid=$(echo "$line" | awk '{print $2}') local mem_percent_proc=$(echo "$line" | awk '{print $4}') if (( $(echo "$mem_percent_proc > 15" | bc -l) )); then kill_process_with_notification "$pid" "High Memory Usage" "System RAM: ${mem_percent}%, Process RAM: ${mem_percent_proc}%" fi done fi } # Monitor temperature monitor_temperature() { if command -v sensors >/dev/null 2>&1; then local max_temp=0 local cpu_temps=$(sensors 2>/dev/null | grep -E "(Core|Package|CPU)" | grep -o '+[0-9]*\.[0-9]*°C' | sed 's/+//;s/°C//' || echo "0") for temp in $cpu_temps; do local temp_int=${temp%.*} if [[ "$temp_int" -gt "$max_temp" ]]; then max_temp="$temp_int" fi done if [[ "$max_temp" -gt "$TEMP_THRESHOLD" ]]; then log "HIGH TEMPERATURE: ${max_temp}°C" send_notification "🌡️ High Temperature Warning" \ "Temperature: ${max_temp}°C (Threshold: ${TEMP_THRESHOLD}°C) Killing high CPU processes to reduce heat" "critical" # Kill top CPU processes ps aux --sort=-%cpu | head -4 | tail -3 | while read line; do local pid=$(echo "$line" | awk '{print $2}') local cpu_percent=$(echo "$line" | awk '{print $3}') if (( $(echo "$cpu_percent > 10" | bc -l) )); then kill_process_with_notification "$pid" "Temperature Protection" "CPU Temperature: ${max_temp}°C" fi done fi fi } # Monitor disk usage monitor_disk() { local disk_usage=$(df / | tail -1 | awk '{print $5}' | sed 's/%//') if [[ "$disk_usage" -gt "$DISK_THRESHOLD" ]]; then log "HIGH DISK USAGE: ${disk_usage}%" send_notification "💾 Low Disk Space Warning" \ "Disk usage: ${disk_usage}% (Threshold: ${DISK_THRESHOLD}%) Cleaning temporary files..." "critical" # Clean temporary files find /tmp -type f -atime +1 -delete 2>/dev/null || true find /var/tmp -type f -atime +1 -delete 2>/dev/null || true # Clean package cache if command -v paccache >/dev/null 2>&1; then paccache -r -k3 2>/dev/null || true fi fi } # Load configuration if [[ -f "$CONFIG_FILE" ]]; then source "$CONFIG_FILE" log "Configuration loaded from $CONFIG_FILE" fi # Write PID file echo $$ > "$PID_FILE" # Main monitoring loop log "PC Monitor started - Protecting your system from crashes and freezes" send_notification "🛡️ PC Monitor Active" \ "System protection enabled Monitoring: CPU, Memory, Temperature, Disk, Processes" "normal" while true; do monitor_cpu monitor_memory monitor_temperature monitor_disk sleep 5 done EOF # Make script executable chmod +x /usr/local/bin/pc-monitor # Update service file to be more permissive print_status "Updating service configuration..." cat > /etc/systemd/system/pc-monitor.service << 'EOF' [Unit] Description=PC Anti-Freeze Monitor - System Crash Prevention Documentation=man:pc-monitor(8) After=multi-user.target graphical-session.target Wants=multi-user.target [Service] Type=simple ExecStart=/usr/local/bin/pc-monitor ExecReload=/bin/kill -HUP $MAINPID KillMode=process Restart=always RestartSec=10 User=root Group=root # Environment for notifications Environment=PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin # Resource limits LimitNOFILE=1024 LimitNPROC=512 [Install] WantedBy=multi-user.target EOF # Reload systemd and start service print_status "Reloading systemd and starting service..." systemctl daemon-reload systemctl start pc-monitor.service # Check if it's working sleep 3 if systemctl is-active --quiet pc-monitor.service; then print_status "✅ PC Monitor is now running successfully!" systemctl status pc-monitor.service --no-pager --lines=5 else print_error "❌ Service still failing. Checking logs..." journalctl -u pc-monitor.service --no-pager -n 10 fi print_status "🛡️ Your system is now protected from crashes and freezes!" echo echo "Useful commands:" echo " • Check status: systemctl status pc-monitor" echo " • View logs: journalctl -u pc-monitor -f" echo " • Stop service: systemctl stop pc-monitor" echo " • Restart service: systemctl restart pc-monitor"