Aktiver dvale efter X minutters inaktivitet


Source: Download script

Last Updated: 13. December 2024 by Sune Koch Hansen (sune@kvalitetsit.dk)

Parameters:

Navn Type Standardværdi Påkrævet
Click to see the source code
#! /usr/bin/env sh

# DESCRIPTION
#
# This script will log out the user and suspend the PC after a given period of inactivity.
# A configurable warning is shown before the user is logged out and the pc suspended.
#
# The script will also suspend the PC after the same period of inactivity on the login screen.
# This second part of the script requires "lightdm_greeter_setup_scripts" to be run and enabled to take effect
#
# The script is designed to wake up the PC 1 minute before a potential scheduled shutdown (on/off-schedule)
# so that it can be shut down as planned.
# If no scheduled shutdown exists, it will suspend the PC until it is woken manually.
#
# This script and "inactivity_logout_after_time.sh" are mutually exclusive, and each of them
# are written to overwrite each other, so whichever was the last of them run takes effect.
#
# PARAMETERS
# 1. Checkbox. Enables/disables the script.
# 2. Integer. How many minutes to wait before showing the warning dialog
# 3. Integer. How many minutes to wait before logging out and suspending
# 4. String. (optional) The text to be shown in the warning dialog. If no input is given, a default is used
# 5. String. (optional) The text to be shown on the dialog button. If no input is given, a default is used

set -x

ENABLE=$1
DIALOG_TIME_MINS=$2
LOGOUT_TIME_MINS=$3
DIALOG_TEXT=$4
BUTTON_TEXT=$5

# Note: Currently these logs are never rotated, so they'll grow and grow
SUSPEND_SCRIPT="/usr/share/os2borgerpc/bin/inactive_logout.sh"
SUSPEND_SCRIPT_LOG="/usr/share/os2borgerpc/bin/inactive_logout.log"
LIGHTDM_SUSPEND_SCRIPT="/etc/lightdm/greeter-setup-scripts/suspend_after_time.sh"
LIGHTDM_SUSPEND_SCRIPT_LOG="/etc/lightdm/scriptlogs/suspend_after_time.log"
LIGHTDM_GREETER_SETUP_SCRIPT="/etc/lightdm/greeter_setup_script.sh"
LIGHTDM_GREETER_SCRIPTS_DIR="/etc/lightdm/greeter-setup-scripts"

# Stop Debconf from interrupting when interacting with the package system
export DEBIAN_FRONTEND=noninteractive

error() {
  echo "$1"
  exit 1
}

if get_os2borgerpc_config os2_product | grep --quiet kiosk; then
  error "Dette script er ikke designet til at blive anvendt på en kiosk-maskine."
fi

# Handle deactivating inactivity suspend
if [ "$ENABLE" = "False" ]; then
  rm --force $SUSPEND_SCRIPT $LIGHTDM_SUSPEND_SCRIPT $SUSPEND_SCRIPT_LOG $LIGHTDM_SUSPEND_SCRIPT_LOG
  OLDCRON="/tmp/oldcron"
  crontab -l > $OLDCRON
  if [ -f "$OLDCRON" ]; then
    sed --in-place "\@$SUSPEND_SCRIPT@d" $OLDCRON
    crontab $OLDCRON
    rm --force $OLDCRON
  fi
  exit
fi

[ -z "$DIALOG_TIME_MINS" ] && error 'Please insert the time the user has to be inactive before dialog is shown.'
[ -z "$LOGOUT_TIME_MINS" ] && error 'Please insert the time the user has to be inactive before being logged out.'
[ "$DIALOG_TIME_MINS" -gt "$LOGOUT_TIME_MINS" ] && error 'Dialog time is greater than logout time and dialog will therefore not be shown. Edit dialog time!'
[ -z "$DIALOG_TEXT" ] && DIALOG_TEXT="Du er inaktiv og bliver logget ud om kort tid..."
[ -z "$BUTTON_TEXT" ] && BUTTON_TEXT="OK"

# xprintidle uses milliseconds, so convert the user inputted minutes to that
LOGOUT_TIME_MS=$(( LOGOUT_TIME_MINS * 60 * 1000 ))
DIALOG_TIME_MS=$(( DIALOG_TIME_MINS * 60 * 1000 ))

