Skip to content

Instantly share code, notes, and snippets.

@seungjin
Created July 7, 2026 06:26
Show Gist options
  • Select an option

  • Save seungjin/da36bcffa5e6033c102215360fc74d2c to your computer and use it in GitHub Desktop.

Select an option

Save seungjin/da36bcffa5e6033c102215360fc74d2c to your computer and use it in GitHub Desktop.
do-not-sleep
#!/usr/bin/env bash
# Copyright (c) 2026 Seungjin Kim
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
# Use 2 hours as the default time window if no argument is provided
if [ -z "$1" ]; then
DURATION_INPUT="2h"
else
DURATION_INPUT="$1"
fi
# Help usage text
if [[ "$DURATION_INPUT" == "-h" || "$DURATION_INPUT" == "--help" ]]; then
echo "Usage: $(basename "$0") [duration]"
echo "Default is 2h if no duration is provided."
echo "Examples: $(basename "$0"), $(basename "$0") 1h, $(basename "$0") 45m"
exit 0
fi
# Convert human-readable time to total seconds
if [[ "$DURATION_INPUT" =~ ^[0-9]+$ ]]; then
SECONDS_TOTAL="$DURATION_INPUT"
DISPLAY_TIME="$DURATION_INPUT seconds"
else
UNIT="${DURATION_INPUT: -1}"
VALUE="${DURATION_INPUT::-1}"
case "$UNIT" in
s) SECONDS_TOTAL=$VALUE; DISPLAY_TIME="$VALUE seconds" ;;
m) SECONDS_TOTAL=$((VALUE * 60)); DISPLAY_TIME="$VALUE minutes" ;;
h) SECONDS_TOTAL=$((VALUE * 3600)); DISPLAY_TIME="$VALUE hours" ;;
d) SECONDS_TOTAL=$((VALUE * 86400)); DISPLAY_TIME="$VALUE days" ;;
*)
echo -e "\e[31mError: Unknown time unit '$UNIT'. Use s, m, h, or d.\e[0m"
exit 1
;;
esac
fi
# Calculate the precise end time
END_TIME=$(date -d "+$SECONDS_TOTAL seconds" "+%Y-%m-%d %H:%M:%S")
# Colors
CYAN="\e[1;36m"
NC="\e[0m" # No Color
echo -e "${CYAN}Keeping system awake for $DISPLAY_TIME ($SECONDS_TOTAL seconds)...${NC}"
echo -e "This program will end at: \e[32m$END_TIME\e[0m"
echo -e "\e[33mPress Ctrl+C to cancel early.\e[0m"
echo "----------------------------------------------------------------"
# The visual countdown function
run_countdown() {
local total=$1
local remaining=$1
# Braille loading spinner frames
local spinner=(⠋ ⠙ ⠹ ⠸ ⠼ ⠴ ⠦ ⠧ ⠇ ⠏)
local spin_idx=0
local bar_width=20
# Hide the cursor
printf "\e[?25l"
# Ensure the cursor is restored if the user hits Ctrl+C
trap 'printf "\e[?25h\n\e[0m"; exit' INT TERM
while [ $remaining -gt 0 ]; do
# 1. Determine dynamic color based on time remaining percentages
local pct=$(( remaining * 100 / total ))
local COLOR="\e[32m" # Green (Default: > 50% left)
if [ $pct -le 20 ]; then
COLOR="\e[1;31m" # Blinking/Bold Red (< 20% left)
elif [ $pct -le 50 ]; then
COLOR="\e[33m" # Yellow (< 50% left)
fi
# 2. Build the progress bar
local filled=$(( (remaining * bar_width) / total ))
local empty=$(( bar_width - filled ))
local bar_str=""
# Fill the remaining time with blocks, and already passed time with spaces (or dots)
for ((i=0; i<filled; i++)); do bar_str+="█"; done
for ((i=0; i<empty; i++)); do bar_str+="░"; done
# 3. Format the remaining clock string (HH:MM:SS)
local clock_str=$(printf "%02d:%02d:%02d" $((remaining/3600)) $((remaining%3600/60)) $((remaining%60)))
# 4. Render the whole line line dynamically
printf "\r${COLOR}%s\e[0m Time remaining: \e[1m%s\e[0m ${COLOR}[%s]\e[0m" \
"${spinner[spin_idx]}" "$clock_str" "$bar_str"
# Advance spinner frame and sleep
spin_idx=$(( (spin_idx + 1) % ${#spinner[@]} ))
sleep 1
: $((remaining--))
done
# Restore cursor and finish up
printf "\e[?25h"
echo -e "\r\e[32m✔ Finished! System is no longer inhibited.\e[0m"
}
# Run the systemd-inhibit wrapper around our custom countdown function
export -f run_countdown
systemd-inhibit --why="DO NOT SLEEP FOR $SECONDS_TOTAL SEC" --what=idle:sleep bash -c "run_countdown $SECONDS_TOTAL $SECONDS_TOTAL"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment