102

I have set up ACPI wakeup so my laptop wakes up at a certain time each morning. The timezone for this is UTC. I want to set up my crontabs also using UTC so they fit with the wakeup alarm.

How do you do it?

I've tried editing /etc/default/cron to include:

TZ="UTC"

but it doesn't work. (I've also tried TZ=UTC and TZ="UTC/GMT")

Any ideas?

4

14 Answers 14

86

I had a similar problem on Trusty (14.04). Solved it by setting machine's timezone then restarting cron service

  1. sudo dpkg-reconfigure tzdata - follow the instructions to select Region/Country
  2. sudo service cron restart
  3. timedatectl - Verify your date settings
7
  • 1
    After setting the time zone, you can type date at the command line to confirm that the date is correct as per your expectation. Jun 11, 2017 at 14:51
  • 1
    I've restarted cron, but it is still using the old timezone (UTC)?
    – Luke
    Apr 23, 2018 at 23:10
  • 1
    This worked seamlessly for me on 18.10. ~$ date returns the correct time. Got to love those bright coloured DOS style GUI interfaces! Thanks.
    – itsricky
    May 15, 2019 at 2:09
  • can confirm this on 18.04.5 Aug 26, 2020 at 8:08
  • It worked!! thank you!! Oct 28, 2020 at 2:24
22

There is no easy way of achieving this. cron uses the local time. /etc/default/cron and other TZ specifications in the crontab just specify what TZ should be used for the processes started by cron, it doesn't impact the start time.

Most solutions I have seen involve a utility in the middle, so cron would kick off something that would then determine when to kick of in UTC (e.g. if you know you are only concerned about DST changes, kick it off 2 hours before, calculate the time difference, and kick it off then. Have a look at at. To do so, people often use perl or python or similar scripting languages).

There is a nasty way to hack it if you wanted. cron only reads the TZ info off the system at startup. So if this is an ever running server, you could just set TZ to UTC, reboot, and after boot set it to your local timezone. You could script this as well.

As an alternative approach, also have a look at the @reboot syntax of cron, which should execute scripts after booting, which sounds like what you might want.

1
  • /etc/default/cron is deprecated as of Ubuntu 20
    – user30994
    Mar 22, 2022 at 10:08
21

There is a file that controls system timezone.. I just got the same issue, here is the solution:

If you haven't configure manually any timezone, running date should display UTC time.

  • create a backup

    sudo cp /etc/localtime /etc/localtime.bkp
    
  • remove the file:

    sudo rm /etc/localtime
    
  • I live in Chicago, (you may need to change the path, using tab key helps) so:

    sudo ln -s /usr/share/zoneinfo/America/Chicago /etc/localtime
    
  • Then reboot. When your system startup perform: date

  • now your timezone should be there now, and cron will look at this.

FYI: setting the TZ variable is a temporary solution, and might act as a "mask" sometimes.

2
  • 5
    +1 for a CentOS compatible solution (and EC2 Amazon Linux). A full restart may be a good idea, but for me date worked without rebooting, and bar restarting the OS sudo service crond restart was enough to fix up my cron job times.
    – davur
    May 30, 2016 at 6:52
  • @davur thank you for the suggestion. It worked well for me without the reebot too. Oct 3, 2022 at 4:52
18

As of March 2017, I discovered that crond supports the CRON_TZ variable in each crontab.

The CRON_TZ variable specifies the time zone specific for the cron table. The user should enter a time according to the specified time zone into the table. The time used for writing into a log file is taken from the local time zone, where the daemon is running.

— quote from crontab(5) manual page

This allowed me to specify the time to execute each cronjob in local time, that automatically accounted for DST, while the server remained in UTC.

Note, this was in the CentOS 7 distro with cronie 1.4.