# Older versions of this script used sh, but our lightdm suspend script uses
# bash specifics. Change it to run the script directly with whatever interpreter it has.
# This requires ensuring that lightdm has execute permissions on all those scripts.
chmod --recursive 700 $LIGHTDM_GREETER_SCRIPTS_DIR
cat << EOF > $LIGHTDM_GREETER_SETUP_SCRIPT
#!/bin/sh
greeter_setup_scripts=\$(find $LIGHTDM_GREETER_SCRIPTS_DIR -mindepth 1)
for file in \$greeter_setup_scripts
do
    ./"\$file" &
done
EOF

chmod 700 $LIGHTDM_GREETER_SETUP_SCRIPT

mkdir --parents "$(dirname $LIGHTDM_SUSPEND_SCRIPT)" "$(dirname $SUSPEND_SCRIPT_LOG)"

TIMEOUT_SECS=$((LOGOUT_TIME_MINS * 60))

cat << EOF > "$LIGHTDM_SUSPEND_SCRIPT"
#!/usr/bin/env bash

LOG=$LIGHTDM_SUSPEND_SCRIPT_LOG

while :
do
  echo "Starting sleep for $TIMEOUT_SECS seconds" >> \$LOG
  sleep $TIMEOUT_SECS
  echo "Sleep over" >> \$LOG
  if [ -z \$(users) ]; then
    echo "no active users, suspending" >> \$LOG
    # If the pc has a time plan, don't use systemctl suspend, but instead rtcwake -m mem,
    # which is functionally the same and allows the machine to wake up in time to be shut down
    # by the time plan
    re="([0-9]+) ([0-9]+) ([0-9]+) ([0-9]+) .+"
    if [[ \$(crontab -l | grep scheduled_off) =~ \$re ]]; then
      MINUTES=\${BASH_REMATCH[1]}
      HOURS=\${BASH_REMATCH[2]}
      DAY=\${BASH_REMATCH[3]}
      MONTH=\${BASH_REMATCH[4]}
      YEAR=\$(date +%Y)
      # wake up 1 minute before shut down
      MINM1P60=\$(( \$(( MINUTES - 1)) + 60))
      # Rounding minutes
      MINS=\$(( MINM1P60 % 60))
      HRCORR=\$(( 1 - \$(( MINM1P60 / 60))))
      HRS=\$(( HOURS - HRCORR))
      HRS=\$(( \$(( HRS + 24)) % 24))
      rtcwake -m mem --date "\$YEAR-\$MONTH-\$DAY \$HRS:\$MINS"
    else
      systemctl suspend
    fi
  else
    echo "should be logged in as \$(users) breaking loop" >> \$LOG
    break
  fi
done

echo "exited loop" >> \$LOG
exit 0
EOF

chmod 700 $LIGHTDM_SUSPEND_SCRIPT

# Install xprintidle
apt-get update --assume-yes

# Only try installing if it isn't already as otherwise it will exit with nonzero
# and stop the script
if ! dpkg --get-selections | grep -v deinstall | grep --quiet xprintidle; then
  if ! apt-get install --assume-yes xprintidle; then
    # apt install could fail due to debian frontend lock being unavailable
    # during automatic updates
    error "apt failed to install xprintidle"
  fi
fi

# if line already added to crontab: skip
if ! crontab -l | grep "$SUSPEND_SCRIPT"; then
	line="* * * * * $SUSPEND_SCRIPT"
	(crontab -l -u root; echo "$line") | crontab -u root -
fi

