Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
#Quick script to shutdown a laptop when AC power is no longer being supplied and the battery is low. Can optionally send an alert out via Pushover or email (Need a functioning mail server for email) Tested on Proxmox VE. Needs the following packages installed on the target server: powermgmt-base, curl, util-linux
#!/bin/bash
#Quick script to shutdown a laptop when AC power is no longer being supplied and the battery is low.
#Can optionally send an alert out via Pushover or email (Need a functioning mail server for this)
#Tested on Proxmox VE. Needs the following packages installed on the target server: powermgmt-base curl util-linux
#Set alerting method (pushover/email/off)
#a value of 'off' here will disable all alerts
#Alerting method
ALERT_METHOD=''
#Critical battery threshold. Sets the capacity value where the battery is considered to be critically low
#Value is read from /sys/class/power_supply/BAT0/capacity
CRITICAL_BATTERY_THRESHOLD=20
#Pushover credentials
PUSHOVER_USER_TOKEN=""
PUSHOVER_API_TOKEN=""
#Settings for email alerts
ALERT_EMAIL_RECIPIENT=""
function shutdown_server () {
#echo "shutdown_server() called"
#Runs commands for shutting down the server
/usr/sbin/shutdown -h now
}
function send_alert () {
#Handles sending out of alerts via email or pushover
#echo "send_alert() called"
local CURRENT_DATETIME=`date +%F\ %H:%M:%S`
local ALERT_MESSAGE="${SYSTEM_HOSTNAME} - ${CURRENT_DATETIME} ALERT: battery is low and mains power is not present. will shut down soon if ac power is not restored"
if [[ $ALERT_METHOD == 'pushover' ]]; then
/usr/bin/curl -q -s \
-F "token=${PUSHOVER_API_TOKEN}" \
-F "user=${PUSHOVER_USER_TOKEN}" \
--form-string "message=${ALERT_MESSAGE}" \
https://api.pushover.net/1/messages.json
fi
if [[ $ALERT_METHOD == 'email' ]]; then
echo $ALERT_MESSAGE | mail -s "Power Loss Alert" $ALERT_EMAIL_RECIPIENT
fi
#check the alert has been sent ok. if it has then create the lock file so we don't send out anymore alerts
# until the event has cleared. Only set if the previous alert was sent ok
if [ $? -eq 0 ]; then
touch /tmp/.alert-sent
return 0
fi
}
#Grab the hostname
SYSTEM_HOSTNAME=`cat /etc/hostname`
#BATTERY_ALARM=`cat /sys/class/power_supply/BAT0/alarm`
BATTERY_CAPACITY=`cat /sys/class/power_supply/BAT0/capacity`
#Check whether ac power is being applied
# Store the return value in a variable (0 means ac power is applied, 1 means it isn't)
/usr/sbin/on_ac_power
AC_POWER_STATE=$?
#Delete the lock file to re-enable sending of alerts if it exists and everything is ok
# By ok, we mean that AC power is applied
if [ $AC_POWER_STATE -eq 0 ] && [ -f /tmp/.alert-sent ]; then
rm /tmp/.alert-sent
fi
# if no ac power and battery very low
if [ $AC_POWER_STATE -eq 1 ] && [ $BATTERY_CAPACITY -le $CRITICAL_BATTERY_THRESHOLD ]; then
#check for ac power again. If ac power still isn't being applied then
#Send alert via pushover. don't send an alert if the lock file exists
sleep 2 #Wait for a bit to rule out any brief mains power losses
#get the current state of the AC power supply again
/usr/sbin/on_ac_power
AC_POWER_STATE=$?
#Still no AC power yet. Send an alert (if enabled) as we haven't done already and shutdown the server
if [ ! -f /tmp/.alert-sent ] && [ $AC_POWER_STATE -eq 1 ]; then
if [[ $ALERT_METHOD != 'off' ]]; then #Send an alert if enabled
send_alert
fi
#Shutdown the server
shutdown_server
fi
fi
@cybermaus
Copy link

cybermaus commented Mar 25, 2022

Possibly I am lacked a lot of obvious base skills on proxmox that I should be having. But please tell me, where to put this shell, how to get it triggered automatically?

Also, does the shutdown -h now actually informs the client machines they too need to shutdown gracefully? I do have QEMU agents installed and active.

@peterlavelle
Copy link
Author

peterlavelle commented Mar 25, 2022

Hi @cybermaus

I currently have this in a cron job running once per minute as the root user.

Example cron job I have to do this currently can be found below. I added this under the root user by running crontab -e while logged in as root on the Proxmox server

*/1 * * * * /path/to/script/autoshutdown.sh

There's a nice guide to using cron under linux to schedule tasks here

Defining the scheduling for cron jobs can be a bit hard to understand at first (I still find I have to look it up sometimes, myself!) so hopefully the link here will be of some help.

The shutdown -h now command should shutdown containers/VM's running on the Proxmox instance and wait until all of them have shutdown cleanly before shutting down the Proxmox server itself, but I admit its not the cleanest way of doing this.

If you need it to run a different set of commands when it's shutting down the Proxmox server, you should be able to add them to the shutdown_server () function of the script.

@cybermaus
Copy link

cybermaus commented Mar 26, 2022

Ok, a simple cron job. I was thinking/hoping it was some interrupt driven script, so it would pick up immediately.
Given that my old pair of laptops have about 10 seconds battery life left, I would have to run the cron job rather often.
And I do not really feel like buying new batteries.

Thanks for the prompt response.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment