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.
/etc/systemd/system/goodmorning.timer
[Unit] Description=good morning [Timer] Unit=goodmorning.service OnCalendar=*-*-* 7:30 WakeSystem=true Persistent=false [Install] WantedBy=multi-user.target
/etc/systemd/system/goodmorning.service
[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"
installation
After installing those files, run (as root): systemctl enable goodmorning.timer; systemctl start goodmorning.timer
Then, you'll also need to edit /etc/systemd/logind.conf
, and
set 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!
xfce workaround
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.
Heya! Unfortunately this wouldn't work as a per-user unit btw, as WakeSystem= timers require privileges.
The Unit=goodmorning.service line is implied btw. Persistent=false is the default, so could be dropped too.
Lennart
I think almost all x86 systems have a RTC with wake support.
The "*IgnoreInhibited" settings shouldn't be needed; they're about the lid overriding normal "sleep" inhibitors, not handle-* ones.
Generally nice, but I really don't see why this needs to be:
So why can't I give that privilege to the user? A normal user shouldn't have to touch root for user-tasks like this. Please, Mr. Pöttering, please, please, please, spend a month with a group of experienced sys admins. Maybe then you will see the errors of your ways and why systemd is a nice toy but not a serious tool.
rtcwake -m mem -s 120 && /path/script
in a cron job? I would guess it's about entering sleep again?
Seems like a very complex way to solve a simple problem?
I suspend my laptop by closing its lid at some random time. I could build everything needed to make rtcwake run on lid close, do the math about when to wake up, etc -- but systemd already did.
Also, notice that this is a composable solution; I can have multiple wakeup jobs that wake up at the same or different times, do activities of different lengths, etc. The laptop will be set to wake up at the next time any such job is scheduled to run. It will keep running until no such jobs remain running and then, as long as the lid is closed, it will go back to sleep.
Strange, I've got a similar setup (without inhibition, though) working flawlessly as a per-user unit. Arch, systemd 217, all defaults (no special configuration of privileges took place).