4
  • I also found this link helpful: serverfault.com/questions/848829/…. To find the timezone option I needed I entered ls /usr/share/zoneinfo/America to see the options. Mar 13, 2019 at 3:23
  • Which OS where you reading this manpage? I don't see it in Ubuntu 18 Feb 1, 2020 at 8:43
  • 1
    Ubuntu 20.04 LTS' crontab(5) manpage doesn't have CRON_TZ too. It still says: "It currently does not support per-user timezones."
    – xpt
    Jul 18, 2020 at 15:50
  • 2
    This answer doesn't apply to any version of Ubuntu.
    – muru
    Mar 15, 2021 at 9:22
10

OK, I took some time and figured out how to do this on Ubuntu Natty, and here's how I made it work. There may be a more elegant way, but this way works.

First, we need wrap the cron executable in a shell that sets the TZ variable. Here's how:

cd /usr/sbin
mv cron cron.real

Then, create a new /usr/sbin/cron file. I used vim, but you can use any editor you want, just make the file look like this:

#!/bin/bash
export TZ=UTC
/usr/sbin/cron.real

Make the new cron file executable:

chmod ugo+rx cron

Now, restart the cron daemon:

service cron restart

Your cron jobs will now run on a UTC-based schedule -- HOWEVER, even though the time they are executed will be UTC, when they run they will have the timezone set to whatever is defined for the system. To change that, put this in your crontab before any commands:

TZ=UTC

So your crontab will look something like this:

# Edit this file to introduce tasks to be run by cron.
# 
# Each task to run has to be defined through a single line
# indicating with different fields when the task will be run
# and what command to run for the task
# 
# To define the time you can provide concrete values for
# minute (m), hour (h), day of month (dom), month (mon),
# and day of week (dow) or use '*' in these fields (for 'any').# 
# Notice that tasks will be started based on the cron's system
# daemon's notion of time and timezones.
# 
# Output of the crontab jobs (including errors) is sent through
# email to the user the crontab file belongs to (unless redirected).
# 
# For example, you can run a backup of all your user accounts
# at 5 a.m every week with:
# 0 5 * * 1 tar -zcf /var/backups/home.tgz /home/
# 
# For more information see the manual pages of crontab(5) and cron(8)
# 
# m h  dom mon dow   command
TZ=UTC
00 19 * * * date > /tmp/date.log
3
  • 1
    What's the point of setting TZ=UTC in two places? Can't you just put it in the crontab file? Aug 15, 2014 at 4:06
  • No. Putting TZ=UTC in the crontab file only sets it for the cron jobs, not for cron itself. It doesn't affect the timing of the job execution.
    – Mark Reed
    Oct 3, 2016 at 20:07
  • It took me over an hour to figure out that cron was behaving crazy and "not respecting" the hour setting because it was still in the wrong timezone. I changed the system timezone a few days ago and forgot about it. I just needed to restart cron, thanks!
    – msb
    Feb 10, 2022 at 1:18
4
  1. See /etc/default/cron. You can set TZ here for -all- crontabs and it should be TZ=UTC iirc. So your method should have worked.

  2. Have a look at fcron. You can set individual crontabs at different time-zones:

    timezone-name 'time zone of the system'

    Run the job in the given time zone. timezone-name is a string which is valid for the environment variable TZ: see the documentation of your system for more details. For instance, "Europe/Paris" is valid on a Linux system. This option handles daylight saving time changes correctly. The TZ environ,ment variable is set to the value of timezone when a job defining this option is run.

    Please note that if you give an erroneous timezone-name argument, it will be SILENTLY ignored, and the job will run in the time zone of the system.

