Manually block sleep and screen locking for N minutes

System inhibition (which is essentially what the PowerDevil “manually block” feature does) is pretty easy to script. Maybe all you need is a command to request inhibition for how long you want, and then have some UI button to trigger it?

The command systemd-inhibit allows you to inhibit idle sleep (or a few other power management conditions) while another command is running. The specific command you want to run is probably something like this:

systemd-inhibit --what=idle:sleep  sleep 300

Which means: run the command sleep 300 and inhibit the idle timer or the sleep feature until that command ends. The command sleep 300 means “wait 300 seconds and then exit”. If you run this, you can see the effect in the PowerDevil widget:

image

This is not very informative, but that is because we didn’t specify the details that PowerDevil wants to display - namely the “who”, “what”, and “why” flags for systemd-inhibit (see the explanation by typing man:systemd-inhibit in krunner or main menu), and there are other missing features that you may want, such as - triggering with a GUI, knowing how long until the timer runs out, etc.

So, for exercise, I made this little script (attached at the end) that manages the unsleeping time for you. I’ve set it up as a widget on the desktop using the 3rd-party Command Output widget (also get it from the “Get New Widgets” button in the widgets menu) and it works like this:

  1. Configure the display command:

  1. Configure the click action command:

Then, when not blocking, it just shows the text “Not blocking”:

image

Click on it and a dialog box opens:

image

After selecting something and clicking “OK”, it starts blocking and you get a count down:

image

Here is the script - save it in a directory in your path (for example ~/.bin or ~/.local/bin) as unsleep-time and give it “execute” permission:

#!/bin/bash -e

QUERY=
REMOVE=
ASK=
TIME_SPEC=
CLIARGS=( "" "$@" ) # OPTIND is 1 based
while [ "$OPTIND" -lt "${#CLIARGS[*]}" ]; do
	if getopts "rqh?" OPT; then
		case $OPT in
		h|\?) echo "$0 <-q|-r|TIME-SPEC>" >&2; exit 5;;
		q) QUERY=yes;;
		r) REMOVE=yes;;
		esac
	else
		TIME_SPEC="${CLIARGS[$OPTIND]}"
		OPTIND=$(( $OPTIND + 1 ))
	fi
done

if [ -n "$QUERY" ]; then
	pid="$(systemd-inhibit --list | awk '$1=="unsleep-time"{print$4}')"
	if [ -z "$pid" ]; then
		echo "Not blocking"
		exit 0
	fi
	running=$(ps h -p "$pid" -o etimes)
	sleep_for="$(ps h -p "$pid" -o cmd | awk '{print$NF}')"
	remaining=$(( sleep_for - running ))
	printf "Blocking for %dm %02ds\n" $(( remaining / 60 )) $(( remaining % 60 ))
elif [ -n "$REMOVE" ]; then
	pid="$(systemd-inhibit --list | awk '$1=="unsleep-time"{print$4}')"
	if [ -n "$pid" ]; then
		kill "$pid"
	fi
else
	if [ -z "$TIME_SPEC" ]; then
		if which kdialog 2>&1 >/dev/null; then
			TIME_SPEC="$(kdialog --slider "Inhibit idle sleep for how many minutes?" "1" "15" "1" || true)min"
		else
			TIME_SPEC="5min"
		fi
	fi
	until="$(date -d "$TIME_SPEC" +%s)"
	sleep_for=$(( $until - $(date +%s) ))
	systemd-inhibit --what=idle:sleep --who=unsleep-time --why="Unsleeping for $TIME_SPEC" sleep "$sleep_for"
fi

So, this is a bit heavy handed but I like bash scripting :grin: A more “plasmay” approach will be to just create a standalone widget that implements the functionality directly using the PowerDevil DBus API, but that is too much for me at this time of night…

2 Likes