- System protection script with custom enhancements and TUI interface - Browser tab limiting and application-specific monitoring - AI behavior learning and predictive analysis - Terminal-based configuration interface - Multi-distro installation support
337 lines
11 KiB
Bash
Executable File
337 lines
11 KiB
Bash
Executable File
#!/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" |