4
  • Well I checked it and the crontab only works when I set the trigger time as the local time. Setting the time to UTC just doesn't work.
    – alj
    Jul 24, 2011 at 18:47
  • well 4 years later and i had a peek at the file at /etc/default/cron and this is officially deprecated now
    – Randy L
    Jun 30, 2015 at 19:13
  • A downvote after 4 years? Yes this is invalid now but it was not back in the day. Then again nobody is user 11.04 anymore, I hope.
    – Rinzwind
    Jan 18, 2016 at 21:12
  • 4
    If this answer is invalid, you should probably delete it; there's no point in knowingly keeping misinformation on StackExchange. That it used to be on-topic and/or correct is pretty much irrelevant to anyone visiting this page in search of correct information. Jun 24, 2016 at 23:43
4

Please see my next post for an Ubuntu-specific solution

I know this is an Ubuntu forum, but I believe the answer will be very similar to how you would do this on a Red Hat system. I do not have an Ubuntu system handy to test this on, but I did test it on Red Hat.

All you need to do is add a line to your cron daemon init script. Set and export the environment variable TZ, like this:

export TZ=UTC

Then restart your cron daemon. Make sure you put this export in the cron daemon start script AFTER any other variable setting and sourcing -- I think this may be why the original poster's edit of the /etc/default/cron script did not work for him. Maybe he set it, but it then got reset by something else further down in the script.

Note that this will only affect the cron daemon itself, and not the jobs you run via cron, so if you want a cron job to use UTC as its timezone, you'll have to set it in the job itself, too.

You probably can not copy this verbatim and have it work on an Ubuntu box, but here's the init script I used to test this on Red Hat. You'll find the export right before the start() function:

#!/bin/sh
#
# crond          Start/Stop the cron clock daemon.
#
# chkconfig: 2345 90 60
# description: cron is a standard UNIX program that runs user-specified \
#              programs at periodic scheduled times. vixie cron adds a \
#              number of features to the basic UNIX cron, including better \
#              security and more powerful configuration options.

### BEGIN INIT INFO
# Provides: crond crontab
# Required-Start: $local_fs $syslog
# Required-Stop: $local_fs $syslog
# Default-Start:  2345
# Default-Stop: 90
# Short-Description: run cron daemon
# Description: cron is a standard UNIX program that runs user-specified 
#              programs at periodic scheduled times. vixie cron adds a 
#              number of features to the basic UNIX cron, including better 
#              security and more powerful configuration options.
### END INIT INFO

[ -f /etc/sysconfig/crond ] || { 
    [ "$1" = "status" ] && exit 4 || exit 6 
}

RETVAL=0
prog="crond"
exec=/usr/sbin/crond
lockfile=/var/lock/subsys/crond
config=/etc/sysconfig/crond

# Source function library.
. /etc/rc.d/init.d/functions

[ -e /etc/sysconfig/$prog ] && . /etc/sysconfig/$prog

export TZ=UTC
start() {
    if [ $UID -ne 0 ] ; then
        echo "User has insufficient privilege."
        exit 4
    fi
    [ -x $exec ] || exit 5
    [ -f $config ] || exit 6
    echo -n $"Starting $prog: "
    daemon $prog $CRONDARGS
    retval=$?
    echo
    [ $retval -eq 0 ] && touch $lockfile
}

stop() {
    if [ $UID -ne 0 ] ; then
        echo "User has insufficient privilege."
        exit 4
    fi
    echo -n $"Stopping $prog: "
    if [ -n "`pidfileofproc $exec`" ]; then
        killproc $exec
        RETVAL=3
    else
        failure $"Stopping $prog"
    fi
    retval=$?
    echo
    [ $retval -eq 0 ] && rm -f $lockfile
}

restart() {
    stop
    start
}

reload() {
    echo -n $"Reloading $prog: "
    if [ -n "`pidfileofproc $exec`" ]; then
        killproc $exec -HUP
    else
        failure $"Reloading $prog"
    fi
    retval=$?
    echo
}

force_reload() {
    # new configuration takes effect after restart
    restart
}

rh_status() {
    # run checks to determine if the service is running or use generic status
    status -p /var/run/crond.pid $prog
}

rh_status_q() {
    rh_status >/dev/null 2>&1
}


