1

I have a Python script with the following code:

import subprocess
import sys

default = "Take a 20 second break - look at least 20 feet away!"
message = sys.argv[1] if len(sys.argv) > 1 else default

def sendmessage(message):
    subprocess.Popen(['notify-send', message])
    return

sendmessage(message)

called takebreak.py, which will send a system notification.

When I try to automate it using crontab like so:

* * * * * /usr/bin/python /home/polo/git-repositories/takebreak/takebreak.py

It doesn't work. Running the command

/usr/bin/python /home/polo/git-repositories/takebreak/takebreak.py

in the terminal does work, which means it's not a file location problem, but rather something to do with cron. Any ideas?

EDIT1:

After debugging and looking at the logs, I can verify that cron is actually executing the commmand export DISPLAY=:0; /usr/bin/python /home/polo/git-repositories/takebreak/takebreak.py every minute like I set it to do, but for some reason this command, while it should send a system notification, is not doing so. Any ideas?

EDIT2:

The solution was to add some address bus thing (forget the exact code) that I found in another post, that ended up fixing it. Unfortunately, none of the answers or comments here helped with solving the problem, but thanks regardless!

  • This may help: http://stackoverflow.com/questions/22743548/cronjob-not-running – Paulo Almeida Mar 30 '16 at 23:51
  • My crontab is running for sure, but for some reason the command in question will not work. typing just `* * * * * export DISPLAY=:0; /usr/bin/notify-send blah` does not display anything – patrickstarpants Mar 31 '16 at 00:02
  • http://unix.stackexchange.com/questions/111188/using-notify-send-with-cron – Paulo Almeida Mar 31 '16 at 00:05
  • Im having difficulty understand the solution in the code above. I'm supposed to add a DBUS_SESSION_BUS_ADDRESS to my main code? And what would the address be? – patrickstarpants Mar 31 '16 at 00:26
  • To begin with, my suggestion would be to run `env|grep DBUS` and hardcode it in the crontab, just like `$PATH` in Will's answer. That will tell you if it solves the problem. If it does, there are a couple of suggestions on how to do it, in that answer I linked to. It would be easier if it were a bash script, you'll have to figure out the best way to do it, either from Python or by dumping the environment variable somewhere and using it from the crontab. – Paulo Almeida Mar 31 '16 at 08:41

1 Answers1

1

Most likely, the problem is that notify-send is not in your $PATH when running from crontab. First, figure out where it's stored:

$ which notify-send
/usr/bin/notify-send

For me, it's in /usr/bin.

At the top of your crontab file (crontab -e), set $PATH:

PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"

If you want to include whatever $PATH may have already been set before (safer), do this instead:

PATH="${PATH}:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"

Make sure this includes the directory where your command is installed, if it's not installed in /usr/bin.

Of course, the other option, is to simply specify the full command path in your Python script:

subprocess.Popen(['/usr/bin/notify-send', message])
Will
  • 24,082
  • 14
  • 97
  • 108
  • Wouldn't it be better to specify the absolute command path in the script? Setting the crontab PATH could have side-effects. – isedev Mar 30 '16 at 23:14
  • I'd say no--then the script is less portable as it depends on libnotify's tools being installed in the specified location. I added to my answer and put a safer way to modify `$PATH`, as well as changing the Python script to use the absolute path to the command. – Will Mar 30 '16 at 23:17
  • Both methods didn't work, `cat /var/log/syslog | grep crontab` returns (among edits and such) the following line: `Mar 30 19:31:01 polo cron[634]: (polo) RELOAD (crontabs/polo) ` – patrickstarpants Mar 30 '16 at 23:34
  • Let's try writing our standard error output to a file and looking at it. Add `>/tmp/cron-error.log 2>&1` to the end of your crontab line, then look at `/tmp/cron-error.log` and see what it says. – Will Mar 30 '16 at 23:38
  • I tried this before yet no log appeared after waiting several minutes (the crontab is set to run every minute right now) – patrickstarpants Mar 30 '16 at 23:41
  • Ahh, I wasn't very familiar with `notify-send`, but I think it needs a `$DISPLAY`. What about changing the command called by `cron` to: `sh -c 'DISPLAY=:0 /usr/bin/python /home/polo/git-repositories/takebreak/takebreak.py'` – Will Mar 31 '16 at 00:14
  • Yeah in a comment on the original question I indicated that I was using DISPLAY, I tried adding your code so the final product is `* * * * * sh -c 'DISPLAY=:0 /usr/bin/python /home/polo/git-repositories/takebreak/takebreak.py'` – patrickstarpants Mar 31 '16 at 00:22
  • This is stumping me as well, haha. Let's rule out Python-related problems just for sanity. Let's try `* * * * * /bin/bash -c 'DISPLAY=:0 /usr/bin/notify-send "weird test message"'` – Will Mar 31 '16 at 00:38