Cron not working for root

Hello,

I am on Fedora KDE 43, and I am pretty new to Linux, so I shouldn’t have derived too much from the original setup.

I am trying to make my computer hibernate between 9PM and 7AM, if it is not already closed.

I want to make the following cron line work:

* 0-6,21-23 * * * systemctl hibernate

The problem is, it doesn’t work.

To understand what the issue is, I also created a log file:

* 0-6,21-23 * * * systemctl hibernate >> ~/logs/log_sudo.help 2>&1

And… I receive no log entries at all.

Here is what is tried:

sudo crontab -e

returns

* * * * * echo "hey!"
* 0-6,21-23 * * * echo "Le système s'est éteint à $( date '+%F_%H:%M:%S' )"  >> ~/logs/log_sudo.help 2>&1
* 0-6,21-23 * * * systemctl hibernate >> ~/logs/log_sudo.help 2>&1

The first line was to know if the simplest thing could work. It doesn’t, but maybe it is more complicated than that.
The second was to get some log entries. I didn’t get any.
The third does what I want.

If I try to open the log via

sudo nano ~logs/log_sudo.help

it shows an empty file.

I tried every line separately outside of cron. Everything works fine.
I had a few issues with swap space at first for hibernating, but now it works well.

I tried not to hibernate, but to make my computer shutdown or whatever, it doesn’t do anything.

Some people in the internet mentioned that the cron file for root is supposedly in /etc/crontab.
I opened it

sudo nano /etc/crontab

and wrote

SHELL=/bin/bash
PATH=/sbin:/bin:/usr/sbin:/usr/bin
MAILTO=root

# For details see man 4 crontabs

# Example of job definition:
# .---------------- minute (0 - 59)
# |  .------------- hour (0 - 23)
# |  |  .---------- day of month (1 - 31)
# |  |  |  .------- month (1 - 12) OR jan,feb,mar,apr ...
# |  |  |  |  .---- day of week (0 - 6) (Sunday=0 or 7) OR sun,mon,tue,wed,thu,fri,sat
# |  |  |  |  |
# *  *  *  *  * user-name  command to be executed

* * * * * echo "hey!"
* * * * * echo "hey!" >> ~/logs/log_sudo.help 2>&1

Again, it doesn’t do anything.

Cron works for non-root users fine though:
On my account, if I write:

crontab -l
* * * * * echo "hey" >> ~/logs/log.help 2>&1

And I open ~/logs/log.help, I do see a line of 'hey’s.

What did I do wrong?
I have been stuck on this for a few days, it is pretty frustrating.

If I forgot to mention everything to help you understand the issue, please ask.

I don’t think ~ works in a cron script. I think $HOME will work.

These days I use systemd timer unit in place of cron for a number of reasons.
First the timer’s actively is logged in the journal as is the related systemd unit’s output.
I don’t like the cron syntax and find the more explicit systemd syntax easier to reason about and fix as I’m developing a timed activity.

Notice this format takes a user name before the command, so

* * * * * root echo "hey!" >> ~/logs/log_sudo.help 2>&1

The regular crontab files you edit with crontab -e doesn’t take a user name.

Although in the root crontab, of course it will resolve to /root and not the homedir of the user who used sudo to create the job.

And that is yet another reason i use systemd timers and units.

Thank you for your answers. I will check systemd later on.

I tried your recommendations. Now, when I do

sudo nano /etc/crontab
SHELL=/bin/bash
PATH=/sbin:/bin:/usr/sbin:/usr/bin
MAILTO=root

# For details see man 4 crontabs

# Example of job definition:
# .---------------- minute (0 - 59)
# |  .------------- hour (0 - 23)
# |  |  .---------- day of month (1 - 31)
# |  |  |  .------- month (1 - 12) OR jan,feb,mar,apr ...
# |  |  |  |  .---- day of week (0 - 6) (Sunday=0 or 7) OR sun,mon,tue,wed,thu,fri,sat
# |  |  |  |  |
# *  *  *  *  * user-name  command to be executed


* * * * * root echo "hey!" >> $HOME/logs/log_sudo.help 2>&1

It still doesn’t work…
Am I still missing something?

As in the job fails? Or it appears to succeed but you don’t see anything in /root/logs/log_sudo.help ?

It doesn’t show anything in the logs.
The log was not in /root, but in $HOME.
I just tried to create a similar /root/logs/log, and now it appears to work…
Excellent!

I have no idea why this is the case though. I though root had access to everything, so why must the log file be in /root and not in /home/usr ?

But for a job running in the root crontab, $HOME is /root. Or it should be AFAIK!

Are you saying that when you had >> $HOME/logs/log_sudo.help in the cron job, no log got created anywhere, neither in /root nor in anywhere else?

No reason why it must be. But if you want a job in the root crontab to write to /home/bearsard, you’ll have to explicitly write /home/bearsard, not $HOME.

No, you are right. I didn’t know there were the /root directory was the same as/user.
The log gets created in /root with $HOME.

I still have a problem though, which is that if I write in /etc/crontab

* * * * * root echo "hey!" >> $HOME/logs/log_crontab.txt 2>&1
* * * * * root echo " $( date '+%F_%H:%M:%S' ) " >> $HOME/logs/log_crontab.txt 2>&1

I do get "hey!"s in the log, but not the dates. However, if I try to echo "$( date '+%F_%H:%M:%S' )" in my terminal, it does work.

Rewrite that as

* * * * * root date '+%F_%H:%M:%S' >> $HOME/logs/log_crontab.txt 

There is no reason to capture standard ouput just to send it out to standard output using the echo command.

I tried to, it didn’t work.

the directory /root/logs/ must exist!

check root’s mbox for emails regarding failed crontab jobs

Yes, I created it! The logs get recorded at /root/logs/log_crontab.txt, which is full of "hey!"s.
I don’t get any emails in any of the emails I think of.

ok, so what’s the issue then?

The times do not get recorded, just the first line of the crontab.

ah, IIRC % has a special meaning in crontabs.
I think you need to escape that with a backslash \%
Might depend on the implementation.

see man crontab, can’t verify atm.
and I’d change date to /usr/bin/date or /bin/date use full paths whenever possible

Correct, you do.

so that would be

* * * * * root date '+\%F_\%H:\%M:\%S' >> $HOME/logs/log_crontab.txt

Run man 5 crontab and look.

Also run systemctl status crond.service see any errors from the crontab.

I did what you said, and now it works! No error appears from the crontab via the command line.
Thank you very much!