I get lost in askubuntu reading Q&A and experimenting with recommended code snippets. So I often miss switching TV news channels on the internet at the top of the hour. Not a big problem for youtube channels that allow time-shifting, but it's a "show stopper" for tv channels using flash player.

Can cron be configured to run a job at the top of each hour where I provide a script to sound a grandfather like clock chime (with subtle sound volume of course!)? A minor chime could be sounded at the bottom of the hour too. I'm sure I can locate suitable .ogg or .oga files on the net and I know I can use ogg123 to play them. I just don't know if cron could do it. I know I could use a script that sleeps and wakes up to test time but don't like the thought of having something running all the time (there's enough of that going on already I think).

If this can be done with cron can someone answer how to set it up?

Thank you.

  • I am not very good at English idioms. top of each hour meaning start of each hour?
    – heemayl
    Oct 1, 2016 at 22:56
  • 1
    @heemayl LOL yes. I come from a time before digital clocks were invented and there was a minute hand that when at "top" meant :00 of hour and when at "bottom" meant :30 of the hour. Hehe Oct 1, 2016 at 22:58
  • sudo apt-get install mcron - stackoverflow.com/questions/44470965/…
    – SDsolar
    Jun 15, 2017 at 2:37
  • @SDsolar this appears to be a replacement for cron which is beyond the scope of the question. FYI I've written the grandfather clock script in the answer below. Jun 15, 2017 at 10:25

3 Answers 3


heemayl has provided the correct answer to get cron to run at the top of the hour and bottom of the hour. Thanks again! However as other users have discovered a cronjob cannot play sound files by default:

Configuring cron to play sounds

In order for cron to play sound files it needs to export an environment variable:

export XDG_RUNTIME_DIR="/run/user/1000"

Once this is done in your script sounds will play.

As pointed out by another answer your user ID may not always be 1000. To find your user ID use:

$ id

uid=1000(rick) gid=1000(rick) groups=1000(rick),4(adm),24(cdrom),27(sudo),30(dip),46(plugdev),113(lpadmin),128(sambashare)

If your user ID is not 1000, then change the script to your ID.

Configure cron to run top of hour and bottom of hour

crontab -e setup (last 5 lines only):

# For more information see the manual pages of crontab(5) and cron(8)
# m h  dom mon dow   command
00 *    *   *   *    /usr/local/bin/top-of-hour-chime    >/dev/null
00,30 * *   *   *    /usr/local/bin/bottom-of-hour-chime >/dev/null

Most users setup cron to use the nano editor. Use these control keys in nano to save your work:

  • Add the last two lines above and use Ctrl+O to write Out (save) the file.
  • A /tmp... filename is presented, but do not be concerned, simply press Enter.
  • Now use Ctrl+X to eXit the nano editor.

The bottom-of-hour-chime script runs at the top of the hour too but, that is OK since it's short and sweet.

If you don't have the >/dev/null at the end of the lines cron tries to email you with the command output. If you don't have the mail server setup an error message appears in your /var/log/syslog file:

Oct 02 10:00:07 dell CRON[21259]: (CRON) info (No MTA installed, discarding output)

Configuring cron to display pop-up notifications

The script displays a pop-up notification message at the top of every hour. So for this an additional variable needs to be exported:

eval "export $(egrep -z DBUS_SESSION_BUS_ADDRESS /proc/$(pgrep -u $LOGNAME gnome-session)/environ)";

Contents of top-of-hour-chime

#! /bin/bash

# NAME: top-of-hour-chime
# PATH: /usr/local/bin
# DESC: Play sound called by cron
# CALL: Automatically called by /var/spool/cron/crontabs/<user_name>
# DATE: Created Oct 1, 2016. Modified June 10, 2018.
# UPDT: 2016-11-09 - Add notification bubble with time in text.
#       2018-06-10 - Switch from `ogg123` to `paplay` in default installation.

# exit # uncomment to suppress when watching movies

# paplay needs environment variable exported:
export XDG_RUNTIME_DIR="/run/user/1000"

# needed for notify-send
eval "export $(egrep -z DBUS_SESSION_BUS_ADDRESS /proc/$(pgrep -u $LOGNAME gnome-session)/environ)";

# get hour in 12 hour format
HOUR=$(date +%I)
ZHOUR=$(echo $HOUR | sed 's/^0*//')

