hyleaus
hyleaus

Reputation: 755

Cron scheduler of python script using notify-send

I'm having some difficulty using these three technologies together.

Cron entry:

* * * * * /usr/bin/python /path/to/python/email/program.py

Python program:

  1 #!/usr/bin/python
  2 
  3 import imaplib
  4 import os
  5 import sys
  6 import pynotify
  7 
  8 if not pynotify.init('Emails'):
  9     sys.exit(1)
 10 
 11 with open('/path/to/python/email/count.tmp', 'r') as file:
 12     data = int(file.read().strip())
 13 client = imaplib.IMAP4_SSL('mail.sever.com', '993')
 14 client.login('[email protected]', 'password')
 15 client.select()
 16 
 17 unseen = client.search(None, 'UnSeen')[1][0].split()
 18 
 19 if unseen[0] == '':
 20     pass
 21 else:
 22     if len(unseen) != data:
 23         n = pynotify.Notification(str(len(unseen) - data) + " New Messages",
 24             str(len(unseen)) + " Unread Messages",
 25             "file:///path/to/python/email/mail.png")
 26         if not n.show():
 27             print "Fail"
 28             sys.exit(1)
 30         with open('/path/to/python/email/count.tmp', 'w') as file:
 31             file.write(str(len(unseen)))

The script works correctly when run by itself, but it will not run when scheduled as a cron job. I checked the syslog and it says the script is being run, and I've run as sudo the line from the log to verify.

I've checked

Execute python Script on Crontab

and

Cron with notify-send

but neither, nor further links seem to address this combination.

Any thoughts?

-Update 1-

As pynotify seems not to allow the program to work at all, I've replaced their calls with an os.system call. At least this updates the small tmp file, but still no notify.

os.system('/usr/bin/X11/notify-send "{} New Messages" "{} Unread Messages"'.format(len(unseen) - data, len(unseen))

-Update 2-

/usr/lib/python2.7/dist-packages/gtk-2.0/gtk/__init__.py:57: GtkWarning: could not open display
warnings.warn(str(e), _gtk.Warning)

** (other.py:16509): WARNING **: Command line `dbus-launch --autolaunch=91bdcc4a583bfb56734fbe1200000010 --binary-syntax --close-stderr' exited with non-zero exit status 1: Autolaunch error: X11 initialization failed.\n

Upvotes: 1

Views: 1777

Answers (5)

Manu J4
Manu J4

Reputation: 2859

Under Ubuntu 20.04, the following Python script stored under /home/<user>/notify.py:

import subprocess

subprocess.Popen(['notify-send', 'Running. Finally.'])

sucessfully sends a message from my user's crontab (crontab -e, not root) with the entry:

*/1 * * * * export DISPLAY=:0.0 && export DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/$(id -u)/bus && /usr/bin/python3 /home/<user>/notify.py

For me, the DBUS_SESSION_BUS_ADDRESS parameter made the difference. Solutions without it didn't work.

Upvotes: 0

Michael Hamilton
Michael Hamilton

Reputation: 586

In an answer to another question I described a generalised notify-desktop github gist written for use in cron and timer jobs. The script deals with identifying the desktop user(s) and offers a solution for Wayland as well as X11.

Upvotes: 0

shyaa shakya
shyaa shakya

Reputation: 11

Try this command:

*\1 * * * * sudo -u user DISPLAY=:0 DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/1000/bus notify-send 'Hi.'

Upvotes: 1

user2629998
user2629998

Reputation:

When you run your program manually, it works because the variable DISPLAY is being set to your current display (:0 in most cases), however when running the script via cron, there is no such variable being set and notifications doesn't work.

As mentionned in this answer, you should export both the display and the Xauthority, and finally running the script as your user (and not as root).

Try something like this :

* * * * * export DISPLAY=:0.0 && export XAUTHORITY=/home/<username>/.Xauthority && sudo -u <username> /usr/bin/python /path/to/python/email/program.py

(change <username> with your username)

Upvotes: 6

its me
its me

Reputation: 127

Change your cron entry to * * * * * /usr/bin/python /path/to/python/email/program.py >> /var/log/program.log 2>&1 and see what you get in log file program.log You can add print statements to your program to debug better (as you will get them in program.log)

Upvotes: 1

Related Questions