Suspend und zeitgesteuertes Aufwachen
Hier kommt eine Reihe von Scripten zum Einsatz, die v. a. auf der im Linux-Magazin-Artikel Weckdienst (Linux-Magazin 08/2004) beschriebenen "settime"-Methode beruhen. Die zugrunde liegenden Berechnungen habe ich hier mal zu visualisieren versucht (auch als PDF-Dokument):
Bei den verwendeten Skripten handelt es sich im Einzelnen um die folgenden...
/usr/local/bin/setWakeupTime
#!/bin/sh # setWakeupTime -- prepare the system to be woken up # by BIOS clock at a certain date # Usage: setWakeupTime intended_wakeup_time # Wakeup time format: YYYY-MM-DD hh:mm:ss # # Note: "epoche format" means the number of # seconds passed since 1970-01-01 00:00:00 UTC # Initialize some variables source initSleepVars echo "`date`: * begin setWakeupTime" >> $LOG echo "`date`: setting wakeup time to $1" >> $LOG # Convert current time to epoche format Now=`date +%s` # Convert intended wakeup time to epoche format Wakeup=`date -d "$1" +%s` # Calculate time difference between now and # intended wakeup time Diff=$[$Wakeup-$Now] # Convert fixed BIOS wakeupt time to epoche format Bios=`date -u -d "$BIOS_WAKEUP" +%s` # Store time difference between intended wakeup time # and fixed BIOS wakeup time in file echo "$[$Wakeup-$Bios]" > /var/timeDiff # Set system time to Diff (time difference # between now and intended wakeup time) seconds # before fixed BIOS wakeup time date -u -s "$BIOS_WAKEUP $Diff seconds ago" >/dev/null # Also change BIOS clock to new system time; # as a result, when gone to sleep, the system # will wakeup in Diff seconds from this very moment hwclock -w --utc echo "`date`: wakeup time has been set" >> $LOG echo "`date`: * end setWakeupTime" >> $LOG
/usr/local/bin/initSleepVars
# initSleepVars -- Initialize some suspend-related variables # # This script is sourced by a number of scripts developed # in the context of automatic shutdown/wakeup of MythTV. # Path to log file for suspend-related events LOG=/var/log/sleep.log # Fixed wakeup time as set in BIOS BIOS_WAKEUP="2005-12-31 23:59:59" # Ensure that a sensible search path is set MY_PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin if [ $PATH ] then PATH=$MY_PATH:$PATH else PATH=$MY_PATH fi # Server to be used by ntpdate NTP_SERVER=ptbtime1.ptb.de
Wichtig: In "initSleepVars" muss die Variable BIOS_WAKEUP auf den gleichen Aufweck-Termin gesetzt werden, der auch im BIOS eingestellt wird!
/usr/local/bin/mythSleep
#!/bin/sh # mythSleep -- contains everything for suspending the system # if mythbackend is idle and for properly # resuming operation after wakeup # Initialize some variables source initSleepVars echo "`date`: * begin mythSleep" >> $LOG # Stop mythbackend daemon echo "`date`: stopping backend" >> $LOG /etc/init.d/mythtv-backend stop # Unload dvb driver; otherwise hibernation # may fail from time to time #modprobe -r cx88_dvb # Stop lirc and unload lirc_serial driver echo "`date`: stopping lirc" >> $LOG killall irexec /etc/init.d/lirc stop #rmmod lirc_serial # Suspend the system echo "`date`: going to sleep" >> $LOG echo disk > /sys/power/state #---------------------------------------------------------- # Chrrr... Zzzz... #----------------------------------------------------------- # . # . # . #---------------------------------------------------------- # Ooops! System woke up! #---------------------------------------------------------- # Re-load lirc_serial driver and re-start lirc echo "`date`: starting lirc" >> $LOG #modprobe lirc_serial /etc/init.d/lirc start irexec -d /etc/lirc/lircrc # Determine wakeup time (should be # around fixed BIOS wakeup time) # and convert to epoche format Wakeup=`date +%s` # Readjust system time echo "`date`: readjusting time" >> $LOG readjustTimeAfterWakeup # Re-load dvb driver #modprobe cx88_dvb # Re-start mythbackend echo "`date`: starting backend" >> $LOG /etc/init.d/mythtv-backend restart # Unfortunately, XvMC seems not to get re-initialized # properly after wakeup, hence we let 'init' restart X # according to inittab #echo "`date`: restarting X" >> $LOG #killall Xorg # Convert fixed BIOS wakeup time to epoche format Bios=`date -u -d "$BIOS_WAKEUP" +%s` # Now have a closer look at wakeup time # determined above. If woken up # earlier than fixed BIOX wakeup time... if [ "$Bios" -gt "$Wakeup" ]; then #...then assume that system has been woken # up by user echo "`date`: seems I was woken up by user" >> $LOG echo "`date`: re-starting frontend" >> $LOG sleep 3 /bin/su - mythtv -c "export DISPLAY=:0; /usr/bin/mythfrontend --logfile /var/log/mythtv/mythfrontend.log" & else # ...otherwise we assume that the system has # been woken up by BIOS clock alarm echo "`date`: seems I was woken up by timer alarm" >> $LOG # Since we haven't been woken up by user, # we don't need a frontend. So wait until # frontend is running... # until [ `ps -e | grep mythfrontend | wc -w` -gt 0 ]; do # sleep 1; # done # # ...end kill it immediately # echo "`date`: frontend not needed, hence killing" >> $LOG # killall mythfrontend fi echo "`date`: renicing myth and mysql" >> $LOG mythRenice echo "`date`: * end mythSleep" >> $LOG
/usr/local/bin/readjustTimeAfterWakeup
#!/bin/sh # readjustTimeAfterWakeup -- # readjusts system time after being woken # up by BIOS clock # # Note: "epoche format" means the number of # seconds passed since 1970-01-01 00:00:00 UTC # Initialize some variables source /usr/local/bin/initSleepVars echo "`date`: * begin readjustTimeAfterWakeup" >> $LOG echo "`date`: readjusting time" >> $LOG # Check whether a time difference has been stored # (by the setWakeupTime script); if so, adjust # system time using the stored value if [ -r /var/timeDiff ]; then # Determine modification time of time difference # file (which contains the time difference between # intended wakeup time and fixed BIOS wakeup # time) and convert to epoche format TimeStamp=`date -r /var/timeDiff +%s` # Convert current time to epoche format Now=`date +%s` # If system has been woken up, the system clock # will now (approx.) show the fixed BIOS wakeup time. # The timeDiff file, however, has been created # *before* turning back the clock; hence it's # modification time will now apprear to lie # in the future if [ "$TimeStamp" -gt "$Now" ]; then echo "`date`: readjusting time according to saved time difference" >> $LOG # Read saved time difference between current # system time (i.e. approx. fixed BIOS wakeup # time) and actual time from file Diff=`cat /var/timeDiff | head -n 1` # Set system clock to actual time by adding # saved time difference to current system time date -s "+$Diff seconds" >/dev/null # Also set BIOS clock to actual time hwclock -w --noadjfile --utc fi fi # In any case, try to set the system clock # via NTP. We're not too big in trouble if # NTP happens to fail, since we have already # re-adjusted the system time using the # stored time difference value. ntpdate $NTP_SERVER # Again set BIOS clock to actual time hwclock -w --noadjfile --utc echo "`date`: time has been readjusted" >> $LOG echo "`date`: * end readjustTimeAfterWakeup" >> $LOG
/usr/bin/mythPreShutdown
#!/bin/sh # # mythPreShutdown -- called by mythbackend to figure out # whether or not it is allowed to # shut down the system # Returns exit code 0 if shutdown is ok, 1 else # Regex defining names of processes which will prevent # shutdown if still running PROG=mythcommflag\|python # Initialize some variables source initSleepVars echo "`date`: * begin mythPreShutdown" >> $LOG # If any of the programs defined above is still running... if [ `ps -e | grep -E $PROG | wc -w` -gt 0 ]; then echo "`date`: $PROG still running, may not go to sleep yet..." >> $LOG #...tell mythbackend to re-idle exit 1 else echo "`date`: $PROG finished, may now go to sleep" >> $LOG # else: tell mythbackend that it may shutdown exit 0 fi echo "`date`: * end mythPreShutdown" >> $LOG
MythTV-Konfiguration
Jetzt müssen wir bloß noch MythTV beibringen, mit diesen Skripten sinnvoll umzugehen. Dazu in "mythtv-setup" den Menüpunkt "General" auswählen und unter "Shutdown/Wakeup Options" folgende Einstellungen vornehmen:
- Startup command: (nichts)
- Block shutdown before client connected: aktivieren
- Idle timeout (secs): 90 (oder was auch immer)
- Max. wait for recording (min): 15 (oder so)
- Startup before rec (secs): 300 (halt genug zum Hochfahren/Aufwachen)
- Wakeup time format: yyyy-MM-dd hh:mm
- Set wakeuptime command: sudo /usr/local/bin/setWakeupTime "$time"
- Server halt command: sudo /usr/local/bin/mythSleep
- Pre Shutdown check-command: sudo /usr/local/mythPreShutdown