pactl set-sink-volume 0 -25%
DISPLAY=:0 notify-send --urgency=critical --icon=/usr/share/icons/gnome/256x256/status/appointment-soon.png "It is ""$ZHOUR"" o'clock"
paplay '/usr/share/sounds/ubuntu/ringtones/Melody piano.ogg'
pactl set-sink-volume 0 +25%

The export XDG_RUNTIME_DIR... is necessary to get sound to play. This is because cron runs in minimal environment. This line should be omitted first if it you use a third party sound player. Then if no sound put the line back. Then still if no sound, well happy hunting!

The two main TV news shows I watch over the net have softer volume than normal so I have the TV turned up higher than normal. Consequentially when ogg123 plays sound files they sound very loud. So pactl is used to reduce volume before chime and increase it afterwards.

Contents of bottom-of-hour-chime

This is almost a duplicate of top-of-hour-chime and perhaps redundant here, but included for full documentation purposes.

#! /bin/bash

# NAME: bottom-of-hour-chime
# PATH: /usr/local/bin
# DESC: Play sound called by cron
# CALL: Automatically called by /var/spool/cron/crontabs/<user_name>
# DATE: Oct 1, 2016. Modified June 10, 2018.

# UPDT: 2018-06-10 Switch from `ogg123` to `paplay` installed by default.

# exit # Uncomment to suppress when watching movies.

# paplay needs environment variable exported:
export XDG_RUNTIME_DIR="/run/user/1000"

pactl set-sink-volume 0 -25%
paplay /usr/share/sounds/ubuntu/ringtones/Bliss.ogg
pactl set-sink-volume 0 +25%
  • Doesn't work. Steps followed, script runs, but still no sound. Mar 18, 2021 at 15:27
  • @PaulFeakins When you call the script from the command line (not from within cron) are any error messages displayed? When cron is running what messages are showing up in journalctl -xe output. Mar 20, 2021 at 15:45
  • I gave up, I'm just using this now instead: online-stopwatch.com/talking-clock-analog Mar 30, 2021 at 10:38
  • @PaulFeakins many people have problems getting cron working. I know I've had problems configuring it in the past. I'll look at creating a new script that simply sleeps until the top of the hour and bottom of the hour. The new script won't use cron at all. It's pretty low on the priority list though... Mar 30, 2021 at 11:42
  • Yeah this is waaay more complicated than it should be. Perhaps using the right music player would solve it? Mar 31, 2021 at 14:12

Yes, you can.

Open your cron table with crontab -e, and add:

00 * * * * /path/to/player /path/to/file.ogg

Replace /path/to/player, and /path/to/file.ogg with respective values you want.

The above will play the sound (i.e. run the command), at every hour at 00-th (start of first) minute.

If you want to run the command at 30-th minute of each hour too:

00,30 * * * * /path/to/player /path/to/file.ogg
  • When typing crontab -e it says there is no file created for my user account. It offers to create one with nano. I did this and set up the commands suggested. When selecting ^W (write file) the default file name is: /tmp/crontab.6QN0vo/crontab. The file name seems very wrong. Can you update your answer for creating a new crontab -e configuration file? Note my system is already setup to delete /tmp/IG* files over a day old which has been working well (I just don't remember how I set that puppy up). Oct 1, 2016 at 23:33
  • @WinEunuuchs2Unix Don't worry, cron opens that file temporarily in /tmp, once you save the content, will create/replace the file /var/spool/cron/crontabs/<username>, and thats permanent.
    – heemayl
    Oct 1, 2016 at 23:45

Despite using this export:

# paplay needs environment variable exported:
export XDG_RUNTIME_DIR="/run/user/1000"

it didn't work.

After months of research found no solution.

In desperation, tried the following and it worked:

Enter the following in contab

# Terminal command: crontab -e
# Detect the name of the display in use
display=":$(ls /tmp/.X11-unix/* | sed 's#/tmp/.X11-unix/X##' | head -n 1)"
user=$(who | grep '('$display')' | awk '{print $1}') # the user of the display 
uid=$(id -u $user) #Detect the id of the user


*/5 * * * * sh /root/.play_sound.sh

Next create .play_sound.sh


display=":$(ls /tmp/.X11-unix/* | sed 's#/tmp/.X11-unix/X##' | head -n 1)"
user=$(who | grep '('$display')' | awk '{print $1}') # the user of the display 
uid=$(id -u $user) #Detect the id of the user

su - $user -c "paplay /usr/share/sounds/freedesktop/stereo/complete.oga"

Hope this helps.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.