#!/bin/bash # /lib/systemd/system-sleep/rtcwake # chmod a+rx AWAKE_TIME="01:23:45" # hour:minute:second GAP="10 seconds" # precision of awake time in date(1) format WAIT_TRIGGER='true' # test to go back to sleep when action is finished # typically pgrep on user or for specific process WAIT_TRIGGER_DELAY=60 # sleep duration in seconds between two tests with WAIT_TRIGGER MAX_TRIGGER=60 # don't go back to sleep if WAIT_TRIGGER isn't true # after WAIT_TRIGGER_DELAY * MAX_TRIGGER seconds LOG=/dev/null # same format than AWAKE_TIME but as an array of times in increase order #AWAKE_TIMES=("01:23:45" "02:46:00" "13:57:00" "20:00:00") #WAIT_TRIGGER_DELAYS=(60 60 60 60) #WAIT_TRIGGERS=("true" "true" "true" "true") #MAX_TRIGGERS=(60 60 60 60) #ON_ERRORS=() unset RTCWAKE_TIME AWAKE_TIME test -r $0.conf && source $0.conf # all previous variables can be set here echo -e "\n$(date) $1/$2" >> $LOG function set_RTCWAKE_TIME () { NOW=$(date +%_H%M%S) if test -z "$AWAKE_TIME"; then for ((i=0; i<${#AWAKE_TIMES[@]}; i++)); do echo "set_RTCWAKE_TIME: test $NOW -lt ${AWAKE_TIMES[i]//:}" >> $LOG if test $NOW -lt ${AWAKE_TIMES[i]//:}; then RTCWAKE_TIME=$(date +%s -d ${AWAKE_TIMES[i]}) echo "next wake up at ${AWAKE_TIMES[i]}" >> $LOG break elif test $i -eq $((${#AWAKE_TIMES[@]} - 1)); then RTCWAKE_TIME=$(date +%s -d "tomorrow ${AWAKE_TIMES[0]}") echo "next wake up tomorrow at ${AWAKE_TIMES[0]}" >> $LOG fi done else RTCWAKE_TIME=$([ $NOW -lt ${AWAKE_TIME//:} ] && date +%s -d $AWAKE_TIME || date +%s -d "tomorrow $AWAKE_TIME") fi suspend_duration=$(( $RTCWAKE_TIME - $(date +%s) )) date_awake=$(date -d "$suspend_duration seconds") echo "will be awaken in $suspend_duration seconds ($date_awake) (mode=$1)" >> $LOG rtcwake -m $1 -s $suspend_duration } case "$1/$2" in pre/suspend) set_RTCWAKE_TIME no ;; post/suspend) at -M now <<< "$0 post wait-for-trigger" > /dev/null 2>&1 ;; post/wait-for-trigger) NOW=$(date +%_H%M%S) if test -z "$AWAKE_TIME"; then for ((i=0; i<${#AWAKE_TIMES[@]}; i++)); do if test $NOW -ge ${AWAKE_TIMES[i]//:} -a $NOW -le $(date +%_H%M%S -d "${AWAKE_TIMES[i]} $GAP"); then AWAKE_TIME=${AWAKE_TIMES[i]} WAIT_TRIGGER_DELAY=${WAIT_TRIGGER_DELAYS[i]:-60} MAX_TRIGGER=${MAX_TRIGGERS[i]:-60} WAIT_TRIGGER=${WAIT_TRIGGERS[i]:-true} test -n "${ON_ERRORS[i]}" && ON_ERROR=${ON_ERRORS[i]} test -n "${AWAKE_ACTIONS[i]}" && AWAKE_ACTION=${AWAKE_ACTIONS[i]} break fi done fi test -n "$AWAKE_ACTION" && at -M now <<< $AWAKE_ACTION > $LOG 2>&1 if test -n "$AWAKE_TIME" && test $NOW -ge ${AWAKE_TIME//:} -a $NOW -le $(date +%_H%M%S -d "$AWAKE_TIME $GAP"); then cat >> $LOG << EOL NOW: $NOW AWAKE_TIME: $AWAKE_TIME WAIT_TRIGGER_DELAY: $WAIT_TRIGGER_DELAY WAIT_TRIGGER: $WAIT_TRIGGER MAX_TRIGGER: $MAX_TRIGGER EOL COUNT=1 while sleep $WAIT_TRIGGER_DELAY && eval "$WAIT_TRIGGER"; do let COUNT++ if test $COUNT -eq $MAX_TRIGGER; then if test -n "$ON_ERROR"; then eval "$ON_ERROR" fi break fi done unset AWAKE_TIME test -r $0.conf && source $0.conf set_RTCWAKE_TIME mem else echo "rtcwake -m disable" >> $LOG rtcwake -m disable fi ;; esac