How do I know if jobs have been/are performing? - Crontab - python

I have followed the suggestion in this question
as I am using Django, I have set the script to store date and time of each run of the script in the db, but no entry has been stored yet in the database.
Is there a way to figure out, other than typing "top" and searching through?

First, I would probably configure cron to mail yourself any output by using MAILTO:
In /etc/crontab:
MAILTO=username
Second, I usually add something to my script that (almost) cannot possibly fail, like the following:
#!/bin/sh
echo "$0 ran on `date +%c`" >> /tmp/crontab_test.log
# ... rest of program
If you're calling a python script directly from cron, you could do something similar or create a wrapper shell script.

If you have sendmail installed, you can add the following to '/etc/aliases'
root: your_name#domain.com
After you do that, update the aliases running this command:
sudo newaliases
Cron will automatically email you every time a job is run. No need to specify that in the crontab file.
Also, make sure you test your email capabilities (e.g. make sure you are able to send emails from the server) and lastly, create a trivial cronjob and test if you receive an email.
Do not assume!

In addition to setting up cron to send email, you can send the output of cron to a seperate syslog log facility by adding the following to your /etc/syslog.conf.
# Log cron stuff
cron.* /var/log/cron.log
This should log a message to /var/log/cron.log each time a job is run.

Related

python: running 'nohup': how to get rid of message?

I have a variable list of programs that I want to kick off from a cron job. The solution I have settled on at least for now is to write the actual cron job in python, then run through the list, starting each program with:
outf=open('the_command.log','w')
subprocess.Popen(['nohup','the_command', ...],stdout=outf)
outf.close()
The problem with this is that it creates a nohup.out file - the same one for each process, it seems. If I did this same thing from the command line, it might look like:
$ nohup the_command ... > the_command.log 2>&1
This works fine, except I get a message from nohup when I run it:
nohup: ignoring input and redirecting stderr to stdout
I have tried to redirect stderr to /dev/null, but the result is that the_command.log is empty. How can I solve this?
I solved this by using a different command detach from http://inglorion.net/software/detach/
But I now consider this to be improper. It would be better to use oneshot services started by your cron job script or make your cron entry cause a oneshot service to be started.
With this there would be no need to detach as the processes aren't your scripts children rather they are children of the supervisor. Any init that supports starting a normally down service and does not restart it when it exits can be used.

Send display to user from a root job

I have a job that starts in crontab with root privilege. This job should display a popup message after a while. The job is in python and use MessageBox toolkit.
With roit, the job works and after 5 minutes, I see the messagebox.
The problem is that if I login as a user, I can see the job running in the tasks list but the popup does not work (probably since the display of the job is of the root and not the user).
I cant find the way to change this job to use the display of the current ligin user.
Is there a way to change this so the user will see the popup?
Thanks.
The MessageBox does not popup because the cron job run in an environment where the DISPLAY (environment variable) is not set. Instead of having cron run your python directly, you can make it run a simple wrapper around it:
#!/usr/bin/env bash
export DISPLAY=':0'
python /path/to/your/python/program.sh
Alternatively, if your confident it won't mess with other cron jobs, you can add DISPLAY=:0 as the first line of your crontab.

Zenity not working in python script with crontab

I have a python script in which I have used Zenity to display some notification. The code snippet is as follows:
if message_list:
pretty_print(message_list)
os.system("/usr/bin/zenity --notification --text='You have unread messages'")
When I run this script normally, everything works fine i.e. dialog box appears and message gets displayed. But when I schedule this script in crontab nothing appears. Any solution to this?
There is no sane way to run interactive commands from cron. There is no guarantee that there is a user, there is no guarantee that there is a single user, there is no guarantee that the user(s) who are on want to, or are even able to, interact with your software; some of them may be pseudo-users or remote on expensive metered Internet access or just idle or whatever.
The usual solution is a server/client architecture where whatever runs from cron makes its results available via some IPC mechanism, and users who want the results run a client from within their X11 session (or shell, or what have you).
Create a script info.sh (remember to grant it execute rights):
#!/bin/bash
xhost +
/usr/bin/zenity --notification --text='You have unread messages'
And in your script:
if message_list:
pretty_print(message_list)
os.system("./info.sh")
That's if you want to use the solution you mentioned.

Restart Python with threading or crontab

