dotfiles/.config/hypr/scripts/Polkit-Diag.sh
2026-05-13 21:22:17 +02:00

521 lines
17 KiB
Bash
Executable file

#!/usr/bin/env bash
# ==================================================
# KoolDots (2026)
# Project URL: https://github.com/LinuxBeginnings
# License: GNU GPLv3
# SPDX-License-Identifier: GPL-3.0-or-later
# ==================================================
# 💫 https://github.com/LinuxBeginnings 💫 #
# Polkit Diagnostic & Triage Script #
# Default values
OUTFILE="$HOME/Downloads/Polkit-diag.txt"
DRY_RUN=0
INSTALL_OVERRIDE=0
FORCE_OVERRIDE=0
# Systemd override details for hyprpolkitagent
OVERRIDE_DIR="$HOME/.config/systemd/user/hyprpolkitagent.service.d"
OVERRIDE_FILE="$OVERRIDE_DIR/override.conf"
OVERRIDE_CONTENT="[Unit]
After=
After=dbus.service graphical-session.target
PartOf=graphical-session.target
[Install]
WantedBy=graphical-session.target"
print_help() {
cat << EOF
Usage: $(basename "$0") [OPTIONS]
Gather diagnostic information for polkit issues and optionally apply a systemd override.
This script is modular and extensible for different Linux distributions.
Options:
-h, --help Show this help message and exit
-d, --dry-run Run without making changes (output to stdout instead of file)
--install-override Install the systemd override for hyprpolkitagent if not already present
--force-override Overwrite the existing systemd override for hyprpolkitagent
-o, --output FILE Specify custom output file (default: $HOME/Downloads/Polkit-diag.txt)
EOF
}
setup_output() {
if [[ $DRY_RUN -eq 1 ]]; then
echo "================================================="
echo " [Dry Run] Diagnostics will be printed to stdout."
echo "================================================="
exec 3>&1
else
local outdir
outdir=$(dirname "$OUTFILE")
# Check and create directory if it doesn't exist
if [[ ! -d "$outdir" ]]; then
echo "Directory $outdir does not exist. Creating..."
mkdir -p "$outdir"
fi
# Backup existing file
if [[ -f "$OUTFILE" ]]; then
local backup_file="${OUTFILE}.bak.$(date +%Y%m%d%H%M%S)"
echo "Existing output file found. Backing up to: $backup_file"
mv "$OUTFILE" "$backup_file"
fi
echo "Diagnostics will be saved to: $OUTFILE"
exec 3> "$OUTFILE"
fi
}
apply_override() {
if [[ $INSTALL_OVERRIDE -eq 1 ]]; then
local msg="\n=== Systemd Override for hyprpolkitagent ==="
[[ $DRY_RUN -eq 0 ]] && echo -e "$msg" >&3
echo -e "$msg"
local out
if systemctl --user is-enabled hyprpolkitagent.service >/dev/null 2>&1; then
msg="[STATUS] hyprpolkitagent.service is currently enabled."
else
msg="[STATUS] hyprpolkitagent.service is NOT enabled. You may need to enable it."
fi
[[ $DRY_RUN -eq 0 ]] && echo "$msg" >&3
echo "$msg"
if [[ -f "$OVERRIDE_FILE" && $FORCE_OVERRIDE -eq 0 ]]; then
msg="[INFO] Override already exists at $OVERRIDE_FILE."
[[ $DRY_RUN -eq 0 ]] && echo "$msg" >&3; echo "$msg"
msg="[ACTION] Use --force-override to overwrite it."
[[ $DRY_RUN -eq 0 ]] && echo "$msg" >&3; echo "$msg"
else
if [[ -f "$OVERRIDE_FILE" && $FORCE_OVERRIDE -eq 1 ]]; then
msg="[CONFIRM] Force override requested. Overwriting existing override..."
[[ $DRY_RUN -eq 0 ]] && echo "$msg" >&3; echo "$msg"
fi
msg="[ACTION] Installing override to $OVERRIDE_FILE..."
[[ $DRY_RUN -eq 0 ]] && echo "$msg" >&3; echo "$msg"
if [[ $DRY_RUN -eq 0 ]]; then
# Capture dir creation
if out=$(mkdir -p "$OVERRIDE_DIR" 2>&1); then
msg=" [OK] Created/verified directory $OVERRIDE_DIR."
else
msg=" [ERROR] Failed to create directory $OVERRIDE_DIR.\n Details: $out"
fi
echo -e "$msg" >&3; echo -e "$msg"
# Capture file write
if out=$(echo "$OVERRIDE_CONTENT" > "$OVERRIDE_FILE" 2>&1); then
msg=" [OK] Successfully wrote override file."
else
msg=" [ERROR] Failed to write override file.\n Details: $out"
fi
echo -e "$msg" >&3; echo -e "$msg"
# Capture daemon-reload
if out=$(systemctl --user daemon-reload 2>&1); then
msg=" [OK] Systemd daemon reloaded."
else
msg=" [ERROR] Failed to reload systemd daemon.\n Details: $out"
fi
echo -e "$msg" >&3; echo -e "$msg"
# Capture restart
if systemctl --user is-active --quiet hyprpolkitagent.service; then
msg="[ACTION] Restarting hyprpolkitagent.service..."
[[ $DRY_RUN -eq 0 ]] && echo "$msg" >&3; echo "$msg"
if out=$(systemctl --user restart hyprpolkitagent.service 2>&1); then
msg=" [OK] Service restarted successfully."
else
msg=" [ERROR] Failed to restart service.\n Details: $out"
fi
echo -e "$msg" >&3; echo -e "$msg"
else
msg="[INFO] Service is not currently active, skipping restart step."
[[ $DRY_RUN -eq 0 ]] && echo "$msg" >&3; echo "$msg"
fi
else
msg="[Dry Run] Would create $OVERRIDE_FILE and reload systemd daemon."
echo "$msg"
fi
fi
fi
}
gather_general_info() {
echo -e "\n=======================================" >&3
echo -e " General System Information" >&3
echo -e "=======================================" >&3
echo "Date: $(date)" >&3
echo -e "\n--- Kernel ---" >&3
uname -a >&3
echo -e "\n--- OS Release ---" >&3
cat /etc/os-release >&3
echo -e "\n=======================================" >&3
echo -e " Polkit Service Status" >&3
echo -e "=======================================" >&3
echo -e "\n--- System Polkit Service ---" >&3
systemctl status polkit.service --no-pager >&3 2>&1 || true
echo -e "\n--- User Hyprpolkitagent Service ---" >&3
systemctl --user status hyprpolkitagent.service --no-pager >&3 2>&1 || true
echo -e "\n--- Running Polkit Processes ---" >&3
local polkit_procs
polkit_procs=$(ps aux | grep -i '[p]olkit')
if [[ -n "$polkit_procs" ]]; then
echo "$polkit_procs" >&3
# Check for conflicting agents
local kde_agent_running=0
local gnome_agent_running=0
local hypr_agent_running=0
if echo "$polkit_procs" | grep -q "polkit-kde-authentication-agent-1"; then
kde_agent_running=1
fi
if echo "$polkit_procs" | grep -q "polkit-gnome-authentication-agent-1"; then
gnome_agent_running=1
fi
if echo "$polkit_procs" | grep -q "hyprpolkitagent"; then
hypr_agent_running=1
fi
if [[ $hypr_agent_running -eq 1 && ($kde_agent_running -eq 1 || $gnome_agent_running -eq 1) ]]; then
echo -e "\n[!] CONFLICT DETECTED: Multiple polkit agents are running!" >&3
echo " Hyprpolkitagent is running alongside another desktop environment's agent." >&3
echo " Only ONE polkit agent can be registered at a time." >&3
if [[ $kde_agent_running -eq 1 ]]; then
echo " -> Found KDE polkit agent. You may need to disable it in Hyprland by adding 'NotShowIn=Hyprland;' to its autostart .desktop file." >&3
fi
if [[ $gnome_agent_running -eq 1 ]]; then
echo " -> Found GNOME polkit agent. You may need to disable it in Hyprland." >&3
fi
elif [[ $kde_agent_running -eq 1 && $hypr_agent_running -eq 0 ]]; then
echo -e "\n[!] WARNING: KDE polkit agent is running instead of hyprpolkitagent." >&3
echo " This can cause 'authentication agent already exists' errors if hyprpolkitagent tries to start later." >&3
fi
else
echo "No polkit processes found running." >&3
fi
echo -e "\n=======================================" >&3
echo -e " Recent Logs" >&3
echo -e "=======================================" >&3
echo -e "\n--- Journalctl (polkit.service) [Last 50 entries, warnings/errors] ---" >&3
journalctl -u polkit.service -n 50 --no-pager -p 4 >&3 2>&1 || echo "Could not fetch system polkit logs." >&3
echo -e "\n--- Journalctl (hyprpolkitagent.service) [Last 50 entries] ---" >&3
journalctl --user -u hyprpolkitagent.service -n 50 --no-pager >&3 2>&1 || echo "Could not fetch user hyprpolkitagent logs." >&3
}
# --- Modular Package Checking System ---
check_packages() {
local check_cmd="$1"
local install_msg="$2"
shift 2
local pkgs=("$@")
local missing_pkgs=()
for pkg in "${pkgs[@]}"; do
local out
if out=$(eval "$check_cmd \"$pkg\"" 2>/dev/null); then
# Print the first line of output as the installed info
echo "[INSTALLED] $(echo "$out" | head -n 1)" >&3
else
echo "[MISSING] $pkg" >&3
missing_pkgs+=("$pkg")
fi
done
if [[ ${#missing_pkgs[@]} -gt 0 ]]; then
echo -e "\nWARNING: The following packages are missing:" >&3
for mpkg in "${missing_pkgs[@]}"; do
echo " - $mpkg" >&3
done
echo "$install_msg ${missing_pkgs[*]}" >&3
return 1
fi
return 0
}
check_source_binaries() {
local bin_dir="$1"
shift
local bins=("$@")
local found_any=0
echo -e "\n--- Source Builds (${bin_dir}) ---" >&3
for bin in "${bins[@]}"; do
if [[ -x "${bin_dir}/${bin}" ]]; then
echo "[SOURCE] ${bin_dir}/${bin}" >&3
found_any=1
else
echo "[MISSING] ${bin_dir}/${bin}" >&3
fi
done
return $found_any
}
gather_arch_info() {
echo -e "\n=======================================" >&3
echo -e " Package Info (Arch Linux)" >&3
echo -e "=======================================" >&3
# Essential packages required for polkit & related UI
local pkgs=(
"qt5-declarative"
"qt5-quickcontrols2"
"qt6-declarative"
"hyprpolkitagent"
"polkit"
)
local aur_pkgs=(
"xfce-polkit"
)
local missing_any=0
echo -e "\n--- Official Repositories ---" >&3
check_packages "pacman -Q" "Install official packages by running: sudo pacman -S" "${pkgs[@]}" || missing_any=1
echo -e "\n--- AUR ---" >&3
check_packages "pacman -Q" "Install AUR packages by running: yay -S" "${aur_pkgs[@]}" || missing_any=1
if [[ $missing_any -eq 0 ]]; then
echo -e "\nSUCCESS: All expected packages are installed." >&3
fi
}
gather_ubuntu_info() {
echo -e "\n=======================================" >&3
echo -e " Package Info (Ubuntu/PPA)" >&3
echo -e "=======================================" >&3
# Essential packages required for polkit & related UI
local pkgs=(
"qml-module-qtqml"
"qml-module-qtquick2"
"qml-module-qtquick-controls"
"qml-module-qtquick-controls2"
"qml-module-qtquick-layouts"
"qml6-module-qtqml"
"qml6-module-qtquick"
"qml6-module-qtquick-controls"
"hyprpolkitagent"
"polkit"
)
local extra_pkgs=(
"xfce-polkit"
"polkit-kde-agent-1"
"mate-polkit"
)
local missing_any=0
echo -e "\n--- Official Repositories / PPA ---" >&3
check_packages "dpkg -s" "Install packages by running: sudo apt install" "${pkgs[@]}" || missing_any=1
echo -e "\n--- Extra/Alternative ---" >&3
check_packages "dpkg -s" "Install extra packages by running: sudo apt install" "${extra_pkgs[@]}" || missing_any=1
echo "[INFO] lxqt-polkit (optional) — large dependency set." >&3
if [[ $missing_any -eq 0 ]]; then
echo -e "\nSUCCESS: All expected packages are installed." >&3
fi
}
gather_debian_info() {
echo -e "\n=======================================" >&3
echo -e " Package Info (Debian/Ubuntu)" >&3
echo -e "=======================================" >&3
local source_bins=(
"hyprpolkitagent"
)
local source_found=0
if check_source_binaries "/usr/local/bin" "${source_bins[@]}"; then
source_found=1
fi
# Essential packages required for polkit & related UI
local pkgs=(
"qml-module-qtqml"
"qml-module-qtquick2"
"qml-module-qtquick-controls"
"qml-module-qtquick-controls2"
"qml-module-qtquick-layouts"
"qml6-module-qtqml"
"qml6-module-qtquick"
"qml6-module-qtquick-controls"
"polkit"
)
local extra_pkgs=(
"xfce4-polkit"
"lxqt-policykit"
"polkit-kde-agent-1"
"mate-polkit"
)
local missing_any=0
echo -e "\n--- Official Repositories ---" >&3
if [[ $source_found -eq 0 ]]; then
pkgs+=("hyprpolkitagent")
else
echo "[INFO] hyprpolkitagent found in /usr/local/bin (source build). Skipping dpkg check for it." >&3
fi
check_packages "dpkg -s" "Install packages by running: sudo apt install" "${pkgs[@]}" || missing_any=1
echo -e "\n--- Extra/Alternative ---" >&3
check_packages "dpkg -s" "Install extra packages by running: sudo apt install" "${extra_pkgs[@]}" || missing_any=1
if [[ $missing_any -eq 0 ]]; then
echo -e "\nSUCCESS: All expected packages are installed." >&3
fi
}
gather_fedora_info() {
echo -e "\n=======================================" >&3
echo -e " Package Info (Fedora)" >&3
echo -e "=======================================" >&3
# Essential packages required for polkit & related UI
local pkgs=(
"qt5-qtdeclarative"
"qt5-qtquickcontrols2"
"qt6-qtdeclarative"
"hyprpolkitagent"
"polkit"
)
local extra_pkgs=(
"xfce-polkit"
)
local missing_any=0
echo -e "\n--- Official Repositories ---" >&3
check_packages "rpm -q" "Install packages by running: sudo dnf install" "${pkgs[@]}" || missing_any=1
echo -e "\n--- Extra/Alternative ---" >&3
check_packages "rpm -q" "Install extra packages by running: sudo dnf install" "${extra_pkgs[@]}" || missing_any=1
if [[ $missing_any -eq 0 ]]; then
echo -e "\nSUCCESS: All expected packages are installed." >&3
fi
}
detect_os() {
if [ -f /etc/os-release ]; then
. /etc/os-release
OS=$ID
else
OS="unknown"
fi
}
# ----------------------------------------------------------------------------
# Main Execution
# ----------------------------------------------------------------------------
# Parse arguments
while [[ "$#" -gt 0 ]]; do
case "$1" in
-h|--help)
print_help
exit 0
;;
-d|--dry-run)
DRY_RUN=1
;;
--install-override)
INSTALL_OVERRIDE=1
;;
--force-override)
FORCE_OVERRIDE=1
INSTALL_OVERRIDE=1
;;
-o|--output)
if [[ -n "$2" && "$2" != -* ]]; then
OUTFILE="$2"
shift
else
echo "Error: Argument for $1 is missing" >&2
exit 1
fi
;;
*)
echo "Unknown option: $1" >&2
print_help
exit 1
;;
esac
shift
done
setup_output
echo "Starting Polkit Diagnostic Script..." >&3
# Optional apply override logic
if [[ $INSTALL_OVERRIDE -eq 1 ]]; then
apply_override
fi
# Gather general info
gather_general_info
# Gather OS-specific package info
detect_os
case "$OS" in
arch|artix|manjaro|endeavouros|cachyos)
gather_arch_info
;;
debian)
gather_debian_info
;;
ubuntu|pop|linuxmint)
gather_ubuntu_info
;;
fedora)
gather_fedora_info
;;
opensuse*)
echo -e "\n=======================================" >&3
echo -e " Package Info ($OS)" >&3
echo -e "=======================================" >&3
echo "OpenSUSE package check is pending implementation." >&3
;;
nixos)
echo -e "\n=======================================" >&3
echo -e " Package Info ($OS)" >&3
echo -e "=======================================" >&3
echo "NixOS configuration check is pending implementation." >&3
;;
*)
echo -e "\n=======================================" >&3
echo -e " Package Info" >&3
echo -e "=======================================" >&3
echo "Unknown or unsupported OS: $OS. Skipping package checks." >&3
;;
esac
echo -e "\nDiagnostics completed at $(date)" >&3
if [[ $DRY_RUN -eq 0 ]]; then
echo "================================================="
echo " Diagnostic gathering complete!"
echo " Please review the output file: $OUTFILE"
echo "================================================="
fi