case "$1" in
    start)
        rh_status_q && exit 0
        $1
        ;;
    stop)
        rh_status_q || exit 0
        $1
        ;;
    restart)
        $1
        ;;
    reload)
        rh_status_q || exit 7
        $1
        ;;
    force-reload)
        force_reload
        ;;
    status)
        rh_status
        ;;
    condrestart|try-restart)
        rh_status_q || exit 0
        restart
        ;;
    *)
        echo $"Usage: $0 {start|stop|status|restart|condrestart|try-restart|reload|force-reload}"
        exit 2
esac
exit $?
4

You can also use timedatectl to find and set the timezone. (Ubuntu 18)

timedatectl list-timezones
timedatectl set-timezone America/Los_Angeles
service cron restart
2

Add

TZ="Europe/Warsaw"

but not in etc!: Run cron service editor

systemctl edit cron.service

and then, after you add and save, as above, run

service cron restart
3
  • The others have a slight scent of mothball, may this answer rise to the top!
    – brasofilo
    Mar 11, 2023 at 0:09
  • On Ubuntu 22.04 I get in the syslog: systemd[1]: /etc/systemd/system/cron.service.d/override.conf:1: Assignment outside of section. Ignoring.. So it seems I put the TZ line in the wrong place. I put it between the lines ### Anything between here and the comment below will become the new contents of the file and ### Lines below this comment will be discarded. Nevertheless, doesn't work.
    – lbruun
    Feb 25 at 12:15
  • I couldn't make sense of this recipe so I created my own answer here.
    – lbruun
    Feb 25 at 21:51
1

Updated answer for newer versions of cron.

sudo systemctl edit cron.service If this file does not exist it will create one. Add 'TZ=EST' 'TZ=UTC' etc

0

Just figured this out on Ubuntu 14/16. Worked perfectly for me.

Steps (sudo implied):

cat /etc/timezone
rm -fv /etc/localtime
ln -s /usr/share/zoneinfo/Asia/Kolkata /etc/localtime
apt install -y --reinstall tzdata
/etc/init.d/rsyslog restart
tail -f /var/log/syslog
cat /etc/timezone
0

What about evaluating the utc time in a shell script? Schedule the shell script to run every hour. At the top of the script get the UTC hour from the date command. If it is not the UTC hour you want, exit.

This script will exit if it is not 1am utc.

#!/bin/bash
if [ $(date -u +"%H") != "01" ]; then
 exit 0
fi
0

You can set environment variable CRON_TZ If the cron job is run on a remote server, you probably should notice that the shell used by crontab is sh. You can double-check on /etc/crontab.

0

This is an updated answer for Ubuntu 22.04.

The answer is about setting the timezone for how jobs are scheduled. Also the answer assumes that you do not want to change system-wide default timezone. You only want to change the cron daemon's timezone. In the example below we want cron to interpret sheduling instructions in the crontab file according to timezone Europe/Paris (replace with your own example).

Unlike some other Linux distros, Ubuntu does not support any CRON_TZ variable to be put in the crontab file. You can only set timezone for the cron daemon as a whole.

Here is how:

  1. Add an override to cron's systemd service definition. This is done with the systemctl edit cron.service command. Add text like this:
[Service]
Environment="TZ=Europe/Paris"

...but in the right location as shown here:

enter image description here The cron deamon will now run with TZ=Europe/Paris

  1. Restart the cron daemon : systemctl restart cron

How to check it is working

  • You can check the merged config for the cron service with this command: systemctl show cron.service. You should be able to see a line such as Environment="TZ=Europe/Paris" in the output.

  • Find the PID of the cron process. Something like ps -efd | grep "usr/sbin/cron" will tell you the PID. Now you can do cat /proc/$PID_OF_CRON/environ --show-nonprinting which will tell you which environment variables the process is executing with. You should be able to see the TZ variable in the output.

You must log in to answer this question.

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