Skip to content

Commit

Permalink
Add autosuspend conf and scripts (from Dustin Nguyen and Florian Schm…
Browse files Browse the repository at this point in the history
…aus)
  • Loading branch information
thelazt committed Oct 24, 2022
1 parent 28e37dd commit 45dc7ba
Show file tree
Hide file tree
Showing 12 changed files with 255 additions and 0 deletions.
41 changes: 41 additions & 0 deletions autosuspend/autosuspend.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
[general]
interval = 120
idle_time = 900
suspend_cmd = /etc/autosuspend/suspend
wakeup_cmd = /etc/autosuspend/wakeup {timestamp:.0f}
woke_up_file = /var/run/autosuspend-just-woke-up
lock_file = /var/lock/autosuspend.lock
lock_timeout = 30
# Can be used to call a command before suspending, either with scheduled wake up or not.
# notify_cmd_wakeup = su myuser -c notify-send -a autosuspend 'Suspending the system. Wake up at {iso}'
# notify_cmd_no_wakeup = su myuser -c notify-send -a autosuspend 'Suspending the system.'

[check.LogindSessionsIdle]
enabled = true

# Incoming SSH connections also prevent automatic suspension of the
# system.
[check.ActiveConnection]
enabled = true
ports = 22

[check.ExternalCommand]
enabled = true
command = /etc/autosuspend/activity-check

# Do not interrupt run-fai with a suspend
[check.RunFai]
enabled = true
class = Processes
processes = fai

[wakeup.RunFai]
# check when the next run of run-fai.service is scheduled and set an apropriate wakeup-time
enabled = true
class = Command
command = /etc/autosuspend/wakeup-run-fai

[wakeup.BeforeScheduledReboot]
enabled = true
class = Command
command = /etc/autosuspend/wakeup-before-scheduled-reboot
32 changes: 32 additions & 0 deletions autosuspend/scripts/activity-check
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
#!/usr/bin/env bash

ACTIVITY_CHECK_DIR=/etc/autosuspend/activity-check.d

if [[ ! -d "${ACTIVITY_CHECK_DIR}" ]]; then
# autosuspend assumes that the system is active if the exit status
# is zero, or inactive otherwise. If there is no
# ACTIVITY_CHECK_DIR, then the system is assumed to be inactive,
# hence we return 1 here.
exit 1
fi

