Skip to content

Commit ac408c6

Browse files
author
Marcus Funch
committed
Merge branch 'feature/52846_script_to_suspend_pc' into 'master'
Script to auto-suspend after time See merge request os2borgerpc/os2borgerpc-scripts!143
2 parents d5190ed + ea598a2 commit ac408c6

5 files changed

+364
-167
lines changed

os2borgerpc/login/lightdm_greeter_setup_scripts.sh

+1-1
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ cat << EOF > "$LIGHTDM_DIR"/greeter_setup_script.sh
3535
if [ \$(ls -A "$SCRIPT_DIR"/) ]; then
3636
for file in "$SCRIPT_DIR"/*
3737
do
38-
sh "\$file"
38+
bash "\$file" &
3939
done
4040
fi
4141
EOF
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
#! /usr/bin/env sh
2+
3+
# This script and "inactivity_suspend_after_time.sh" are mutually exclusive, and each of them
4+
# are written to overwrite each other, so whichever was the last of them run takes effect.
5+
6+
# PARAMETERS
7+
# 1. Checkbox. Enables/disables the script.
8+
# 2. Integer. How many minutes to wait before showing the warning dialog
9+
# 3. Integer. How many minutes to wait before logging out
10+
# 4. String. (optional) The text to be shown in the warning dialog. If no input is given, a default is used
11+
# 5. String. (optional) The text to be shown on the dialog button. If no input is given, a default is used
12+
13+
set -x
14+
15+
ENABLE=$1
16+
DIALOG_TIME_MINS=$2
17+
LOGOUT_TIME_MINS=$3
18+
DIALOG_TEXT=$4
19+
BUTTON_TEXT=$5
20+
21+
# Note: Currently this log is never rotated, so it'll grow and grow
22+
INACTIVITY_SCRIPT="/usr/share/os2borgerpc/bin/inactive_logout.sh"
23+
INACTIVITY_SCRIPT_LOG="/usr/share/os2borgerpc/bin/inactive_logout.log"
24+
LIGHTDM_SCRIPT="/etc/lightdm/greeter-setup-scripts/suspend_after_time.sh"
25+
26+
# Stop Debconf from interrupting when interacting with the package system
27+
export DEBIAN_FRONTEND=noninteractive
28+
29+
error() {
30+
echo "$1"
31+
exit 1
32+
}
33+
34+
# If this is run after inactivity_suspend_after_time, ensure the suspend script
35+
# hasn't left files behind
36+
rm --force $LIGHTDM_SCRIPT
37+
38+
# Handle deactivating inactivity logout
39+
if [ "$ENABLE" = "False" ]; then
40+
rm --force $INACTIVITY_SCRIPT $INACTIVITY_SCRIPT_LOG
41+
OLDCRON="/tmp/oldcron"
42+
crontab -l > $OLDCRON
43+
if [ -f "$OLDCRON" ]; then
44+
sed --in-place "\@$INACTIVITY_SCRIPT@d" $OLDCRON
45+
crontab $OLDCRON
46+
rm --force $OLDCRON
47+
fi
48+
exit
49+
fi
50+
51+
[ -z "$DIALOG_TIME_MINS" ] && error 'Please insert the time the user has to be inactive before dialog is shown.'
52+
[ -z "$LOGOUT_TIME_MINS" ] && error 'Please insert the time the user has to be inactive before being logged out.'
53+
[ "$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!'
54+
[ -z "$DIALOG_TEXT" ] && DIALOG_TEXT="Du er inaktiv og bliver logget ud om kort tid..."
55+
[ -z "$BUTTON_TEXT" ] && BUTTON_TEXT="OK"
56+
57+
# xprintidle uses milliseconds, so convert the user inputted minutes to that
58+
LOGOUT_TIME_MS=$(( LOGOUT_TIME_MINS * 60 * 1000 ))
59+
DIALOG_TIME_MS=$(( DIALOG_TIME_MINS * 60 * 1000 ))
60+
61+
# Install xprintidle
62+
apt-get update --assume-yes
63+
64+
# Only try installing if it isn't already as otherwise it will exit with nonzero and stop the script
65+
if ! dpkg --get-selections | grep -v deinstall | grep --quiet xprintidle; then
66+
if ! apt-get install --assume-yes xprintidle; then
67+
# apt install could fail due to debian frontend lock being unavailable
68+
# during automatic updates
69+
error "apt failed to install xprintidle"
70+
fi
71+
fi
72+
73+
# if line already added to crontab: skip
74+
if ! crontab -l | grep "$INACTIVITY_SCRIPT"; then
75+
line="* * * * * $INACTIVITY_SCRIPT"
76+
(crontab -l -u root; echo "$line") | crontab -u root -
77+
fi
78+
79+
# New auto_logout file, running as root
80+
cat <<- EOF > $INACTIVITY_SCRIPT
81+
#! /usr/bin/env sh
82+
83+
# If the user is inactive for too long, a dialog will appear, warning the user that the session will end.
84+
# If the user do not touch the mouse or press any keyboard key the session will end.
85+
# Only have one dialog at a time, so remove preexisting ones.
86+
# Create a new message every time, in case someone didn't close it but
87+
# just put e.g. a browser in front, to ensure they or someone else gets a
88+
# new warning when/if inactivity is reached again
89+
90+
USER_DISPLAY=\$(who | grep -w 'user' | sed -rn 's/.*(:[0-9]*).*/\1/p')
91+
92+
# These are used by xprintidle
93+
export XAUTHORITY=/home/user/.Xauthority
94+
export DISPLAY=\$USER_DISPLAY
95+
su - user -c "DISPLAY=\$USER_DISPLAY xhost +localhost"
96+
97+
LOG=$INACTIVITY_SCRIPT_LOG
98+
99+
echo $LOGOUT_TIME_MS \$(xprintidle) >> \$LOG
100+
101+
if [ \$(xprintidle) -ge $LOGOUT_TIME_MS ]; then
102+
echo 'Logging user out' >> \$LOG
103+
pkill -KILL -u user
104+
exit 0
105+
fi
106+
# if idle time is past the dialog time: show the dialog
107+
if [ \$(xprintidle) -ge $DIALOG_TIME_MS ]; then
108+
# Do spare the poor lives of potential other zenity windows.
109+
PID_ZENITY="\$(pgrep --full 'Inaktivitet')"
110+
if [ -n \$PID_ZENITY ]; then
111+
kill \$PID_ZENITY
112+
fi
113+
# echo 'Running zenity...' >> \$LOG
114+
# We use the --title to match against above
115+
zenity --warning --text="$DIALOG_TEXT" --ok-label="$BUTTON_TEXT" --no-wrap --display=\$USER_DISPLAY --title "Inaktivitet"
116+
fi
117+
EOF
118+
119+
chmod +x $INACTIVITY_SCRIPT
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,219 @@
1+
#! /usr/bin/env sh
2+
3+
# DESCRIPTION
4+
#
5+
# This script will log out the user and suspend the PC after a given period of inactivity.
6+
# A configurable warning is shown before the user is logged out and the pc suspended.
7+
#
8+
# The script will also suspend the PC after the same period of inactivity on the login screen.
9+
# This second part of the script requires "lightdm_greeter_setup_scripts" to be run and enabled to take effect
10+
#
11+
# The script is designed to wake up the PC 1 minute before a potential scheduled shutdown (on/off-schedule)
12+
# so that it can be shut down as planned.
13+
# If no scheduled shutdown exists, it will suspend the PC until it is woken manually.
14+
#
15+
# This script and "inactivity_logout_after_time.sh" are mutually exclusive, and each of them
16+
# are written to overwrite each other, so whichever was the last of them run takes effect.
17+
#
18+
# PARAMETERS
19+
# 1. Checkbox. Enables/disables the script.
20+
# 2. Integer. How many minutes to wait before showing the warning dialog
21+
# 3. Integer. How many minutes to wait before logging out and suspending
22+
# 4. String. (optional) The text to be shown in the warning dialog. If no input is given, a default is used
23+
# 5. String. (optional) The text to be shown on the dialog button. If no input is given, a default is used
24+
25+
set -x
26+
27+
ENABLE=$1
28+
DIALOG_TIME_MINS=$2
29+
LOGOUT_TIME_MINS=$3
30+
DIALOG_TEXT=$4
31+
BUTTON_TEXT=$5
32+
33+
# Note: Currently these logs are never rotated, so they'll grow and grow
34+
SUSPEND_SCRIPT="/usr/share/os2borgerpc/bin/inactive_logout.sh"
35+
SUSPEND_SCRIPT_LOG="/usr/share/os2borgerpc/bin/inactive_logout.log"
36+
LIGHTDM_SUSPEND_SCRIPT="/etc/lightdm/greeter-setup-scripts/suspend_after_time.sh"
37+
LIGHTDM_SUSPEND_SCRIPT_LOG="/etc/lightdm/scriptlogs/suspend_after_time.log"
38+
LIGHTDM_GREETER_SETUP_SCRIPT="/etc/lightdm/greeter_setup_script.sh"
39+
40+
# Stop Debconf from interrupting when interacting with the package system
41+
export DEBIAN_FRONTEND=noninteractive
42+
43+
error() {
44+
echo "$1"
45+
exit 1
46+
}
47+
48+
if get_os2borgerpc_config os2_product | grep --quiet kiosk; then
49+
error "Dette script er ikke designet til at blive anvendt på en kiosk-maskine."
50+
fi
51+
52+
# Handle deactivating inactivity suspend
53+
if [ "$ENABLE" = "False" ]; then
54+
rm --force $SUSPEND_SCRIPT $LIGHTDM_SUSPEND_SCRIPT $SUSPEND_SCRIPT_LOG $LIGHTDM_SUSPEND_SCRIPT_LOG
55+
OLDCRON="/tmp/oldcron"
56+
crontab -l > $OLDCRON
57+
if [ -f "$OLDCRON" ]; then
58+
sed --in-place "\@$SUSPEND_SCRIPT@d" $OLDCRON
59+
crontab $OLDCRON
60+
rm --force $OLDCRON
61+
fi
62+
exit
63+
fi
64+
65+
[ -z "$DIALOG_TIME_MINS" ] && error 'Please insert the time the user has to be inactive before dialog is shown.'
66+
[ -z "$LOGOUT_TIME_MINS" ] && error 'Please insert the time the user has to be inactive before being logged out.'
67+
[ "$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!'
68+
[ -z "$DIALOG_TEXT" ] && DIALOG_TEXT="Du er inaktiv og bliver logget ud om kort tid..."
69+
[ -z "$BUTTON_TEXT" ] && BUTTON_TEXT="OK"
70+
71+
# xprintidle uses milliseconds, so convert the user inputted minutes to that
72+
LOGOUT_TIME_MS=$(( LOGOUT_TIME_MINS * 60 * 1000 ))
73+
DIALOG_TIME_MS=$(( DIALOG_TIME_MINS * 60 * 1000 ))
74+
75+
# Older versions of this script used sh, but our lightdm suspend script uses
76+
# bash specifics
77+
# The & after bash "$file" is necessary to prevent the lightdm suspend script from
78+
# blocking the login screen. It has to be escaped in sed
79+
# The spaces before sh and bash are necessary to prevent repeated runs of the script
80+
# from changing the file content to babash "$file" & & or similar
81+
if [ -f "$LIGHTDM_GREETER_SETUP_SCRIPT" ]; then
82+
# shellcheck disable=SC2016
83+
sed --in-place 's/ sh "$file"/ bash "$file" \&/' "$LIGHTDM_GREETER_SETUP_SCRIPT"
84+
fi
85+
86+
mkdir --parents "$(dirname $LIGHTDM_SUSPEND_SCRIPT)" "$(dirname $SUSPEND_SCRIPT_LOG)"
87+
88+
TIMEOUT_SECS=$((LOGOUT_TIME_MINS * 60))
89+
90+
cat << EOF > "$LIGHTDM_SUSPEND_SCRIPT"
91+
#!/usr/bin/env bash
92+
93+
LOG=$LIGHTDM_SUSPEND_SCRIPT_LOG
94+
95+
while :
96+
do
97+
echo "Starting sleep for $TIMEOUT_SECS seconds" >> \$LOG
98+
sleep $TIMEOUT_SECS
99+
echo "Sleep over" >> \$LOG
100+
if [ -z \$(users) ]; then
101+
echo "no active users, suspending" >> \$LOG
102+
# If the pc has a time plan, don't use systemctl suspend, but instead rtcwake -m mem,
103+
# which is functionally the same and allows the machine to wake up in time to be shut down
104+
# by the time plan
105+
re="([0-9]+) ([0-9]+) ([0-9]+) ([0-9]+) .+"
106+
if [[ \$(crontab -l | grep scheduled_off) =~ \$re ]]; then
107+
MINUTES=\${BASH_REMATCH[1]}
108+
HOURS=\${BASH_REMATCH[2]}
109+
DAY=\${BASH_REMATCH[3]}
110+
MONTH=\${BASH_REMATCH[4]}
111+
YEAR=\$(date +%Y)
112+
# wake up 1 minute before shut down
113+
MINM1P60=\$(( \$(( MINUTES - 1)) + 60))
114+
# Rounding minutes
115+
MINS=\$(( MINM1P60 % 60))
116+
HRCORR=\$(( 1 - \$(( MINM1P60 / 60))))
117+
HRS=\$(( HOURS - HRCORR))
118+
HRS=\$(( \$(( HRS + 24)) % 24))
119+
rtcwake -m mem --date "\$YEAR-\$MONTH-\$DAY \$HRS:\$MINS"
120+
else
121+
systemctl suspend
122+
fi
123+
else
124+
echo "should be logged in as \$(users) breaking loop" >> \$LOG
125+
break
126+
fi
127+
done
128+
129+
echo "exited loop" >> \$LOG
130+
exit 0
131+
EOF
132+
133+
# Install xprintidle
134+
apt-get update --assume-yes
135+
136+
# Only try installing if it isn't already as otherwise it will exit with nonzero
137+
# and stop the script
138+
if ! dpkg --get-selections | grep -v deinstall | grep --quiet xprintidle; then
139+
if ! apt-get install --assume-yes xprintidle; then
140+
# apt install could fail due to debian frontend lock being unavailable
141+
# during automatic updates
142+
error "apt failed to install xprintidle"
143+
fi
144+
fi
145+
146+
# if line already added to crontab: skip
147+
if ! crontab -l | grep "$SUSPEND_SCRIPT"; then
148+
line="* * * * * $SUSPEND_SCRIPT"
149+
(crontab -l -u root; echo "$line") | crontab -u root -
150+
fi
151+
152+
# New auto_logout file, running as root
153+
cat <<- EOF > $SUSPEND_SCRIPT
154+
#!/usr/bin/env bash
155+
156+
# If the user is inactive for too long, a dialog will appear, warning the user that the session will end.
157+
# If the user do not touch the mouse or press any keyboard key the session will end.
158+
# Only have one dialog at a time, so remove preexisting ones.
159+
# Create a new message every time, in case someone didn't close it but
160+
# just put e.g. a browser in front, to ensure they or someone else gets a
161+
# new warning when/if inactivity is reached again
162+
163+
USER_DISPLAY=\$(who | grep -w 'user' | sed -rn 's/.*(:[0-9]*).*/\1/p')
164+
165+
# These are used by xprintidle
166+
export XAUTHORITY=/home/user/.Xauthority
167+
export DISPLAY=\$USER_DISPLAY
168+
su - user -c "DISPLAY=\$USER_DISPLAY xhost +localhost"
169+
170+
LOG=$SUSPEND_SCRIPT_LOG
171+
172+
echo $LOGOUT_TIME_MS \$(xprintidle) >> \$LOG
173+
174+
# If the pc has a time plan, don't use systemctl suspend, but instead rtcwake -m mem,
175+
# which is functionally the same and allows the machine to wake up in time to be shut down
176+
# by the time plan
177+
178+
if [ \$(xprintidle) -ge $LOGOUT_TIME_MS ]; then
179+
echo 'Logging user out' >> \$LOG
180+
pkill -KILL -u user
181+
echo 'suspending pc' >> \$LOG
182+
# If the pc has a time plan, don't use systemctl suspend, but instead rtcwake -m mem,
183+
# which is functionally the same and allows the machine to wake up in time to be shut down
184+
# by the time plan
185+
re="([0-9]+) ([0-9]+) ([0-9]+) ([0-9]+) .+"
186+
if [[ \$(crontab -l | grep scheduled_off) =~ \$re ]]; then
187+
MINUTES=\${BASH_REMATCH[1]}
188+
HOURS=\${BASH_REMATCH[2]}
189+
DAY=\${BASH_REMATCH[3]}
190+
MONTH=\${BASH_REMATCH[4]}
191+
YEAR=\$(date +%Y)
192+
# wake up 1 minute before shut down
193+
MINM1P60=\$(( \$(( MINUTES - 1)) + 60))
194+
# Rounding minutes
195+
MINS=\$(( MINM1P60 % 60))
196+
HRCORR=\$(( 1 - \$(( MINM1P60 / 60))))
197+
HRS=\$(( HOURS - HRCORR))
198+
HRS=\$(( \$(( HRS + 24)) % 24))
199+
# When run from the crontab, rtcwake needs the full path for some reason or it won't work
200+
/usr/sbin/rtcwake -m mem --date "\$YEAR-\$MONTH-\$DAY \$HRS:\$MINS"
201+
else
202+
systemctl suspend
203+
fi
204+
exit 0
205+
fi
206+
# if idle time is past the dialog time: show the dialog
207+
if [ \$(xprintidle) -ge $DIALOG_TIME_MS ]; then
208+
# Do spare the poor lives of potential other zenity windows.
209+
PID_ZENITY="\$(pgrep --full 'Inaktivitet')"
210+
if [ -n \$PID_ZENITY ]; then
211+
kill \$PID_ZENITY
212+
fi
213+
# echo 'Running zenity...' >> \$LOG
214+
# We use the --title to match against above
215+
zenity --warning --text="$DIALOG_TEXT" --ok-label="$BUTTON_TEXT" --no-wrap --display=\$USER_DISPLAY --title "Inaktivitet"
216+
fi
217+
EOF
218+
219+
chmod +x $SUSPEND_SCRIPT

0 commit comments

Comments
 (0)