I've taught my laptop to wake up at 7:30 in the morning. When it does, it will run whatever's in my ~/bin/goodmorning script. Then, if the lid is still closed, it will go back to sleep again.
So, it's a programmable alarm clock that doesn't need the laptop to be left turned on to work.
But it doesn't have to make noise and wake me up (I rarely want to be woken up by an alarm; the sun coming in the window is a much nicer method). It can handle other tasks like downloading my email, before I wake up. When I'm at home and on dialup, this tends to take an hour in the morning, so it's nice to let it happen before I get up.
This took some time to figure out, but it's surprisingly simple. Besides ~/bin/goodmorning, which can be any program/script, I needed just two files to configure systemd to do this.
[Unit] Description=good morning [Timer] Unit=goodmorning.service OnCalendar=*-*-* 7:30 WakeSystem=true Persistent=false [Install] WantedBy=multi-user.target
[Unit] Description=good morning RefuseManualStart=true RefuseManualStop=true ConditionACPower=true [Service] Type=oneshot ExecStart=/bin/systemd-inhibit --what=handle-lid-switch --why=goodmorning /bin/su joey -c "/usr/bin/timeout 45m /home/joey/bin/goodmorning"
After installing those files, run (as root):
systemctl enable goodmorning.timer; systemctl start goodmorning.timer
Then, you'll also need to edit
LidSwitchIgnoreInhibited=no -- this overrides the default, which
is not to let systemd-inhibit block sleep on lid close.
almost too easy
I don't think this would be anywhere near as easy to do without systemd, logind, etc. Especially the handling of waking the system at the right time, and the behavior around lid sleep inhibiting.
The WakeSystem=true relies on some hardware support for waking from sleep; my laptop supported it with no trouble but I don't know how broadly available that is.
Also, notice the
ConditionACPower=true, which I added once I realized I
don't want the job to run if I forgot to leave the laptop plugged in
overnight. Technically, it will still wake up when on battery power, but
then it should go right back to sleep.
Quite a lot of nice peices of systemd all working together here!
If using xfce, xfce4-power-manager takes over handling of lid close from systemd, and currently prevents the system from going back to sleep if the lid is still closed when goodmorning finishes. Happily, there is an easy workaround; this configures xfce to not override the lid switch behavior:
xfconf-query -c xfce4-power-manager -n -p /xfce4-power-manager/logind-handle-lid-switch -t bool -s true
Other desktop environments may have similar issues.
why not a per-user unit?
It would perhaps be better to use the per-user systemd, not the system wide one. Then I could change the time the alarm runs without using root.
What's prevented me from doing this is that systemd-inhibit uses policykit, and policykit prevents it from being used in this situation. It's a lot easier to run it as root and use su, than it is to reconfigure policykit.