shopt -s nullglob
for FILE in "${ACTIVITY_CHECK_DIR}"/*; do
if [[ ! -x "${FILE}" ]]; then
continue
fi

if [[ "${FILE}" == *.pre_fcopy ]]; then
continue
fi

if "${FILE}"; then
# Executing FILE returned a zero exit status, that means the
# system is active and we do not need to check more scripts.
exit
fi
done

# No script signalled that the system is active. Return a non-zero
# value to signal that it is inactive.
exit 1
22 changes: 22 additions & 0 deletions autosuspend/scripts/activity-check.d/inhibit-autosuspend-flag-file
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
#!/usr/bin/env bash
set -euo pipefail

readonly INHIBIT_AUTOSUSPEND_FLAG_FILE="/var/tmp/inhibit-autosuspend"

if [[ ! -f "${INHIBIT_AUTOSUSPEND_FLAG_FILE}" ]]; then
exit 1
fi

FLAG_FILE_LAST_MODIFICATION=$(stat -c "%Y" "${INHIBIT_AUTOSUSPEND_FLAG_FILE}")
NOW=$(date +"%S")

FLAG_FILE_AGE_SECONDS=$(( ${NOW} - ${FLAG_FILE_LAST_MODIFICATION} ))

if [[ ${FLAG_FILE_AGE_SECONDS} -gt 259200 ]]; then
echo "${INHIBIT_AUTOSUSPEND_FLAG_FILE} was last touched three days ago. Going to remove and ignore the file"
rm "${INHIBIT_AUTOSUSPEND_FLAG_FILE}"
exit 1
fi

echo "${INHIBIT_AUTOSUSPEND_FLAG_FILE} found, signalling that the system is active"
exit 0
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
#!/usr/bin/env bash
set -euo pipefail

readonly INHIBIT_AUTOSUSPEND_FLAG_FILE="/var/tmp/inhibit-autosuspend"

if [[ ! -f "${INHIBIT_AUTOSUSPEND_FLAG_FILE}" ]]; then
exit 1
fi

FLAG_FILE_LAST_MODIFICATION=$(stat -c "%Y" "${INHIBIT_AUTOSUSPEND_FLAG_FILE}")
NOW=$(date +"%S")

FLAG_FILE_AGE_SECONDS=$(( ${NOW} - ${FLAG_FILE_LAST_MODIFICATION} ))

if [[ ${FLAG_FILE_AGE_SECONDS} -gt 4320 ]]; then
echo "${INHIBIT_AUTOSUSPEND_FLAG_FILE} was last touched three days ago. Going to remove and ignore the file"
rm "${INHIBIT_AUTOSUSPEND_FLAG_FILE}"
exit 1
fi

echo "${INHIBIT_AUTOSUSPEND_FLAG_FILE} found, signalling that the system is active"
exit 0
25 changes: 25 additions & 0 deletions autosuspend/scripts/activity-check.d/logind-idle-hint
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
#!/usr/bin/env bash
set -euo pipefail

# Although autosuspend's LogindSessionsIdle should check the IdleHint,
# this appears to be, at least sometimes, not reliable. I suspect it
# may because autosuspend uses
# if not properties["IdleHint"]:
# return "Login session {} is not idle".format(session_id)
# https://github.com/languitar/autosuspend/blob/c7f06a27db37f2a4ed04b596427da52fd1192935/src/autosuspend/checks/systemd.py#L112-L113
# which does not check if the value of IdleHint is 'true' or
# 'false'. Until autosuspend's LogindSessionsIdle check is reliable,
# we use the little script below to see if there is a session with
# IdleHint=no.
# See https://github.com/languitar/autosuspend/pull/225

for SESSION_ID in $(loginctl list-sessions --no-legend | awk '{ print $1 }'); do
IDLE_HINT=$(loginctl show-session $SESSION_ID -P IdleHint)

if [[ "${IDLE_HINT}" == no ]]; then
echo "Session $SESSION_ID is not idle"
exit 0
fi
done

exit 1
26 changes: 26 additions & 0 deletions autosuspend/scripts/activity-check.d/logind-idle-hint.pre_fcopy
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
#!/usr/bin/env bash
set -euo pipefail

# Although autosuspend's LogindSessionsIdle should check the IdleHint,
# this appears to be, at least sometimes, not reliable. I suspect it
# may because autosuspend uses
# if not properties["IdleHint"]:
# return "Login session {} is not idle".format(session_id)
# https://github.com/languitar/autosuspend/blob/c7f06a27db37f2a4ed04b596427da52fd1192935/src/autosuspend/checks/systemd.py#L112-L113
# which does not check if the value of IdleHint is 'true' or
# 'false'. Until autosuspend's LogindSessionsIdle check is reliable,
# we use the little script below to see if there is a session with
# IdleHint=no.
# See https://github.com/languitar/autosuspend/pull/225

for SESSION_ID in $(loginctl list-sessions --no-legend | awk '{ print $1 }'); do
IDLE_HINT=$(loginctl show-session $SESSION_ID -p IdleHint)
IDLE_HINT="${IDLE_HINT#IdleHint=}"

if [[ "${IDLE_HINT}" == no ]]; then
echo "Session $SESSION_ID is not idle"
exit 0
fi
done

exit 1
28 changes: 28 additions & 0 deletions autosuspend/scripts/activity-check.pre_fcopy
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
#!/usr/bin/env bash

ACTIVITY_CHECK_DIR=/etc/autosuspend/activity-check.d

if [[ ! -d "${ACTIVITY_CHECK_DIR}" ]]; then
# autosuspend assumes that the system is active if the exit status
# is zero, or inactive otherwise. If there is no
# ACTIVITY_CHECK_DIR, then the system is assumed to be inactive,
# hence we return 1 here.
exit 1
fi

shopt -s nullglob
for FILE in "${ACTIVITY_CHECK_DIR}"/*; do
if [[ ! -x "${FILE}" ]]; then
continue
fi

if "${FILE}"; then
# Executing FILE returned a zero exit status, that means the
# system is active and we do not need to check more scripts.
exit
fi
done

# No script signalled that the system is active. Return a non-zero
# value to signal that it is inactive.
exit 1
3 changes: 3 additions & 0 deletions autosuspend/scripts/suspend
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
#!/usr/bin/env bash

exec /bin/systemctl suspend
10 changes: 10 additions & 0 deletions autosuspend/scripts/wakeup
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
#!/usr/bin/env bash

TIMESTAMP="${1}"

readonly WAKEALARM="/sys/class/rtc/rtc0/wakealarm"

# One has to write '0' to the pseudo file before setting a new alarm
# time.
echo 0 > "${WAKEALARM}"
echo "${TIMESTAMP}" > "${WAKEALARM}"
21 changes: 21 additions & 0 deletions autosuspend/scripts/wakeup-before-scheduled-reboot
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
#!/usr/bin/env bash
set -eou pipefail

# Although this file is called wakeup-before-scheduled-reboot we
# actually check for the next scheduled reboot *or* shutdown. But this
# does not really matter, as we want to wakeup in both cases and we
# only schedule reboots.
SCHEDULED_SHUTDOWN_INFO=$(busctl get-property org.freedesktop.login1 /org/freedesktop/login1 org.freedesktop.login1.Manager ScheduledShutdown)

declare -i SCHEDULED_SHUTDOWN_SECS
SCHEDULED_SHUTDOWN_SECS=$(echo "${SCHEDULED_SHUTDOWN_INFO}" | cut -d ' ' -f 3)

if [[ ${SCHEDULED_SHUTDOWN_SECS} -eq 0 ]]; then
# Output nothing to make autosuspend happy.
echo ""
exit
fi

BEFORE_SCHEDULED_SHUTDOWN_SECS=$(( SCHEDULED_SHUTDOWN_SECS - 180 ))

echo "${BEFORE_SCHEDULED_SHUTDOWN_SECS}"
17 changes: 17 additions & 0 deletions autosuspend/scripts/wakeup-run-fai
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
#!/usr/bin/env bash
set -eou pipefail

export LANG=C
export LC_TIME=C

NEXT_FAI_RUN_AT=$(systemctl show run-fai.timer --property=NextElapseUSecRealtime --value | cut -d' ' -f 2-)

declare -i NEXT_FAI_RUN_AT_EPOCH_SECS
NEXT_FAI_RUN_AT_EPOCH_SECS=$(date -d "${NEXT_FAI_RUN_AT}" +%s)

declare -i ADD_DAYS=3
declare -i EXTRA_SECS=$(( ADD_DAYS * 24 * 60 * 60 ))

declare -i WAKEUP_EPOCH_SECS=$(( NEXT_FAI_RUN_AT_EPOCH_SECS + EXTRA_SECS ))

echo "${WAKEUP_EPOCH_SECS}"
8 changes: 8 additions & 0 deletions autosuspend/scripts/wakeup-run-fai.pre_fcopy
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
#!/usr/bin/env bash

export LANG=C
export LC_TIME=C

NEXT_FAI_RUN_AT=$(systemctl show run-fai.timer --property=NextElapseUSecRealtime --value | cut -d' ' -f 2-)

date -d "${NEXT_FAI_RUN_AT}" +%s

0 comments on commit 45dc7ba

Please sign in to comment.