wcs/wcs/qommon/cron.py

106 lines
3.4 KiB
Python

# w.c.s. - web application for online forms
# Copyright (C) 2005-2010 Entr'ouvert
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, see <http://www.gnu.org/licenses/>.
import os
import signal
import time
try:
import prctl
except ImportError:
prctl = None
import sys
parent_killed = False
def stop_cron_process(*args):
global parent_killed
parent_killed = True
class CronJob:
hours = None
minutes = None
weekdays = None
days = None
function = None
def __init__(self, function, hours = None, minutes = None, weekdays = None, days = None):
self.function = function
self.hours = hours
self.minutes = minutes
self.weekdays = weekdays
self.days = days
def cron(publisher):
global parent_killed
app_dir = publisher.app_dir
last = time.localtime()
while not parent_killed:
now = time.localtime()
if now[:5] != last[:5]:
last = now
for hostname in os.listdir(app_dir):
publisher.app_dir = os.path.join(app_dir, hostname)
if not os.path.isdir(publisher.app_dir):
continue
# create a fake publisher
try:
publisher.set_config()
except:
continue
for job in publisher.cronjobs:
if job.days and now[2] not in job.days:
continue
if job.weekdays and now[6] not in job.weekdays:
continue
if job.hours and not now[3] in job.hours:
continue
if job.minutes and not now[4] in job.minutes:
continue
publisher.install_lang(publisher.get_site_language())
publisher.substitutions.reset()
publisher.substitutions.feed(publisher)
for extra_source in publisher.extra_sources:
publisher.substitutions.feed(extra_source(publisher, None))
try:
job.function(publisher)
except:
publisher.notify_of_exception(sys.exc_info(), context='[CRON]')
time.sleep(10)
def spawn_cron(create_publisher):
global cron_pid
cron_pid = os.fork()
if cron_pid == 0:
pub = create_publisher()
# set process name and title (this only works on Linux)
if prctl:
prctl.set_name(os.path.basename(sys.argv[0]) + ' [cron]')
prctl.set_proctitle(os.path.basename(sys.argv[0]) + ' [cron]')
signal.signal(signal.SIGTERM, stop_cron_process)
cron(pub)
sys.exit(0)
else:
signal.signal(signal.SIGTERM, kill_cron_process)
#os.close(parent_fd)
def kill_cron_process(signum, frame):
os.kill(cron_pid, signal.SIGTERM)
sys.exit(0)