# New auto_logout file, running as root
cat <<- EOF > $SUSPEND_SCRIPT
	#!/usr/bin/env bash

	# If the user is inactive for too long, a dialog will appear, warning the user that the session will end.
	# If the user do not touch the mouse or press any keyboard key the session will end.
	# Only have one dialog at a time, so remove preexisting ones.
	# Create a new message every time, in case someone didn't close it but
	# just put e.g. a browser in front, to ensure they or someone else gets a
	# new warning when/if inactivity is reached again

	USER_DISPLAY=\$(who | grep -w 'user' | sed -rn 's/.*(:[0-9]*).*/\1/p')

	# These are used by xprintidle
	export XAUTHORITY=/home/user/.Xauthority
	export DISPLAY=\$USER_DISPLAY
	su - user -c "DISPLAY=\$USER_DISPLAY xhost +localhost"

	LOG=$SUSPEND_SCRIPT_LOG

	echo $LOGOUT_TIME_MS \$(xprintidle) >> \$LOG

	# If the pc has a time plan, don't use systemctl suspend, but instead rtcwake -m mem,
	# which is functionally the same and allows the machine to wake up in time to be shut down
	# by the time plan

	if [ \$(xprintidle) -ge $LOGOUT_TIME_MS ]; then
	  echo 'Logging user out' >> \$LOG
	  pkill -KILL -u user
	  echo 'suspending pc' >> \$LOG
	  # If the pc has a time plan, don't use systemctl suspend, but instead rtcwake -m mem,
	  # which is functionally the same and allows the machine to wake up in time to be shut down
	  # by the time plan
	  re="([0-9]+) ([0-9]+) ([0-9]+) ([0-9]+) .+"
	  if [[ \$(crontab -l | grep scheduled_off) =~ \$re ]]; then
	    MINUTES=\${BASH_REMATCH[1]}
	    HOURS=\${BASH_REMATCH[2]}
	    DAY=\${BASH_REMATCH[3]}
	    MONTH=\${BASH_REMATCH[4]}
	    YEAR=\$(date +%Y)
	    # wake up 1 minute before shut down
	    MINM1P60=\$(( \$(( MINUTES - 1)) + 60))
	    # Rounding minutes
	    MINS=\$(( MINM1P60 % 60))
	    HRCORR=\$(( 1 - \$(( MINM1P60 / 60))))
	    HRS=\$(( HOURS - HRCORR))
	    HRS=\$(( \$(( HRS + 24)) % 24))
	    # When run from the crontab, rtcwake needs the full path for some reason or it won't work
	    /usr/sbin/rtcwake -m mem --date "\$YEAR-\$MONTH-\$DAY \$HRS:\$MINS"
	  else
	    systemctl suspend
	  fi
	  exit 0
	fi
	# if idle time is past the dialog time: show the dialog
	if [ \$(xprintidle) -ge $DIALOG_TIME_MS ]; then
	  # Do spare the poor lives of potential other zenity windows.
	  PID_ZENITY="\$(pgrep --full 'Inaktivitet')"
	  if [ -n \$PID_ZENITY ]; then
	    kill \$PID_ZENITY
	  fi
	  # echo 'Running zenity...' >> \$LOG
	  # We use the --title to match against above
	  zenity --warning --text="$DIALOG_TEXT" --ok-label="$BUTTON_TEXT" --no-wrap --display=\$USER_DISPLAY --title "Inaktivitet"
	fi
EOF

chmod 700 $SUSPEND_SCRIPT

Beskrivelse

Vis en advarsel efter et antal minutters inaktivitet - ved fortsat inaktivitet logges brugeren automatisk ud og maskinen går i dvale.

BEMÆRK: USB-overvågning kan ikke være aktiv, mens en computer er i dvale. Vi anbefaler derfor ikke at anvende scriptet på computere, der står uden opsyn, medmindre man benytter de bure, der forhindrer borgere i at tilgå USB-enhederne.

YDERLIGERE BEMÆRKNING: Computere kan ikke tjekke ind på admin-sitet eller køre scripts, mens de er i dvale, og kan derfor komme til at stå som værende offline.

Parametre

Scriptet tager 5 inputparametre:

  1. Aktiver/deaktiver scriptet. Sæt hak i boksen for at aktivere scriptet og lad den stå tom for at deaktivere det.
  2. Antal MINUTTER computeren kan være inaktiv, før en advarsel vises.
  3. Antal MINUTTER computeren kan være inaktiv, før den lukkes ned. Det skal være længere tid end det første inputparameter, da advarslen ellers ikke vil blive set. Vi foreslår minimum 3 minutter længere.
  4. Teksten der vises i inaktivitetsadvarslen. Hvis feltet efterlades tomt bruges standardteksten “Du er inaktiv og logges ud om kort tid..”
  5. Teksten der vises på knappen i inaktivitetsadvarslen. Hvis feltet efterlades tomt bruges standardteksten “OK”.

Eksempel: Med inputparametrene 5 og 10 vil der vises en advarsel efter 5 minutter, og hvis inaktiviteten så fortsætter 5 minutter derefter, vil brugeren blive logget af, og maskinen vil gå i dvale.

Hvis du ønsker linieskift i teksten, kan det gøres ved at skrive \n således: Linie1\nLinie2

Vi anbefaler at genstarte efter kørsel, for at være sikker på, det har taget effekt.

Dette script er blevet testet og virker på Ubuntu 22.04.