foxygit / dotfiles Log in
commits tags

/bin/status · 5.43 KB

raw
#!/bin/bash
# status
# Snabb översikt över skrivbordet: WM-stacken, bakgrundsdaemons, systemd-
# tjänster, nätverk, bluetooth, ljud, batteri och skärm/lock-läge. Rör inget,
# bara läser av och skriver ut.

if [ -t 1 ] && command -v tput >/dev/null 2>&1 && [ "$(tput colors 2>/dev/null)" -ge 8 ]; then
    C_HEAD=$(tput bold)$(tput setaf 3)   # gul
    C_OK=$(tput setaf 2)                 # grön
    C_BAD=$(tput setaf 1)                # röd
    C_DIM=$(tput dim)
    C_RESET=$(tput sgr0)
else
    C_HEAD=""; C_OK=""; C_BAD=""; C_DIM=""; C_RESET=""
fi

header() { printf "\n%s== %s ==%s\n" "$C_HEAD" "$1" "$C_RESET"; }
ok()      { printf "  %s✔%s %s\n" "$C_OK" "$C_RESET" "$1"; }
bad()     { printf "  %s✘%s %s\n" "$C_BAD" "$C_RESET" "$1"; }
line()    { printf "  %s\n" "$1"; }

proc_status() {
    local label="$1" pattern="$2"
    local pid
    # pgrep -x trunkerar mot /proc/[pid]/comm (max 15 tecken), vilket ger
    # falska negativ för längre namn som "lid-display-watch". Matchar
    # istället mot hela kommandoraden med en ord-gräns runt namnet.
    pid=$(pgrep -f "(^|/)${pattern}([[:space:]]|\$)" | head -1)
    if [ -n "$pid" ]; then
        ok "$label (pid $pid)"
    else
        bad "$label - körs inte"
    fi
}

strip_ansi() { sed -e 's/\x1b\[[0-9;]*m//g'; }

service_status() {
    local scope="$1" name="$2"
    local -a scope_args=()
    [ -n "$scope" ] && scope_args=("$scope")
    if systemctl "${scope_args[@]}" is-active --quiet "$name" 2>/dev/null; then
        ok "$name"
    else
        bad "$name - $(systemctl "${scope_args[@]}" is-active "$name" 2>/dev/null)"
    fi
}

header "System"
line "$(hostname) - $(uptime -p 2>/dev/null | sed 's/^up //') - load: $(cut -d' ' -f1-3 /proc/loadavg)"
line "kernel: $(uname -r)"

header "Skrivbord"
proc_status "Xorg"            Xorg
proc_status "sxwm"            sxwm
proc_status "sxbar"           sxbar
proc_status "screensaverd"    screensaverd
proc_status "lid-display-watch" lid-display-watch

header "Tjänster"
service_status "" bluetooth
service_status "--user" pipewire
service_status "--user" pipewire-pulse
service_status "--user" wireplumber

header "Nätverk"
while read -r ifc state addr _; do
    [ "$ifc" = "lo" ] && continue
    if [ "$state" = "UP" ]; then
        ok "$ifc: $addr"
    else
        bad "$ifc: nere"
    fi
done < <(ip -br addr show 2>/dev/null)
if command -v iwctl >/dev/null 2>&1; then
    while read -r wifi_dev; do
        [ -n "$wifi_dev" ] || continue
        ssid=$(iwctl station "$wifi_dev" show 2>/dev/null | strip_ansi | sed -n 's/^[[:space:]]*Connected network[[:space:]]\+//p' | sed 's/[[:space:]]*$//')
        [ -n "$ssid" ] && line "wifi ($wifi_dev): ansluten till \"$ssid\""
    done < <(iwctl station list 2>/dev/null | strip_ansi | awk '/connected/{print $1}')
fi

header "Bluetooth"
if command -v bluetoothctl >/dev/null 2>&1; then
    powered=$(bluetoothctl show 2>/dev/null | awk -F': ' '/^\tPowered:/{print $2}')
    if [ "$powered" = "yes" ]; then
        ok "adapter på"
    else
        bad "adapter av"
    fi
    connected=$(bluetoothctl devices Connected 2>/dev/null)
    if [ -n "$connected" ]; then
        while read -r _ mac name; do
            ok "ansluten: $name ($mac)"
        done <<< "$connected"
    else
        line "${C_DIM}inga anslutna enheter${C_RESET}"
    fi
else
    bad "bluetoothctl saknas"
fi

header "Ljud"
if command -v wpctl >/dev/null 2>&1; then
    sink_vol=$(wpctl get-volume @DEFAULT_AUDIO_SINK@ 2>/dev/null)
    if [ -n "$sink_vol" ]; then
        if echo "$sink_vol" | grep -q MUTED; then
            bad "output: $sink_vol"
        else
            ok "output: $sink_vol"
        fi
    else
        bad "ingen default-output"
    fi
else
    bad "wpctl saknas"
fi

header "Batteri"
for supply in /sys/class/power_supply/*/; do
    name=$(basename "$supply")
    type=$(cat "${supply}type" 2>/dev/null)
    case "$type" in
        Battery)
            cap=$(cat "${supply}capacity" 2>/dev/null)
            st=$(cat "${supply}status" 2>/dev/null)
            if [ "$st" = "Charging" ] || { [ -n "$cap" ] && [ "$cap" -gt 20 ] 2>/dev/null; }; then
                ok "$name: $cap% ($st)"
            else
                bad "$name: $cap% ($st)"
            fi
            ;;
        Mains|USB)
            online=$(cat "${supply}online" 2>/dev/null)
            if [ "$online" = "1" ]; then
                line "$name: ansluten"
            else
                line "$name: inte ansluten"
            fi
            ;;
    esac
done

header "Skärm / lock"
dpms=$(xset q 2>/dev/null | awk '/Monitor is/{print $NF}')
[ -n "$dpms" ] && line "DPMS: $dpms"
lid=$(busctl get-property org.freedesktop.login1 /org/freedesktop/login1 \
    org.freedesktop.login1.Manager LidClosed 2>/dev/null | awk '{print $2}')
case "$lid" in
    true)  line "lock: stängt" ;;
    false) line "lock: öppet" ;;
esac
handle=$(busctl get-property org.freedesktop.login1 /org/freedesktop/login1 \
    org.freedesktop.login1.Manager HandleLidSwitch 2>/dev/null | cut -d'"' -f2)
[ -n "$handle" ] && line "HandleLidSwitch: $handle"
if command -v lidsuspend >/dev/null 2>&1; then
    line "lidsuspend: $(lidsuspend status 2>/dev/null)"
fi
pause_file="${XDG_RUNTIME_DIR:-/tmp}/screensaver-paused"
[ -e "$pause_file" ] && line "screensaver: pausad"

if command -v playerctl >/dev/null 2>&1; then
    pstatus=$(playerctl status 2>/dev/null)
    if [ "$pstatus" = "Playing" ]; then
        header "Media"
        ok "$(playerctl metadata --format '{{artist}} - {{title}}' 2>/dev/null)"
    fi
fi

echo