10

I am on Arch Linux where I am trying to create a systemd timer as a cron alternative for hibernating my laptop on low battery. So I wrote these three files:

/etc/systemd/system/battery.service

[Unit]
Description=Preko skripte preveri stanje baterije in hibernira v kolikor je stanje prenizko

[Service]
Type=oneshot
ExecStart=/home/ziga/Dropbox/workspace/operacijski/archlinux/hibernate/hibernatescript
User=nobody
Group=systemd-journal

/etc/systemd/system/battery.timer

[Unit]
Description=Periodical checking of battery status every two minutes

[Timer]
OnUnitActiveSec=2min 

[Install]
WantedBy=timers.target

/home/ziga/Dropbox/workspace/operacijski/archlinux/hibernate/hibernatescript

#!/bin/sh
/usr/bin/acpi -b | /usr/bin/awk -F'[,:%]' '{print $2, $3}' | (
        read -r status capacity
        if [ "$status" = Discharging ] && [ "$capacity" -lt 50 ]; then
                /usr/bin/systemctl hibernate
        fi                                                                                                                
)    

And then to enable timer I executed:

sudo systemctl enable battery.timer
sudo systemctl start battery.timer

And somehow it isn't working. Script works on its own. This means that if I execute command below, my computer hibernates just fine.

/home/ziga/Dropbox/workspace/operacijski/archlinux/hibernate/hibernatescript

ADD1:

After enabling and starting timer I ran some checks and this is what I get:

[ziga@ziga-laptop ~]$ systemctl list-timers
NEXT                          LEFT       LAST                          PASSED    UNIT                         ACTIVATES
n/a                           n/a        n/a                           n/a       battery.timer                battery.serv
Tue 2016-06-28 00:00:00 CEST  42min left Mon 2016-06-27 00:01:54 CEST  23h ago   logrotate.timer              logrotate.se
Tue 2016-06-28 00:00:00 CEST  42min left Mon 2016-06-27 00:01:54 CEST  23h ago   shadow.timer                 shadow.servi
Tue 2016-06-28 00:00:00 CEST  42min left Mon 2016-06-27 00:01:54 CEST  23h ago   updatedb.timer               updatedb.ser
Tue 2016-06-28 22:53:58 CEST  23h left   Mon 2016-06-27 22:53:58 CEST  23min ago systemd-tmpfiles-clean.timer systemd-tmpf

and

[ziga@ziga-laptop ~]$ systemctl | grep battery
battery.timer  loaded active elapsed   Periodical checking of battery status every two minutes

ADD2:

After applying solution from Alexander T my timer starts (check the code below) but script doesn't hibernate my laptop while it hibernates it if I execute it directly.

[ziga@ziga-laptop ~]$ systemctl list-timers
NEXT                          LEFT          LAST                          PASSED       UNIT                         ACTIVATES
Tue 2016-06-28 19:17:30 CEST  1min 43s left Tue 2016-06-28 19:15:30 CEST  16s ago      battery.timer                battery.service
3
  • 2
    Is it possibly a permissions issue? When you say you ran it, was it as the nobody user, or as ziga (I see /home/ziga)? User nobody may not have sufficient permissions. When you say it isn't working, how far does it get?
    – tniles
    Jun 27, 2016 at 20:33
  • I have tried to change the user to ziga but it doesn't work.
    – 71GA
    Jun 27, 2016 at 21:18
  • I tried changing WantedBy=timers.targetto WantedBy=battery.service in /etc/systemd/system/battery.timer but this doesn't do anything.
    – 71GA
    Jun 28, 2016 at 17:38

2 Answers 2

7

An answer to this question is to swap User=nobody not with User=ziga but with User=root in /etc/systemd/system/battery.service. Somehow even if user ziga has all the privileges of using sudo command it can't execute systemctl hibernate inside of the bash script. I really don't know why this happens. So the working files are as follows:

/etc/systemd/system/battery.service

[Unit]
Description=Preko skripte preveri stanje baterije in hibernira v kolikor je stanje prenizko

[Service]
Type=oneshot
ExecStart=/home/ziga/Dropbox/workspace/operacijski/archlinux/hibernate/hibernatescript
User=root
Group=systemd-journal

/etc/systemd/system/battery.timer

[Unit]
Description=Periodical checking of battery status every two minutes

[Timer]
OnBootSec=2min
OnUnitActiveSec=2min 

[Install]
WantedBy=battery.service

/home/ziga/Dropbox/workspace/operacijski/archlinux/hibernate/hibernatescript

#!/bin/sh
/usr/bin/acpi -b | /usr/bin/awk -F'[,:%]' '{print $2, $3}' | (
        read -r status capacity
        if [ "$status" = Discharging ] && [ "$capacity" -lt 7 ]; then
                /usr/bin/systemctl hibernate
        fi
)

I tried it and it allso works with User=ziga or User=nobody but we need to change /usr/bin/systemctl hibernate into sudo /usr/bin/systemctl hibernate in the last script. So it looks like User variable somehow doesn't even matter... Oh and you can as well remove absolute names from the last script and change first line from #!/bin/sh to #!/bin/bash. I also changed WantedBy=timers.target to WantedBy=battery.service in /etc/systemd/system/battery.timer.

There you go. The best cron alternative to hibernate laptops on low battery. =)

1
  • No part of the system is going to automatically use sudo. If you run the systemd service as non-root user, it will execute commands as that user without executing sudo unless you explicitly add sudo. As a result, the hibernatescript is executed as the user defined by User=ziga in .service file and if that command cannot execute without using sudo, it will obviously fail every time. The correct fix is to use User=root, not sprinkle sudo commands around. Aug 23 at 11:38
2

May be you shoul try to add first start after boot, like this:

[Timer] OnBootSec=15min OnUnitActiveSec=2m

5
  • Did you read this here? wiki.archlinux.org/index.php/Systemd/Timers#Monotonic_timer
    – 71GA
    Jun 28, 2016 at 14:59
  • @71GA, Yes, read it there. I think topic starter problem caused by absence of first start. Jun 28, 2016 at 16:56
  • This changes some things. Please check my ADD2 to the question.
    – 71GA
    Jun 28, 2016 at 17:17
  • Have you tried to call /usr/bin/systemctl hibernate not from the script? It working? Because when i try to do it n my centos not from root account I get error Authentication is required for hibernating the system. and request root password. May be you have same issue and you should start it under sudo? Jun 28, 2016 at 17:31
  • My user ziga is in group users and I have this rule %users ALL=(ALL) NOPASSWD: ALL in the /etc/sudoers file and this rule enables all users from group users to execute sudo command without inputting any password. So user ziga should be fine right? What kind of user does a systemd service use? I tried setting User=nobody and User=ziga in /etc/systemd/system/battery.service but nothing works.
    – 71GA
    Jun 28, 2016 at 17:45

You must log in to answer this question.

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