I have written a function that crawls and clusters news articles. I want this function to restart every 10 minutes, aiming to get the newest articles. I wrote a Python script that this with the help of threading module:
import threading
def run():
do_it()
if not END:
threading.Timer(600.0, run).start()
END = False
threading.Timer(600.0, do_it).start()
It works fine with Python IDLE. Now I see in different forums that "crontab" is mentioned for this purpose. Since I plan to host this application on the web and since I have no prior experience with web development/hosting, what would you suggest to me: to continue with the previous code or to try to do it with the "crontab" function? I am working with the Django framework.
Using Django doesn't really work in this context. if you want to use a cron script then you will want it running independently of your webserver (you don't want your webserver ending after you finish the script). Alternatively you could start up a GET or POST request to an already running Django instance by this method.
First type crontab -e at a prompt in your unix based os or mac. (since you mentioned crontab I'll assume your not using windows)
This will allow you to edit a file for the user you are logged in as. This is the line you will want to type to get a do_it.py file to run every ten min.
*/10 * * * * do_it.py
For more information at your prompt type man 5 crontab. Other modifications you could make are prefixing the word sudo to the command which would allow you to change root's crontab.

Allowing user to configure cron

I have this bash script on the server that runs every hour, via cron. I was perfectly happy, but now the user wants to be able to configure the frequency through the web interface.
I don't feel comfortable manipulating the cron configuration programmatically, but I'm not sure if the other options are any better.
The way I see it, I can either:
Schedule a script to run once a minute and check if it should really run "now"
Forgo cron altogether and use a deamon that is its own scheduler. This probably means rewriting the script in python
...or suck it up and manipulate the cron configuration from the web interface (written in python BTW)
What should I do?
EDIT: to clarify, the main reason I'm apprehensive about manipulating cron is because it's basically text manipulation with no validation, and if I mess it up, none of my other cron jobs will run.
Here's what I ended up doing:
Taking stefanw's advice, I added the following line at the top of my bash script:
if [ ! `cat /home/username/settings/run.freq` = $1 ]; then
exit 0
fi
I set up the following cron jobs:
0 */2 * * * /home/username/scripts/publish.sh 2_hours
#hourly /home/username/scripts/publish.sh 1_hour
*/30 * * * * /home/username/scripts/publish.sh 30_minutes
*/10 * * * * /home/username/scripts/publish.sh 10_minutes
From the web interface, I let the user choose between those four options, and based on what the user chose, I write the string 2_hours/1_hour/30_minutes/10_minutes into the file at /home/username/settings/run.freq.
I don't love it, but it seems like the best alternative.
Give your users some reasonable choices like every minute, every 5 minutes, every half an hour, ... and translate these values to a cron job string. This is user friendly and forbids users to tamper directly with the cron job string.
You could use a python scheduler library that does most of the work already:
pycron
scheduler-py
What about Webmin? I have never used it myself but it seems you could configure the cron module and give permissions to the user who wants to configure the job.
Well something I use is a main script started every minute by cron. this script check touched files. If the files are there the main cron script start a function/subscript. You just have to touch a defined file and "rm -f"ed it when done. It has the side benefits to be more concurrent proof if you want other way to start jobs. Then you can use your favourite web programming language to handle your users scheduling ...
The main script looks like :
[...]
if [ -e "${tag_archive_log_files}" ]; then
archive_log_files ${params}
rm -f ${tag_archive_files}
fi
if [ -e "${tag_purge_log_files}" ]; then
purge_log_files ${params}
rm -f ${tag_purge_log_files}
fi
[...]
I found a module that can manipulate the cron info for me. It's called python-crontab, and it's available with easy_install. From the source:
Example Use:
from crontab import CronTab
tab = CronTab()
cron = tab.new(command='/usr/bin/echo')
cron.minute().during(5,50).every(5)
cron.hour().every(4)
cron2 = tab.new(command='/foo/bar',comment='SomeID')
cron2.every_reboot()
list = tab.find('bar')
cron3 = list[0]
cron3.clear()
cron3.minute().every(1)
print unicode(tab.render())
for cron4 in tab.find('echo'):
print cron4
for cron5 in tab:
print cron5
tab.remove_all('echo')
t.write()
(I kept googling for "cron" and couldn't find anything. The keyword I was missing was "crontab").
I'm now deciding if I'll use this or just replace cron entirely with a python based scheduler.

Categories

Resources