Skip to content

Commit e2fc849

Browse files
author
guttermonk
committed
Added boot/resume detection
1 parent 365eef1 commit e2fc849

File tree

2 files changed

+156
-32
lines changed

2 files changed

+156
-32
lines changed

README.md

Lines changed: 66 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,9 @@ System Requirements:
2323
1. NixOS operating system (based on the nature of the script)
2424
2. A running Waybar instance (the script outputs JSON for Waybar integration)
2525
3. Internet connectivity for performing update checks
26+
4. Desktop notification system compatible with `notify-send`
2627

27-
## Privacy
28+
## Privacy and Security Considerations
2829
External Network Requests: The script uses `ping -c 1 -W 2 8.8.8.8` to check network connectivity and send packets to Google's DNS servers (8.8.8.8), which could potentially reveal:
2930
- That your system is running and online
3031
- The fact you're using this specific script
@@ -36,40 +37,66 @@ External Network Requests: The script uses `ping -c 1 -W 2 8.8.8.8` to check net
3637

3738
2. **File Initialization**: Creates necessary state files if they don't exist (tracks update count, last check time, and tooltip info).
3839

39-
3. **Network Check**: Verifies internet connectivity by pinging 8.8.8.8.
40+
3. **Boot/Resume Detection**: Detects if the system has recently booted or resumed from suspension/hibernation to avoid unnecessary resource usage during these transition periods.
4041

41-
4. **System Update Status**: Checks if the system was recently rebuilt by looking for the rebuild flag.
42+
4. **Grace Period Management**: Applies a configurable grace period after boot or resume before running update checks.
4243

43-
5. **Update Check Timing**: Determines if it's time to check for updates based on the last check timestamp.
44+
5. **Network Check**: Verifies internet connectivity by pinging 8.8.8.8.
4445

45-
6. **Temporary Environment**: Creates a temporary directory for performing update checks without modifying the system.
46+
6. **System Update Status**: Checks if the system was recently rebuilt by looking for the rebuild flag.
4647

47-
7. **Flake Update**: Runs `nix flake update` either in the config directory or temp directory based on settings.
48+
7. **Update Check Timing**: Determines if it's time to check for updates based on the last check timestamp.
4849

49-
8. **System Build**: Builds the updated system configuration to compare with the current one.
50+
8. **Temporary Environment**: Creates a temporary directory for performing update checks without modifying the system.
5051

51-
9. **Update Comparison**: Uses `nvd diff` to compare current system with the new build and count updates.
52+
9. **Flake Update**: Runs `nix flake update` either in the config directory or temp directory based on settings.
5253

53-
10. **Result Storage**: Saves the number of updates and detailed update information to state files.
54+
10. **System Build**: Builds the updated system configuration to compare with the current one.
5455

55-
11. **Notification**: Sends desktop notifications to inform the user about the update status.
56+
11. **Update Comparison**: Uses `nvd diff` to compare current system with the new build and count updates.
5657

57-
12. **JSON Output**: Generates a JSON object with update count, status indicator, and tooltip for Waybar.
58+
12. **Result Storage**: Saves the number of updates and detailed update information to state files.
5859

59-
13. **Flag Management**: Cleans up system update flags if a rebuild was detected.
60+
13. **Notification**: Sends desktop notifications to inform the user about the update status.
6061

61-
14. **Error Handling**: Sets appropriate status messages if update checks fail or network is unavailable.
62+
14. **JSON Output**: Generates a JSON object with update count, status indicator, and tooltip for Waybar.
6263

63-
15. **Tooltip Generation**: Creates detailed tooltips showing which packages have updates available.
64+
15. **Flag Management**: Cleans up system update flags if a rebuild was detected.
6465

65-
16. **State Management**: Manages update state across multiple runs of the script.
66+
16. **Error Handling**: Sets appropriate status messages if update checks fail or network is unavailable.
6667

67-
17. **Output Formatting**: Formats the final output to be compatible with Waybar's custom module format.
68+
17. **Tooltip Generation**: Creates detailed tooltips showing which packages have updates available.
69+
70+
18. **State Management**: Manages update state across multiple runs of the script.
71+
72+
19. **Output Formatting**: Formats the final output to be compatible with Waybar's custom module format.
6873

