5

I have a Linux server that's only needed at workdays in work hours. There's no point having it powered on all the time.

How can I make a Linux system suspend and resume on set times and days without any supervision?

2
  • 1
    Basically, you are creating points of failure and more maintenance shutdowning down and booting it. The boot process might also use up more energy than leaving it on at night, I suspect. If you make a point of turning it off, I would do it only on weekends. May 20, 2019 at 8:05
  • @Rui this is using suspend and resume, so the boot process is very short (there effectively isn’t one). I do something similar on a few systems, including some with hardware RAID etc. which take ages to boot normally, and resuming is instantaneous and doesn’t use much power at all. May 21, 2019 at 12:45

2 Answers 2

7

I've created a shell script for this purpose using systemctl suspend and rtcwake commands to manage the power.

When run, it'll work in a loop (15 minute cycles):

  • checking what time and day of week it is,

  • determining when it should wake up

  • checking if it should suspend right now

#!/bin/bash

while [ 1=1 ]; do # repeat forever

        clear

        echo "Updated: $(date '+%F %T')"

        echo "### TIME SECTION"

        SLEEP_H=18 # What hour should the system suspend at?
        WAKE_H=8 # What hour should the system wake up at?

        # check what day of the week it is now
        DOW=$(date +%w) #  1 = monday, 5 = friday etc.

        echo "Day of week: $DOW"

        # check what time is it now
        H=$(date +%H)
        M=$(date +%M)

        NOW_S=$(date +%s)

        echo "Hour: $H, minute: $M"

        #date +%s --date "tomorrow 8:00"

        if [[ $DOW -lt 5 ]]; then
                echo "It's Monday to Thursday!"
                WAKE="tomorrow $WAKE_H:00"
        else
                echo "It's Friday to Sunday!"
                WAKE="monday $WAKE_H:00"
        fi

        WAKE_S="$(date --date "$WAKE" +%s)"

        WAKE_SR=$(( $WAKE_S - $NOW_S))

        echo
        echo "Wake: $WAKE"
        echo "Wake relative seconds: $WAKE_SR"
        echo
        rtcwake -m no -s "$WAKE_SR"

        # sleep section

        sleep 15m

        echo "### SLEEP SECTION"

        if [[ $H -gt $SLEEP_H ]]; then # sleep if the hour is right
                systemctl suspend
                continue
        else
                echo "It's too early to sleep"
        fi

        if [[ $DOW -gt 5 ]]; then # sleep if it's saturday or sunday
                systemctl suspend
                continue
        else
                echo "It's not weekend - gotta stay up!"
        fi

done

This script is set to make the system wake up between Monday to Friday at 8 AM, and fall asleep at 6 PM.

It'll sleep during weekends and nights. Feel free to modify it to your needs.

I keep this script in /root/power-schedule.sh. Make sure it's executable: `sudo chmod +x /root/power-schedule.sh'

Also put the script in crontab with the @reboot time to make sure that a sudden power outage will not interrupt your schedule.

Run:

sudo crontab -e

And add this line:

@reboot         exec /root/power-schedule.sh

You might also want to configure the UEFI/BIOS so that the machine will power on when it detects AC power - this will cause it to boot up after a power outage (instead of staying off - which is usually the default behaviour).

2
  • I’m curious: why don’t you use a crontab entry to suspend? May 21, 2019 at 12:46
  • Becasue despite many tries I was unable to get cron on this system to execute commands at specified time. It operates in it's own time zone. So I had to come up with a different solution.
    – unfa
    May 22, 2019 at 13:16
0

One liner:

rtcwake -m mem -s $(($(date --date "20:30" +%s) - $(date +%s)))

This won't work if you have network shares mounted, or your network wakes up when it sees traffic.

Disable Wake on Lan:

ethtool -s eno1 wol d

or delegate it to only on "Magic Packet" with:

ethtool -s eno1 wol m

To unmount network shares:

sudo fuser /mount/share

And end / kill those processes, then umount the share, or umount -f -l if you must.

Sometimes it will take while before these time out, so this works better:

while sleep 1; do rtcwake -m mem -s $(($(date --date "20:30" +%s) - $(date +%s))) && break; done 

Instead of 20:30 you can also say tomorrow 9:00. Don't worry if rtcwake reports another time, it will do so if your system clock is UTC.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .