mirror of
https://github.com/kuhyx/testsAndMisc.git
synced 2026-07-04 16:43:05 +02:00
Optimize linux polling and i3blocks scripts
This commit is contained in:
parent
90d8461f1d
commit
c7107e265c
@ -1,48 +1,36 @@
|
||||
#!/bin/bash
|
||||
# ActivityWatch status script for i3blocks
|
||||
# Shows ActivityWatch installation and running status
|
||||
# ActivityWatch status script for i3blocks.
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
# Check if ActivityWatch is installed
|
||||
check_installed() {
|
||||
# Check if activitywatch-bin package is installed
|
||||
if pacman -Qi activitywatch-bin &> /dev/null; then
|
||||
return 0
|
||||
fi
|
||||
|
||||
# Check if aw-qt binary exists
|
||||
if command -v aw-qt &> /dev/null; then
|
||||
return 0
|
||||
fi
|
||||
|
||||
return 1
|
||||
command -v aw-qt > /dev/null 2>&1 || command -v aw-server > /dev/null 2>&1
|
||||
}
|
||||
|
||||
# Check if ActivityWatch is running
|
||||
check_running() {
|
||||
# Check for aw-qt process
|
||||
if pgrep -f "aw-qt" > /dev/null 2>&1; then
|
||||
return 0
|
||||
fi
|
||||
|
||||
# Check for aw-server process
|
||||
if pgrep -f "aw-server" > /dev/null 2>&1; then
|
||||
return 0
|
||||
fi
|
||||
|
||||
local proc_file proc_name
|
||||
for proc_file in /proc/[0-9]*/comm; do
|
||||
[[ -r $proc_file ]] || continue
|
||||
read -r proc_name < "$proc_file" || continue
|
||||
case $proc_name in
|
||||
aw-qt | aw-server)
|
||||
return 0
|
||||
;;
|
||||
esac
|
||||
done
|
||||
return 1
|
||||
}
|
||||
|
||||
# Main logic
|
||||
if ! check_installed; then
|
||||
echo "AW uninstalled"
|
||||
echo
|
||||
echo "#FF0000" # Red
|
||||
echo "#FF0000"
|
||||
elif check_running; then
|
||||
echo "AW on"
|
||||
echo
|
||||
echo "#00FF00" # Green
|
||||
echo "#00FF00"
|
||||
else
|
||||
echo "AW off"
|
||||
echo
|
||||
echo "#FF0000" # Red
|
||||
echo "#FF0000"
|
||||
fi
|
||||
|
||||
@ -1,14 +1,27 @@
|
||||
#!/bin/bash
|
||||
# i3blocks bluetooth indicator.
|
||||
|
||||
# Get Bluetooth device info
|
||||
bluetooth_info=$(bluetoothctl info)
|
||||
set -euo pipefail
|
||||
|
||||
# Check if Bluetooth is connected
|
||||
if echo "$bluetooth_info" | grep -q "Connected: yes"; then
|
||||
device=$(echo "$bluetooth_info" | grep "Alias" | cut -d ' ' -f2-)
|
||||
echo " $device" # is the Bluetooth icon
|
||||
bluetooth_info=$(bluetoothctl info 2> /dev/null) || bluetooth_info=''
|
||||
|
||||
connected='no'
|
||||
device=''
|
||||
while IFS= read -r line; do
|
||||
case $line in
|
||||
*'Connected: yes')
|
||||
connected='yes'
|
||||
;;
|
||||
*'Alias: '*)
|
||||
device=${line#*Alias: }
|
||||
;;
|
||||
esac
|
||||
done <<< "$bluetooth_info"
|
||||
|
||||
if [[ $connected == yes && -n $device ]]; then
|
||||
echo " $device"
|
||||
echo
|
||||
echo "#50FA7B" # Green for connected
|
||||
echo "#50FA7B"
|
||||
else
|
||||
echo " Disconnected"
|
||||
fi
|
||||
|
||||
@ -17,13 +17,13 @@ markup=pango
|
||||
|
||||
|
||||
[memory]
|
||||
command=free -h | awk '/^Mem:/ {print " " $3 "/" $2}' # for RAM
|
||||
command=~/.config/i3blocks/memory.sh
|
||||
interval=5
|
||||
color=#50FA7B
|
||||
|
||||
|
||||
[disk]
|
||||
command=df -h / | awk '/\// {print " " $3 "/" $2}' # for disk
|
||||
command=~/.config/i3blocks/disk.sh
|
||||
interval=60
|
||||
color=#50FA7B
|
||||
|
||||
@ -50,7 +50,7 @@ markup=pango
|
||||
|
||||
|
||||
[ethernet]
|
||||
command=ip -o -4 addr show | grep -E 'enp6s0|eth0' | awk '{print " "$4}' || echo " down" # for Ethernet
|
||||
command=~/.config/i3blocks/ethernet.sh
|
||||
interval=10
|
||||
color=#FFFFFF
|
||||
|
||||
@ -91,6 +91,6 @@ markup=pango
|
||||
|
||||
|
||||
[time]
|
||||
command=echo " $(date '+%Y-%m-%d %H:%M')" # for time (Font Awesome icon)
|
||||
interval=1
|
||||
command=~/.config/i3blocks/time.sh
|
||||
interval=persist
|
||||
color=#50FA7B
|
||||
|
||||
14
linux_configuration/i3-configuration/i3blocks/disk.sh
Executable file
14
linux_configuration/i3-configuration/i3blocks/disk.sh
Executable file
@ -0,0 +1,14 @@
|
||||
#!/bin/bash
|
||||
# i3blocks disk usage indicator with a single df helper.
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
{
|
||||
read -r _
|
||||
read -r _ size used _
|
||||
} < <(df -h / 2> /dev/null) || {
|
||||
echo " N/A"
|
||||
exit 0
|
||||
}
|
||||
|
||||
echo " ${used}/${size}"
|
||||
35
linux_configuration/i3-configuration/i3blocks/ethernet.sh
Executable file
35
linux_configuration/i3-configuration/i3blocks/ethernet.sh
Executable file
@ -0,0 +1,35 @@
|
||||
#!/bin/bash
|
||||
# i3blocks ethernet indicator with one external helper at most.
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
find_ethernet_interface() {
|
||||
local iface_path iface
|
||||
for iface_path in /sys/class/net/*; do
|
||||
iface=${iface_path##*/}
|
||||
[[ $iface == lo ]] && continue
|
||||
[[ -d ${iface_path}/wireless ]] && continue
|
||||
[[ -r ${iface_path}/operstate ]] || continue
|
||||
printf '%s\n' "$iface"
|
||||
return 0
|
||||
done
|
||||
return 1
|
||||
}
|
||||
|
||||
iface=$(find_ethernet_interface) || {
|
||||
printf ' down\n'
|
||||
exit 0
|
||||
}
|
||||
|
||||
read -r state < "/sys/class/net/${iface}/operstate"
|
||||
if [[ $state != up ]]; then
|
||||
printf ' down\n'
|
||||
exit 0
|
||||
fi
|
||||
|
||||
addr_output=$(ip -o -4 addr show dev "$iface" scope global 2> /dev/null) || addr_output=''
|
||||
if [[ $addr_output =~ ([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+/[0-9]+) ]]; then
|
||||
printf ' %s\n' "${BASH_REMATCH[1]}"
|
||||
else
|
||||
printf ' down\n'
|
||||
fi
|
||||
31
linux_configuration/i3-configuration/i3blocks/memory.sh
Executable file
31
linux_configuration/i3-configuration/i3blocks/memory.sh
Executable file
@ -0,0 +1,31 @@
|
||||
#!/bin/bash
|
||||
# i3blocks memory indicator, zero-fork per invocation via /proc/meminfo.
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
format_mib() {
|
||||
local mib=$1
|
||||
if ((mib >= 1024)); then
|
||||
printf '%d.%dGiB' "$((mib / 1024))" "$((((mib % 1024) * 10) / 1024))"
|
||||
else
|
||||
printf '%dMiB' "$mib"
|
||||
fi
|
||||
}
|
||||
|
||||
total_kib=0
|
||||
available_kib=0
|
||||
while IFS=' :' read -r key value _; do
|
||||
case $key in
|
||||
MemTotal)
|
||||
total_kib=$value
|
||||
;;
|
||||
MemAvailable)
|
||||
available_kib=$value
|
||||
;;
|
||||
esac
|
||||
done < /proc/meminfo
|
||||
|
||||
used_mib=$(((total_kib - available_kib) / 1024))
|
||||
total_mib=$((total_kib / 1024))
|
||||
|
||||
printf ' %s/%s\n' "$(format_mib "$used_mib")" "$(format_mib "$total_mib")"
|
||||
@ -1,72 +1,71 @@
|
||||
#!/bin/bash
|
||||
# PC Startup Monitor status script for i3blocks
|
||||
# Shows compact startup compliance status in the status bar
|
||||
# PC Startup Monitor status script for i3blocks.
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
get_now_epoch() {
|
||||
if [[ -n ${NOW_EPOCH:-} ]]; then
|
||||
printf '%s\n' "$NOW_EPOCH"
|
||||
else
|
||||
printf '%(%s)T\n' -1
|
||||
fi
|
||||
}
|
||||
|
||||
get_uptime_seconds() {
|
||||
local uptime_line
|
||||
if [[ -n ${UPTIME_SECONDS:-} ]]; then
|
||||
printf '%s\n' "$UPTIME_SECONDS"
|
||||
return 0
|
||||
fi
|
||||
|
||||
read -r uptime_line _ < /proc/uptime || uptime_line='0'
|
||||
printf '%s\n' "${uptime_line%%.*}"
|
||||
}
|
||||
|
||||
# Function to check if today is a monitored day
|
||||
is_monitored_day() {
|
||||
local day_of_week
|
||||
day_of_week=$(date +%u)
|
||||
if [[ $day_of_week == "1" ]] || [[ $day_of_week == "5" ]] || [[ $day_of_week == "6" ]] || [[ $day_of_week == "7" ]]; then
|
||||
return 0
|
||||
else
|
||||
return 1
|
||||
fi
|
||||
local epoch=$1 day_of_week
|
||||
printf -v day_of_week '%(%u)T' "$epoch"
|
||||
case $day_of_week in
|
||||
1 | 5 | 6 | 7)
|
||||
return 0
|
||||
;;
|
||||
*)
|
||||
return 1
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
# Function to check if current time is in window
|
||||
is_current_time_in_window() {
|
||||
local current_hour current_hour_num
|
||||
current_hour=$(date +%H)
|
||||
current_hour_num=$((10#$current_hour))
|
||||
if [[ $current_hour_num -ge 5 ]] && [[ $current_hour_num -lt 8 ]]; then
|
||||
return 0
|
||||
else
|
||||
return 1
|
||||
fi
|
||||
hour_in_window() {
|
||||
local epoch=$1 hour
|
||||
printf -v hour '%(%H)T' "$epoch"
|
||||
((10#$hour >= 5 && 10#$hour < 8))
|
||||
}
|
||||
|
||||
# Function to check if PC was booted in window today
|
||||
was_booted_in_window_today() {
|
||||
local today uptime_seconds boot_time boot_date
|
||||
today=$(date +%Y-%m-%d)
|
||||
uptime_seconds=$(awk '{print int($1)}' /proc/uptime 2> /dev/null || echo "0")
|
||||
boot_time=$(date -d "@$(($(date +%s) - uptime_seconds))" +"%Y-%m-%d %H:%M:%S")
|
||||
boot_date=$(echo "$boot_time" | cut -d' ' -f1)
|
||||
|
||||
if [[ $boot_date != "$today" ]]; then
|
||||
return 1
|
||||
fi
|
||||
|
||||
local boot_hour boot_hour_num
|
||||
boot_hour=$(echo "$boot_time" | cut -d' ' -f2 | cut -d':' -f1)
|
||||
boot_hour_num=$((10#$boot_hour))
|
||||
|
||||
if [[ $boot_hour_num -ge 5 ]] && [[ $boot_hour_num -lt 8 ]]; then
|
||||
return 0
|
||||
else
|
||||
return 1
|
||||
fi
|
||||
local now_epoch=$1 boot_epoch now_day boot_day
|
||||
boot_epoch=$((now_epoch - $(get_uptime_seconds)))
|
||||
printf -v now_day '%(%Y-%m-%d)T' "$now_epoch"
|
||||
printf -v boot_day '%(%Y-%m-%d)T' "$boot_epoch"
|
||||
[[ $boot_day == "$now_day" ]] || return 1
|
||||
hour_in_window "$boot_epoch"
|
||||
}
|
||||
|
||||
# Main logic
|
||||
if ! is_monitored_day; then
|
||||
# Not a monitored day
|
||||
now_epoch=$(get_now_epoch)
|
||||
|
||||
if ! is_monitored_day "$now_epoch"; then
|
||||
echo "PC:skip"
|
||||
echo
|
||||
echo "#888888" # Gray
|
||||
elif is_current_time_in_window; then
|
||||
# Currently in the window - all good
|
||||
echo "#888888"
|
||||
elif hour_in_window "$now_epoch"; then
|
||||
echo "PC:live"
|
||||
echo
|
||||
echo "#00FF00" # Green
|
||||
elif was_booted_in_window_today; then
|
||||
# Was booted in window today - compliant
|
||||
echo "#00FF00"
|
||||
elif was_booted_in_window_today "$now_epoch"; then
|
||||
echo "PC:ok"
|
||||
echo
|
||||
echo "#00FF00" # Green
|
||||
echo "#00FF00"
|
||||
else
|
||||
# Was NOT booted in window today - non-compliant
|
||||
echo "PC:warn"
|
||||
echo
|
||||
echo "#FF0000" # Red
|
||||
echo "#FF0000"
|
||||
fi
|
||||
|
||||
@ -1,9 +1,9 @@
|
||||
#!/bin/bash
|
||||
# Shutdown countdown status script for i3blocks
|
||||
# Shows time remaining until the next shutdown window
|
||||
# Reads shutdown times from shared config file written by setup_midnight_shutdown.sh
|
||||
# Shutdown countdown status script for i3blocks.
|
||||
|
||||
SHUTDOWN_CONFIG="/etc/shutdown-schedule.conf"
|
||||
set -euo pipefail
|
||||
|
||||
SHUTDOWN_CONFIG=${SHUTDOWN_CONFIG:-/etc/shutdown-schedule.conf}
|
||||
|
||||
# Function to show error state in i3blocks and exit
|
||||
show_error() {
|
||||
@ -14,87 +14,95 @@ show_error() {
|
||||
exit 0
|
||||
}
|
||||
|
||||
# Validate and load config file
|
||||
if [[ ! -f $SHUTDOWN_CONFIG ]]; then
|
||||
show_error "NO CONFIG"
|
||||
fi
|
||||
|
||||
# Source the config file to get MON_WED_HOUR and THU_SUN_HOUR
|
||||
# shellcheck source=/dev/null
|
||||
if ! source "$SHUTDOWN_CONFIG" 2> /dev/null; then
|
||||
show_error "BAD CONFIG"
|
||||
fi
|
||||
MON_WED_HOUR=''
|
||||
THU_SUN_HOUR=''
|
||||
morning_end_hour='5'
|
||||
while IFS='=' read -r key value; do
|
||||
value=${value%%[[:space:]]*}
|
||||
case $key in
|
||||
MON_WED_HOUR)
|
||||
MON_WED_HOUR=$value
|
||||
;;
|
||||
THU_SUN_HOUR)
|
||||
THU_SUN_HOUR=$value
|
||||
;;
|
||||
MORNING_END_HOUR)
|
||||
morning_end_hour=$value
|
||||
;;
|
||||
esac
|
||||
done < "$SHUTDOWN_CONFIG"
|
||||
|
||||
# Validate that required variables are set
|
||||
if [[ -z ${MON_WED_HOUR:-} ]] || [[ -z ${THU_SUN_HOUR:-} ]]; then
|
||||
if [[ -z $MON_WED_HOUR ]] || [[ -z $THU_SUN_HOUR ]]; then
|
||||
show_error "MISSING VARS"
|
||||
fi
|
||||
|
||||
# Validate that values are numbers
|
||||
if ! [[ $MON_WED_HOUR =~ ^[0-9]+$ ]] || ! [[ $THU_SUN_HOUR =~ ^[0-9]+$ ]]; then
|
||||
show_error "INVALID HOURS"
|
||||
fi
|
||||
|
||||
# Get current time info
|
||||
current_hour=$(date +%H)
|
||||
current_minute=$(date +%M)
|
||||
current_time_minutes=$((10#$current_hour * 60 + 10#$current_minute))
|
||||
day_of_week=$(date +%u) # 1=Monday, 7=Sunday
|
||||
if ! [[ $morning_end_hour =~ ^[0-9]+$ ]]; then
|
||||
show_error "INVALID HOURS"
|
||||
fi
|
||||
|
||||
get_now_epoch() {
|
||||
if [[ -n ${NOW_EPOCH:-} ]]; then
|
||||
printf '%s\n' "$NOW_EPOCH"
|
||||
else
|
||||
printf '%(%s)T\n' -1
|
||||
fi
|
||||
}
|
||||
|
||||
now_epoch=$(get_now_epoch)
|
||||
printf -v current_hour '%(%H)T' "$now_epoch"
|
||||
printf -v current_minute '%(%M)T' "$now_epoch"
|
||||
printf -v day_of_week '%(%u)T' "$now_epoch"
|
||||
|
||||
current_time_minutes=$((10#$current_hour * 60 + 10#$current_minute))
|
||||
morning_end_minutes=$((10#$morning_end_hour * 60))
|
||||
|
||||
# Determine shutdown hour based on day of week
|
||||
if [[ $day_of_week -ge 1 ]] && [[ $day_of_week -le 3 ]]; then
|
||||
# Monday-Wednesday
|
||||
shutdown_hour=$MON_WED_HOUR
|
||||
else
|
||||
# Thursday-Sunday
|
||||
shutdown_hour=$THU_SUN_HOUR
|
||||
fi
|
||||
|
||||
shutdown_time_minutes=$((shutdown_hour * 60))
|
||||
|
||||
# Check if we're currently in the shutdown window (after shutdown time or before 05:00)
|
||||
if [[ $current_time_minutes -ge $shutdown_time_minutes ]] || [[ $current_time_minutes -le 300 ]]; then
|
||||
# We're in shutdown window - show warning
|
||||
if [[ $current_time_minutes -ge $shutdown_time_minutes ]] || [[ $current_time_minutes -le $morning_end_minutes ]]; then
|
||||
echo "⏻ SHUTDOWN"
|
||||
echo "⏻"
|
||||
echo "#FF5555"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Calculate minutes until shutdown
|
||||
minutes_until_shutdown=$((shutdown_time_minutes - current_time_minutes))
|
||||
|
||||
# Convert to hours and minutes
|
||||
hours=$((minutes_until_shutdown / 60))
|
||||
minutes=$((minutes_until_shutdown % 60))
|
||||
|
||||
# Format output
|
||||
if [[ $hours -gt 0 ]]; then
|
||||
time_str="${hours}h ${minutes}m"
|
||||
else
|
||||
time_str="${minutes}m"
|
||||
fi
|
||||
|
||||
# Color based on time remaining
|
||||
if [[ $minutes_until_shutdown -le 30 ]]; then
|
||||
# Less than 30 min - red warning
|
||||
color="#FF5555"
|
||||
icon="⏻"
|
||||
elif [[ $minutes_until_shutdown -le 60 ]]; then
|
||||
# Less than 1 hour - orange warning
|
||||
color="#FFB86C"
|
||||
icon="⏻"
|
||||
elif [[ $minutes_until_shutdown -le 120 ]]; then
|
||||
# Less than 2 hours - yellow
|
||||
color="#F1FA8C"
|
||||
icon="⏻"
|
||||
else
|
||||
# More than 2 hours - normal
|
||||
color="#6272A4"
|
||||
icon="⏻"
|
||||
fi
|
||||
|
||||
# Output for i3blocks (full_text, short_text, color)
|
||||
echo "$icon $time_str"
|
||||
echo "$icon"
|
||||
echo "$color"
|
||||
|
||||
15
linux_configuration/i3-configuration/i3blocks/time.sh
Executable file
15
linux_configuration/i3-configuration/i3blocks/time.sh
Executable file
@ -0,0 +1,15 @@
|
||||
#!/bin/bash
|
||||
# i3blocks clock, persist mode with zero external helpers in the hot path.
|
||||
|
||||
set -uo pipefail
|
||||
|
||||
emit() {
|
||||
printf ' %(%Y-%m-%d %H:%M)T\n' -1
|
||||
}
|
||||
|
||||
while :; do
|
||||
emit
|
||||
printf -v now '%(%s)T' -1
|
||||
delay=$((60 - now % 60))
|
||||
IFS= read -r -t "$delay" _ || true
|
||||
done
|
||||
@ -1,26 +1,32 @@
|
||||
#!/bin/bash
|
||||
# i3blocks WARP indicator with a single helper process.
|
||||
|
||||
# Check if warp-cli is installed
|
||||
if ! command -v warp-cli &> /dev/null; then
|
||||
set -euo pipefail
|
||||
|
||||
if ! command -v warp-cli > /dev/null 2>&1; then
|
||||
echo " N/A"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Get the status from warp-cli
|
||||
status=$(warp-cli status 2> /dev/null | grep "Status update:" | awk '{print $3}')
|
||||
status=''
|
||||
while IFS= read -r line; do
|
||||
case $line in
|
||||
'Status update: '*)
|
||||
status=${line#Status update: }
|
||||
;;
|
||||
esac
|
||||
done < <(warp-cli status 2> /dev/null)
|
||||
|
||||
# Display the status with an icon
|
||||
if [ "$status" = "Connected" ]; then
|
||||
if [[ $status == Connected ]]; then
|
||||
echo "🔒 !!! WARP CONNECTED !!!"
|
||||
echo
|
||||
echo "#FFFF00" # Yellow
|
||||
elif [ "$status" = "Disconnected" ]; then
|
||||
echo "#FFFF00"
|
||||
elif [[ $status == Disconnected ]]; then
|
||||
echo "WARP disconnected"
|
||||
echo
|
||||
echo "#00FF00" # Green
|
||||
echo "#00FF00"
|
||||
else
|
||||
echo "⚠️ ! WARP unknown !"
|
||||
echo
|
||||
echo "#FF0000" # Red
|
||||
exit 0
|
||||
echo "#FF0000"
|
||||
fi
|
||||
|
||||
@ -1,27 +1,62 @@
|
||||
#!/bin/bash
|
||||
# i3blocks Wi-Fi indicator with a small, bounded helper budget.
|
||||
|
||||
# Detect the active WiFi interface
|
||||
wifi_interface=$(iw dev | awk '$1=="Interface"{print $2}')
|
||||
set -euo pipefail
|
||||
|
||||
# If no WiFi interface is found, exit
|
||||
if [ -z "$wifi_interface" ]; then
|
||||
find_wifi_interface() {
|
||||
local line
|
||||
while IFS= read -r line; do
|
||||
case $line in
|
||||
*'Interface '*)
|
||||
printf '%s\n' "${line##*Interface }"
|
||||
return 0
|
||||
;;
|
||||
esac
|
||||
done < <(iw dev 2> /dev/null)
|
||||
return 1
|
||||
}
|
||||
|
||||
wifi_interface=$(find_wifi_interface) || {
|
||||
echo " down"
|
||||
exit 1
|
||||
exit 0
|
||||
}
|
||||
|
||||
ssid=''
|
||||
signal=''
|
||||
while IFS= read -r line; do
|
||||
case $line in
|
||||
'SSID: '*)
|
||||
ssid=${line#SSID: }
|
||||
;;
|
||||
'signal: '*)
|
||||
signal=${line#signal: }
|
||||
signal=${signal% dBm}
|
||||
;;
|
||||
'Not connected.'*)
|
||||
ssid=''
|
||||
;;
|
||||
esac
|
||||
done < <(iw dev "$wifi_interface" link 2> /dev/null)
|
||||
|
||||
if [[ -z $ssid ]]; then
|
||||
echo " down"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Get the WiFi details
|
||||
wifi_info=$(iwconfig "$wifi_interface" 2> /dev/null)
|
||||
ip_address=''
|
||||
while IFS= read -r line; do
|
||||
[[ $line == *' inet '* ]] || continue
|
||||
read -r -a fields <<< "$line"
|
||||
for ((i = 0; i < ${#fields[@]}; i++)); do
|
||||
if [[ ${fields[i]} == inet && $((i + 1)) -lt ${#fields[@]} ]]; then
|
||||
ip_address=${fields[i + 1]%%/*}
|
||||
break 2
|
||||
fi
|
||||
done
|
||||
done < <(ip -o -4 addr show dev "$wifi_interface" scope global 2> /dev/null)
|
||||
|
||||
# Extract the SSID and signal strength
|
||||
ssid=$(echo "$wifi_info" | awk -F '"' '/ESSID/ {print $2}')
|
||||
signal=$(echo "$wifi_info" | awk '/Signal level/ {print $4}' | sed 's/level=//')
|
||||
|
||||
# Get the IP address
|
||||
ip_address=$(ip addr show "$wifi_interface" | awk '/inet / {print $2}' | cut -d/ -f1)
|
||||
|
||||
# Output the result
|
||||
if [ -z "$ssid" ]; then
|
||||
echo " down"
|
||||
else
|
||||
if [[ -n $ip_address ]]; then
|
||||
echo " $ssid ($signal dBm) $ip_address"
|
||||
else
|
||||
echo " $ssid ($signal dBm)"
|
||||
fi
|
||||
|
||||
@ -162,26 +162,19 @@ def notify(title: str, message: str, urgency: str = "normal") -> None:
|
||||
|
||||
|
||||
def get_running_processes() -> set[str]:
|
||||
"""Get set of currently running process names."""
|
||||
"""Get set of currently running process names by reading /proc directly.
|
||||
|
||||
Reads /proc/*/comm to avoid forking a subprocess on every poll cycle.
|
||||
"""
|
||||
processes: set[str] = set()
|
||||
ps_bin = shutil.which("ps")
|
||||
if ps_bin is None:
|
||||
return processes
|
||||
try:
|
||||
result = subprocess.run(
|
||||
[ps_bin, "-eo", "comm="],
|
||||
capture_output=True,
|
||||
text=True,
|
||||
timeout=10,
|
||||
check=False,
|
||||
)
|
||||
if result.returncode == 0:
|
||||
for line in result.stdout.strip().split("\n"):
|
||||
proc_name = line.strip().lower()
|
||||
for comm_path in Path("/proc").glob("*/comm"):
|
||||
with contextlib.suppress(OSError):
|
||||
proc_name = comm_path.read_text().strip().lower()
|
||||
if proc_name:
|
||||
processes.add(proc_name)
|
||||
except (OSError, subprocess.SubprocessError) as exc:
|
||||
log(f"Error getting processes: {exc}")
|
||||
except OSError as exc:
|
||||
log(f"Error reading /proc: {exc}")
|
||||
return processes
|
||||
|
||||
|
||||
|
||||
@ -19,7 +19,7 @@ log_message() {
|
||||
local msg="$1"
|
||||
local log_file="${2:-}"
|
||||
local formatted
|
||||
formatted="$(date '+%Y-%m-%d %H:%M:%S') - $msg"
|
||||
printf -v formatted '%(%Y-%m-%d %H:%M:%S)T - %s' -1 "$msg"
|
||||
echo "$formatted" >&2
|
||||
if [[ -n $log_file ]]; then
|
||||
echo "$formatted" >>"$log_file" 2>/dev/null || true
|
||||
@ -29,7 +29,9 @@ log_message() {
|
||||
# Simple log with timestamp (no file output)
|
||||
# Usage: log "message"
|
||||
log() {
|
||||
printf '[%s] %s\n' "$(date '+%Y-%m-%d %H:%M:%S')" "$*"
|
||||
local _ts
|
||||
printf -v _ts '%(%Y-%m-%d %H:%M:%S)T' -1
|
||||
printf '[%s] %s\n' "$_ts" "$*"
|
||||
}
|
||||
|
||||
# =============================================================================
|
||||
@ -180,24 +182,29 @@ FOCUS_APPS_PROCESSES=(
|
||||
# Returns 0 if focus app found, 1 otherwise
|
||||
# Echoes the name of the found app
|
||||
is_focus_app_running() {
|
||||
# Check windows first
|
||||
if command -v xdotool &>/dev/null; then
|
||||
local app
|
||||
for app in "${FOCUS_APPS_WINDOWS[@]}"; do
|
||||
if xdotool search --name "$app" &>/dev/null 2>&1; then
|
||||
echo "$app"
|
||||
# One xdotool call with a combined regex instead of N separate calls
|
||||
if command -v xdotool &>/dev/null && [[ ${#FOCUS_APPS_WINDOWS[@]} -gt 0 ]]; then
|
||||
local regex wid
|
||||
printf -v regex '%s|' "${FOCUS_APPS_WINDOWS[@]}"
|
||||
regex="${regex%|}" # strip trailing |
|
||||
wid=$(xdotool search --name "$regex" 2>/dev/null | head -1 || true)
|
||||
if [[ -n $wid ]]; then
|
||||
xdotool getwindowname "$wid" 2>/dev/null || echo "focus app"
|
||||
return 0
|
||||
fi
|
||||
fi
|
||||
|
||||
# Check specific processes via /proc (no fork)
|
||||
local app comm
|
||||
for app in "${FOCUS_APPS_PROCESSES[@]}"; do
|
||||
for comm in /proc/[0-9]*/comm; do
|
||||
[[ -r $comm ]] || continue
|
||||
read -r _proc_comm < "$comm" 2>/dev/null || continue
|
||||
if [[ $_proc_comm == *"$app"* ]]; then
|
||||
echo "$_proc_comm"
|
||||
return 0
|
||||
fi
|
||||
done
|
||||
fi
|
||||
|
||||
# Check specific processes
|
||||
local app
|
||||
for app in "${FOCUS_APPS_PROCESSES[@]}"; do
|
||||
if pgrep -f "$app" &>/dev/null; then
|
||||
echo "$app"
|
||||
return 0
|
||||
fi
|
||||
done
|
||||
|
||||
return 1
|
||||
|
||||
@ -11,7 +11,9 @@ HOSTS_INSTALL_SCRIPT="__HOSTS_INSTALL_SCRIPT__"
|
||||
|
||||
# Log with timestamp (hosts-file-monitor specific)
|
||||
log_message() {
|
||||
printf '%s [hosts-monitor] %s\n' "$(date '+%Y-%m-%d %H:%M:%S')" "$1" | tee -a "$LOG_FILE" >&2
|
||||
local _ts
|
||||
printf -v _ts '%(%Y-%m-%d %H:%M:%S)T' -1
|
||||
printf '%s [hosts-monitor] %s\n' "$_ts" "$1" | tee -a "$LOG_FILE" >&2
|
||||
}
|
||||
|
||||
# Function to check if hosts file needs restoration
|
||||
|
||||
@ -12,7 +12,9 @@ CHECK_INTERVAL=30
|
||||
|
||||
# Log with timestamp (shutdown-timer-monitor specific)
|
||||
log_message() {
|
||||
printf '%s [shutdown-monitor] %s\n' "$(date '+%Y-%m-%d %H:%M:%S')" "$1" | tee -a "$LOG_FILE" >&2
|
||||
local _ts
|
||||
printf -v _ts '%(%Y-%m-%d %H:%M:%S)T' -1
|
||||
printf '%s [shutdown-monitor] %s\n' "$_ts" "$1" | tee -a "$LOG_FILE" >&2
|
||||
}
|
||||
|
||||
# Function to check if timer needs to be re-enabled
|
||||
|
||||
272
linux_configuration/tests/test_i3blocks_efficiency.sh
Executable file
272
linux_configuration/tests/test_i3blocks_efficiency.sh
Executable file
@ -0,0 +1,272 @@
|
||||
#!/bin/bash
|
||||
# Regression tests for i3blocks hot-path efficiency fixes.
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR=$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)
|
||||
REPO_DIR=$(cd -- "$SCRIPT_DIR/.." && pwd)
|
||||
I3BLOCKS_DIR="$REPO_DIR/i3-configuration/i3blocks"
|
||||
CONFIG_FILE="$I3BLOCKS_DIR/config"
|
||||
|
||||
TMP_DIR=$(mktemp -d)
|
||||
BIN_DIR="$TMP_DIR/bin"
|
||||
mkdir -p "$BIN_DIR"
|
||||
|
||||
cleanup() {
|
||||
if [[ -n "${AW_PID:-}" ]]; then
|
||||
kill "$AW_PID" 2>/dev/null || true
|
||||
wait "$AW_PID" 2>/dev/null || true
|
||||
fi
|
||||
rm -rf "$TMP_DIR"
|
||||
}
|
||||
trap cleanup EXIT
|
||||
|
||||
fail() {
|
||||
printf 'FAIL: %s\n' "$1" >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
assert_equals() {
|
||||
local expected="$1"
|
||||
local actual="$2"
|
||||
local context="$3"
|
||||
if [[ "$expected" != "$actual" ]]; then
|
||||
fail "$context (expected: '$expected', actual: '$actual')"
|
||||
fi
|
||||
}
|
||||
|
||||
assert_le() {
|
||||
local actual="$1"
|
||||
local expected_max="$2"
|
||||
local context="$3"
|
||||
if (( actual > expected_max )); then
|
||||
fail "$context (expected <= $expected_max, actual: $actual)"
|
||||
fi
|
||||
}
|
||||
|
||||
epoch_utc() {
|
||||
TZ=UTC date -d "$1" +%s
|
||||
}
|
||||
|
||||
count_execs() {
|
||||
local script_path="$1"
|
||||
local log_file="$TMP_DIR/trace.log"
|
||||
PATH="$BIN_DIR:$PATH" strace -f -o "$log_file" -e trace=execve bash "$script_path" \
|
||||
>/dev/null 2>&1
|
||||
grep -c 'execve(' "$log_file"
|
||||
}
|
||||
|
||||
cat >"$BIN_DIR/bluetoothctl" <<'EOF'
|
||||
#!/bin/bash
|
||||
printf '%s\n' \
|
||||
'Device AA:BB:CC:DD:EE:FF' \
|
||||
'Alias: Test Headphones' \
|
||||
'Connected: yes'
|
||||
EOF
|
||||
chmod +x "$BIN_DIR/bluetoothctl"
|
||||
|
||||
cat >"$BIN_DIR/pacman" <<'EOF'
|
||||
#!/bin/bash
|
||||
exit 1
|
||||
EOF
|
||||
chmod +x "$BIN_DIR/pacman"
|
||||
|
||||
cat >"$BIN_DIR/pgrep" <<'EOF'
|
||||
#!/bin/bash
|
||||
exit 1
|
||||
EOF
|
||||
chmod +x "$BIN_DIR/pgrep"
|
||||
|
||||
cat >"$BIN_DIR/iw" <<'EOF'
|
||||
#!/bin/bash
|
||||
set -euo pipefail
|
||||
|
||||
if [[ $# -eq 1 && $1 == dev ]]; then
|
||||
if [[ ${WIFI_HAS_INTERFACE:-1} == 1 ]]; then
|
||||
printf '%s\n' \
|
||||
'phy#0' \
|
||||
' Interface wlan0'
|
||||
fi
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if [[ $# -eq 3 && $1 == dev && $3 == link ]]; then
|
||||
if [[ ${WIFI_CONNECTED:-1} == 1 ]]; then
|
||||
printf '%s\n' \
|
||||
'Connected to 00:11:22:33:44:55 (on wlan0)' \
|
||||
'SSID: TestWifi' \
|
||||
'signal: -53 dBm'
|
||||
else
|
||||
printf '%s\n' 'Not connected.'
|
||||
fi
|
||||
exit 0
|
||||
fi
|
||||
|
||||
printf 'unexpected iw args: %s\n' "$*" >&2
|
||||
exit 1
|
||||
EOF
|
||||
chmod +x "$BIN_DIR/iw"
|
||||
|
||||
cat >"$BIN_DIR/ip" <<'EOF'
|
||||
#!/bin/bash
|
||||
set -euo pipefail
|
||||
|
||||
if [[ $# -ge 8 && $1 == -o && $2 == -4 && $3 == addr && $4 == show ]]; then
|
||||
printf '%s\n' '3: wlan0 inet 192.168.1.44/24 brd 192.168.1.255 scope global dynamic wlan0'
|
||||
exit 0
|
||||
fi
|
||||
|
||||
printf 'unexpected ip args: %s\n' "$*" >&2
|
||||
exit 1
|
||||
EOF
|
||||
chmod +x "$BIN_DIR/ip"
|
||||
|
||||
cat >"$BIN_DIR/warp-cli" <<'EOF'
|
||||
#!/bin/bash
|
||||
set -euo pipefail
|
||||
|
||||
if [[ $# -eq 1 && $1 == status ]]; then
|
||||
printf 'Status update: %s\n' "${WARP_STATUS:-Disconnected}"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
printf 'unexpected warp-cli args: %s\n' "$*" >&2
|
||||
exit 1
|
||||
EOF
|
||||
chmod +x "$BIN_DIR/warp-cli"
|
||||
|
||||
cat >"$BIN_DIR/df" <<'EOF'
|
||||
#!/bin/bash
|
||||
set -euo pipefail
|
||||
|
||||
if [[ $# -eq 2 && $1 == -h && $2 == / ]]; then
|
||||
printf '%s\n' \
|
||||
'Filesystem Size Used Avail Use% Mounted on' \
|
||||
'/dev/nvme0n1p2 100G 15G 80G 16% /'
|
||||
exit 0
|
||||
fi
|
||||
|
||||
printf 'unexpected df args: %s\n' "$*" >&2
|
||||
exit 1
|
||||
EOF
|
||||
chmod +x "$BIN_DIR/df"
|
||||
|
||||
ln -s /bin/sleep "$BIN_DIR/aw-qt"
|
||||
|
||||
printf 'Checking config uses dedicated low-fork scripts...\n'
|
||||
grep -q '^command=~/.config/i3blocks/time.sh$' "$CONFIG_FILE" \
|
||||
|| fail 'time block should call time.sh'
|
||||
grep -q '^interval=persist$' "$CONFIG_FILE" \
|
||||
|| fail 'config should use persist interval for time block'
|
||||
grep -q '^command=~/.config/i3blocks/memory.sh$' "$CONFIG_FILE" \
|
||||
|| fail 'memory block should call memory.sh'
|
||||
grep -q '^command=~/.config/i3blocks/ethernet.sh$' "$CONFIG_FILE" \
|
||||
|| fail 'ethernet block should call ethernet.sh'
|
||||
grep -q '^command=~/.config/i3blocks/disk.sh$' "$CONFIG_FILE" \
|
||||
|| fail 'disk block should call disk.sh'
|
||||
|
||||
printf 'Checking bluetooth block behavior and fork count...\n'
|
||||
bluetooth_output=$(PATH="$BIN_DIR:$PATH" bash "$I3BLOCKS_DIR/bluetooth.sh")
|
||||
assert_equals ' Test Headphones' "$(printf '%s\n' "$bluetooth_output" | sed -n '1p')" \
|
||||
'bluetooth script should show connected alias'
|
||||
assert_le "$(count_execs "$I3BLOCKS_DIR/bluetooth.sh")" 2 \
|
||||
'bluetooth script should stay at one external helper plus bash'
|
||||
|
||||
printf 'Checking ActivityWatch block behavior and fork count...\n'
|
||||
activitywatch_output=$(PATH="$BIN_DIR:$PATH" bash "$I3BLOCKS_DIR/activitywatch_status.sh")
|
||||
assert_equals 'AW off' "$(printf '%s\n' "$activitywatch_output" | sed -n '1p')" \
|
||||
'activitywatch script should show AW off when not running'
|
||||
assert_le "$(count_execs "$I3BLOCKS_DIR/activitywatch_status.sh")" 1 \
|
||||
'activitywatch script should avoid pacman/pgrep hot-path forks'
|
||||
|
||||
"$BIN_DIR/aw-qt" 60 >/dev/null 2>&1 &
|
||||
AW_PID=$!
|
||||
activitywatch_running_output=$(PATH="$BIN_DIR:$PATH" bash "$I3BLOCKS_DIR/activitywatch_status.sh")
|
||||
assert_equals 'AW on' "$(printf '%s\n' "$activitywatch_running_output" | sed -n '1p')" \
|
||||
'activitywatch script should detect running aw-qt process'
|
||||
|
||||
printf 'Checking Wi-Fi block behavior and fork count...\n'
|
||||
wifi_connected_output=$(PATH="$BIN_DIR:$PATH" bash "$I3BLOCKS_DIR/wifi_monitor.sh")
|
||||
assert_equals ' TestWifi (-53 dBm) 192.168.1.44' \
|
||||
"$wifi_connected_output" \
|
||||
'wifi script should show ssid, signal, and IP when connected'
|
||||
assert_le "$(count_execs "$I3BLOCKS_DIR/wifi_monitor.sh")" 4 \
|
||||
'wifi script should stay within bash plus iw/iw/ip exec budget'
|
||||
|
||||
wifi_disconnected_output=$(WIFI_CONNECTED=0 PATH="$BIN_DIR:$PATH" bash "$I3BLOCKS_DIR/wifi_monitor.sh")
|
||||
assert_equals ' down' "$wifi_disconnected_output" \
|
||||
'wifi script should show down when the interface is not connected'
|
||||
|
||||
wifi_missing_output=$(WIFI_HAS_INTERFACE=0 PATH="$BIN_DIR:$PATH" bash "$I3BLOCKS_DIR/wifi_monitor.sh") || true
|
||||
assert_equals ' down' "$wifi_missing_output" \
|
||||
'wifi script should show down when no Wi-Fi interface exists'
|
||||
|
||||
printf 'Checking WARP block behavior and fork count...\n'
|
||||
warp_connected_output=$(WARP_STATUS=Connected PATH="$BIN_DIR:$PATH" bash "$I3BLOCKS_DIR/warp_status.sh")
|
||||
assert_equals '🔒 !!! WARP CONNECTED !!!' "$(printf '%s\n' "$warp_connected_output" | sed -n '1p')" \
|
||||
'warp script should show the connected warning when WARP is enabled'
|
||||
assert_equals '#FFFF00' "$(printf '%s\n' "$warp_connected_output" | sed -n '3p')" \
|
||||
'warp script should show yellow when WARP is connected'
|
||||
assert_le "$(count_execs "$I3BLOCKS_DIR/warp_status.sh")" 2 \
|
||||
'warp script should stay at one external helper plus bash'
|
||||
|
||||
warp_disconnected_output=$(WARP_STATUS=Disconnected PATH="$BIN_DIR:$PATH" bash "$I3BLOCKS_DIR/warp_status.sh")
|
||||
assert_equals 'WARP disconnected' "$(printf '%s\n' "$warp_disconnected_output" | sed -n '1p')" \
|
||||
'warp script should show the disconnected state'
|
||||
|
||||
warp_unknown_output=$(WARP_STATUS=Unknown PATH="$BIN_DIR:$PATH" bash "$I3BLOCKS_DIR/warp_status.sh")
|
||||
assert_equals '⚠️ ! WARP unknown !' "$(printf '%s\n' "$warp_unknown_output" | sed -n '1p')" \
|
||||
'warp script should show the unknown state when status parsing fails'
|
||||
|
||||
printf 'Checking disk block behavior and fork count...\n'
|
||||
disk_output=$(PATH="$BIN_DIR:$PATH" bash "$I3BLOCKS_DIR/disk.sh")
|
||||
assert_equals ' 15G/100G' "$disk_output" \
|
||||
'disk script should show used and total disk space'
|
||||
assert_le "$(count_execs "$I3BLOCKS_DIR/disk.sh")" 2 \
|
||||
'disk script should stay at one external helper plus bash'
|
||||
|
||||
printf 'Checking PC startup block behavior and fork count...\n'
|
||||
pc_live_epoch=$(epoch_utc '2026-05-01 06:30:00')
|
||||
pc_live_output=$(TZ=UTC NOW_EPOCH="$pc_live_epoch" UPTIME_SECONDS=1800 PATH="$BIN_DIR:$PATH" bash "$I3BLOCKS_DIR/pc_startup_status.sh")
|
||||
assert_equals 'PC:live' "$(printf '%s\n' "$pc_live_output" | sed -n '1p')" \
|
||||
'pc startup script should show live during the monitored startup window'
|
||||
assert_le "$(count_execs "$I3BLOCKS_DIR/pc_startup_status.sh")" 1 \
|
||||
'pc startup script should avoid date and text-processing helpers'
|
||||
|
||||
pc_ok_epoch=$(epoch_utc '2026-05-01 10:00:00')
|
||||
pc_ok_output=$(TZ=UTC NOW_EPOCH="$pc_ok_epoch" UPTIME_SECONDS=14400 PATH="$BIN_DIR:$PATH" bash "$I3BLOCKS_DIR/pc_startup_status.sh")
|
||||
assert_equals 'PC:ok' "$(printf '%s\n' "$pc_ok_output" | sed -n '1p')" \
|
||||
'pc startup script should show ok when boot happened inside the startup window'
|
||||
|
||||
pc_warn_epoch=$(epoch_utc '2026-05-01 10:00:00')
|
||||
pc_warn_output=$(TZ=UTC NOW_EPOCH="$pc_warn_epoch" UPTIME_SECONDS=1800 PATH="$BIN_DIR:$PATH" bash "$I3BLOCKS_DIR/pc_startup_status.sh")
|
||||
assert_equals 'PC:warn' "$(printf '%s\n' "$pc_warn_output" | sed -n '1p')" \
|
||||
'pc startup script should warn when boot happened outside the startup window'
|
||||
|
||||
pc_skip_epoch=$(epoch_utc '2026-04-30 10:00:00')
|
||||
pc_skip_output=$(TZ=UTC NOW_EPOCH="$pc_skip_epoch" UPTIME_SECONDS=1800 PATH="$BIN_DIR:$PATH" bash "$I3BLOCKS_DIR/pc_startup_status.sh")
|
||||
assert_equals 'PC:skip' "$(printf '%s\n' "$pc_skip_output" | sed -n '1p')" \
|
||||
'pc startup script should skip on unmonitored days'
|
||||
|
||||
printf 'Checking shutdown countdown behavior and fork count...\n'
|
||||
shutdown_config_file="$TMP_DIR/shutdown-schedule.conf"
|
||||
cat >"$shutdown_config_file" <<'EOF'
|
||||
MON_WED_HOUR=23
|
||||
THU_SUN_HOUR=21
|
||||
EOF
|
||||
|
||||
shutdown_countdown_epoch=$(epoch_utc '2026-05-01 19:30:00')
|
||||
shutdown_countdown_output=$(TZ=UTC NOW_EPOCH="$shutdown_countdown_epoch" SHUTDOWN_CONFIG="$shutdown_config_file" PATH="$BIN_DIR:$PATH" bash "$I3BLOCKS_DIR/shutdown_countdown.sh")
|
||||
assert_equals '⏻ 1h 30m' "$(printf '%s\n' "$shutdown_countdown_output" | sed -n '1p')" \
|
||||
'shutdown countdown should show the time remaining until shutdown'
|
||||
assert_equals '#F1FA8C' "$(printf '%s\n' "$shutdown_countdown_output" | sed -n '3p')" \
|
||||
'shutdown countdown should show yellow for two hours or less remaining'
|
||||
assert_le "$(count_execs "$I3BLOCKS_DIR/shutdown_countdown.sh")" 1 \
|
||||
'shutdown countdown should avoid date helpers in the hot path'
|
||||
|
||||
shutdown_window_epoch=$(epoch_utc '2026-05-01 21:15:00')
|
||||
shutdown_window_output=$(TZ=UTC NOW_EPOCH="$shutdown_window_epoch" SHUTDOWN_CONFIG="$shutdown_config_file" PATH="$BIN_DIR:$PATH" bash "$I3BLOCKS_DIR/shutdown_countdown.sh")
|
||||
assert_equals '⏻ SHUTDOWN' "$(printf '%s\n' "$shutdown_window_output" | sed -n '1p')" \
|
||||
'shutdown countdown should show SHUTDOWN inside the blocked window'
|
||||
|
||||
printf 'All i3blocks efficiency regression tests passed.\n'
|
||||
Loading…
Reference in New Issue
Block a user