6974

7075
## How to Use
7176
Download the `update-checker` script, put it in your [PATH](https://unix.stackexchange.com/a/26059) and make it executable (`chmod +x update-checker`).
7277

78+
### Configuration Options
79+
80+
You can modify these variables at the top of the script to customize behavior:
81+
82+
- `UPDATE_INTERVAL`: Time in seconds between update checks (default: 3599)
83+
- `NIXOS_CONFIG_PATH`: Path to your NixOS configuration (default: ~/.config/nixos)
84+
- `CACHE_DIR`: Directory for storing cache files (default: ~/.cache)
85+
- `SKIP_AFTER_BOOT`: Whether to skip update checks right after boot/resume (default: true)
86+
- `GRACE_PERIOD`: Time in seconds to wait after boot/resume before checking (default: 60)
87+
- `UPDATE_LOCK_FILE`: Whether to update the lock file directly or use a temporary copy (default: false)
88+
89+
#### Cache Files
90+
The script uses several cache files in your ~/.cache directory:
91+
- `nix-update-state`: Stores the current number of available updates
92+
- `nix-update-last-run`: Tracks when the last update check was performed
93+
- `nix-update-tooltip`: Contains the tooltip text with update details
94+
- `nix-update-boot-marker`: Used to detect system boot/resume events
95+
- `nix-update-update-flag`: Signals that your lock file has been updated
96+
- `nix-update-rebuild-flag`: Signals that your system has been rebuilt
97+
98+
### Waybar Integration
99+
73100
To configure, add the following to your Waybar config (`~/.config/waybar/config`).
74101

75102
In json:
@@ -111,30 +138,43 @@ In nix:
111138
To style use the `#custom-nix-updates` ID in your Waybar styles file (`~/.config/waybar/styles.css`).
112139

113140

114-
If you have you have UPDATE_LOCK_FILE set to "false", the UPDATE_FLAG file will signal that your lock file has been updated. Add the following to your update script, used to update your lock file (i.e. "nix flake update" script), so that the output of nvd diff is piped in:
141+
If you have UPDATE_LOCK_FILE set to "false", the UPDATE_FLAG file will signal that your lock file has been updated. Add the following to your update script, used to update your lock file (i.e. "nix flake update" script), so that the output of nvd diff is piped in:
115142
`| tee >(if grep -qe '\\[U'; then touch \"$HOME/.cache/nix-update-update-flag\"; else rm -f \"$HOME/.cache/nix-update-update-flag\"; fi) &&`
116143

117144
For example:
118145
```nix
119-
checkup =
120-
"pushd ~/.config/nixos &&
121-
nix flake update nixpkgs nixpkgs-unstable &&
122-
nix build .#nixosConfigurations.'hyprnix'.config.system.build.toplevel &&
123-
nvd diff /run/current-system ./result | tee >(if grep -qe '\\[U'; then touch \"$HOME/.cache/nix-update-update-flag\"; else rm -f \"$HOME/.cache/nix-update-update-flag\"; fi) &&
124-
popd";
146+
checkup =
147+
"pushd ~/.config/nixos &&
148+
nix flake update nixpkgs nixpkgs-unstable &&
149+
nix build .#nixosConfigurations.'hyprnix'.config.system.build.toplevel &&
150+
nvd diff /run/current-system ./result | tee >(if grep -qe '\\[U'; then touch \"$HOME/.cache/nix-update-update-flag\"; else rm -f \"$HOME/.cache/nix-update-update-flag\"; fi) &&
151+
popd";
125152
```
126153

127154
The REBUILD_FLAG signals this script to run after your system has been rebuilt. Add this to your update script to create the REBUILD_FLAG and send a signal to waybar to refresh after updating:
128-
`touch $HOME/.cache/nix-update-rebuild-flag && pkill -x -RTMIN+12 .waybar-wrapped &&`
155+
`if [ -f \"$HOME/.cache/nix-update-update-flag\" ]; then touch \"$HOME/.cache/nix-update-rebuild-flag\" && pkill -x -RTMIN+12 .waybar-wrapped; fi &&`
156+
157+
This works with the `signal: 12` parameter in the Waybar configuration, which causes Waybar to run the script when it receives RTMIN+12 signal.
158+
159+
### Notifications
160+
161+
The script sends desktop notifications to keep you informed:
162+
- When starting an update check: "Checking for Updates"
163+
- When throttled due to recent checks: "Please Wait" with time until next check
164+
- When updates are found: "Update Check Complete" with the number of updates
165+
- When no updates are found: "Update Check Complete - No updates available"
166+
- When connectivity fails: "Update Check Failed - Not connected to the internet"
167+
168+
These notifications require `notify-send` to be installed on your system.
129169

130170
For example:
131171
```nix
132172
nixup =
133173
"pushd ~/.config/nixos &&
134174
echo \"NixOS rebuilding...\" &&
135175
sudo nixos-rebuild switch --upgrade --flake .#hyprnix &&
136-
touch $HOME/.cache/nix-update-rebuild-flag &&
137-
pkill -x -RTMIN+12 .waybar-wrapped &&
176+
if [ -f \"$HOME/.cache/nix-update-update-flag\" ]; then touch \"$HOME/.cache/nix-update-rebuild-flag\" &&
177+
pkill -x -RTMIN+12 .waybar-wrapped; fi &&
138178
popd";
139179
```
140180

update-checker

Lines changed: 90 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,20 @@
11
#!/usr/bin/env bash
22

3-
# NixOS Update Checker for Waybar
4-
# This script checks for NixOS updates and outputs JSON for Waybar integration
5-
63
# ===== Configuration =====
74
UPDATE_INTERVAL=3599 # Check interval in seconds (1 hour)
85
NIXOS_CONFIG_PATH="$HOME/.config/nixos" # Path to NixOS configuration
96
CACHE_DIR="$HOME/.cache"
107
STATE_FILE="$CACHE_DIR/nix-update-state"
118
LAST_RUN_FILE="$CACHE_DIR/nix-update-last-run"
129
LAST_RUN_TOOLTIP="$CACHE_DIR/nix-update-tooltip"
10+
BOOT_MARKER_FILE="$CACHE_DIR/nix-update-boot-marker" # Marker file to detect boot/resume
11+
12+
# The grace period prevents the update checker from running immediately after:
13+
# 1. First boot - when the system has just started up
14+
# 2. Resume from hibernation/suspension - when the system has just woken up
15+
# This avoids unnecessary resource usage and notifications during these transition periods.
16+
SKIP_AFTER_BOOT=true # Set to false if you want to run the checker even after boot/resume
17+
GRACE_PERIOD=60 # Grace period in seconds (60 seconds) after boot/resume
1318

1419
# If true, update the lock file in the config folder.
1520
# If false, copy config to temp folder first, and then update the temp dir's lock file.
@@ -24,7 +29,7 @@ UPDATE_FLAG="$CACHE_DIR/nix-update-update-flag"
2429

2530
# The REBUILD_FLAG signals this script to run after your system has been rebuilt.
2631
# Add this to your update script:
27-
# && touch $HOME/.cache/nix-update-rebuild-flag && pkill -x -RTMIN+12 .waybar-wrapped
32+
# if [ -f \"$HOME/.cache/nix-update-update-flag\" ]; then touch \"$HOME/.cache/nix-update-rebuild-flag\" && pkill -x -RTMIN+12 .waybar-wrapped; fi &&
2833
REBUILD_FLAG="$CACHE_DIR/nix-update-rebuild-flag"
2934

3035

@@ -59,6 +64,75 @@ function send_notification() {
5964
notify-send "$title" "$message" -e
6065
}
6166

67+
function check_boot_resume() {
68+
# This function detects if the system has recently booted or resumed from hibernation/sleep
69+
# Returns 0 (true) if we're in the grace period, 1 (false) otherwise
70+
71+
local current_time=$(date +%s)
72+
local uptime_seconds=$(cat /proc/uptime | awk '{print int($1)}')
73+
local last_boot_time=$((current_time - uptime_seconds))
74+
75+
# Check if this is first run after boot
76+
if [ ! -f "$BOOT_MARKER_FILE" ] || [ $((current_time - last_boot_time)) -lt "$GRACE_PERIOD" ]; then
77+
# We're either in first run or within grace period after boot
78+
echo "$current_time" > "$BOOT_MARKER_FILE"
79+
return 0
80+
fi
81+
82+
# Initialize resume timestamp
83+
local last_resume=0
84+
85+
# Try to detect resume using systemd logs
86+
if command -v journalctl >/dev/null 2>&1; then
87+
# Get timestamp of last resume/wakeup event from systemd journal
88+
local resume_log=$(journalctl -b -u systemd-suspend.service -u systemd-hibernate.service -n 1 -o short-unix 2>/dev/null)
89+
if [ -n "$resume_log" ]; then
90+
# Extract just the numeric timestamp from the beginning of the line
91+
local timestamp=$(echo "$resume_log" | sed -E 's/^([0-9]+).*/\1/')
92+
if [ -n "$timestamp" ] && [[ "$timestamp" =~ ^[0-9]+$ ]]; then
93+
last_resume=$timestamp
94+
fi
95+
fi
96+
97+
# If no direct service logs, try looking for resume messages in kernel logs
98+
if [ $last_resume -eq 0 ]; then
99+
local wake_log=$(journalctl -b -k -g "PM: resumed" -n 1 -o short-unix 2>/dev/null)
100+
if [ -n "$wake_log" ]; then
101+
# Extract just the numeric timestamp from the beginning of the line
102+
local timestamp=$(echo "$wake_log" | sed -E 's/^([0-9]+).*/\1/')
103+
if [ -n "$timestamp" ] && [[ "$timestamp" =~ ^[0-9]+$ ]]; then
104+
last_resume=$timestamp
105+
fi
106+
fi
107+
fi
108+
fi
109+
110+
# Check if we can find resume info in NixOS-specific locations
111+
if [ $last_resume -eq 0 ] && [ -d "/run/systemd/system" ]; then
112+
# Check systemd sleep state
113+
if [ -f "/run/systemd/suspend/active" ] || [ -f "/run/systemd/hibernate/active" ]; then
114+
last_resume=$current_time # Just woke up
115+
fi
116+
fi
117+
118+
# If we detected a resume and it's recent, we're in grace period
119+
if [ $last_resume -gt 0 ] && [ $((current_time - last_resume)) -lt "$GRACE_PERIOD" ]; then
120+
echo "$current_time" > "$BOOT_MARKER_FILE"
121+
return 0
122+
fi
123+
124+
# Check if we have a saved boot marker and we're still in grace period
125+
if [ -f "$BOOT_MARKER_FILE" ]; then
126+
local marker_time=$(cat "$BOOT_MARKER_FILE")
127+
if [[ "$marker_time" =~ ^[0-9]+$ ]] && [ $((current_time - marker_time)) -lt "$GRACE_PERIOD" ]; then
128+
return 0 # Still in grace period from marker
129+
fi
130+
fi
131+
132+
# Not in grace period
133+
return 1
134+
}
135+
62136
function check_network_connectivity() {
63137
# Check if either ethernet or wireless is connected
64138
if ping -c 1 -W 2 8.8.8.8 > /dev/null 2>&1; then
@@ -74,7 +148,6 @@ function sys_updated() {
74148
else
75149
return 1 # System has not been updated
76150
fi
77-
78151
}
79152

80153
function calc_next_update() {
@@ -145,6 +218,16 @@ function check_for_updates() {
145218
function main() {
146219
init_files
147220

221+
# Check if we're in post-boot/resume grace period
222+
if [ "$SKIP_AFTER_BOOT" = "true" ] && check_boot_resume; then
223+
# Skip update check during grace period after boot or resume from hibernation
224+
# This prevents unnecessary resource usage during system startup or wakeup
225+
updates=$(cat "$STATE_FILE")
226+
var_setter
227+
echo "{ \"text\":\"$updates\", \"alt\":\"$alt\", \"tooltip\":\"$tooltip\" }"
228+
exit 0
229+
fi
230+
148231
# Check for network connectivity before proceeding
149232
if check_network_connectivity; then
150233

@@ -177,7 +260,8 @@ function main() {
177260
var_setter
178261
else
179262
# Update check failed
180-
alt="error"
263+
updates=$(cat "$STATE_FILE")
264+
var_setter
181265
tooltip="Update check failed"
182266
fi
183267
else

0 commit comments

Comments
 (0)