521 lines
17 KiB
Bash
Executable file
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
|