mirror of https://github.com/r4sas/py-i2phosts
Hidden Z
14 years ago
1 changed files with 153 additions and 0 deletions
@ -0,0 +1,153 @@
@@ -0,0 +1,153 @@
|
||||
#!/usr/bin/python |
||||
|
||||
import os |
||||
import sys |
||||
import pwd |
||||
import errno |
||||
import argparse |
||||
import time |
||||
import configobj |
||||
import validate |
||||
import subprocess |
||||
import threading |
||||
import daemon |
||||
import daemon.pidlockfile |
||||
|
||||
class Thread(threading.Thread): |
||||
|
||||
def __init__(self): |
||||
threading.Thread.__init__(self) |
||||
self.setDaemon(True) |
||||
|
||||
|
||||
class FetcherThread(Thread): |
||||
""" Run py-i2phosts-fetcher periodically """ |
||||
|
||||
def run(self): |
||||
while True: |
||||
run_prog('py-i2phosts-fetcher') |
||||
time.sleep(float(config['fetch_interval'])) |
||||
|
||||
|
||||
class CheckerThread(Thread): |
||||
""" Run py-i2phosts-checker, py-i2phosts-maint, py-i2phosts-builder periodically """ |
||||
|
||||
def run(self): |
||||
while True: |
||||
run_prog('py-i2phosts-checker') |
||||
run_prog('py-i2phosts-maint') |
||||
run_prog('py-i2phosts-builder') |
||||
time.sleep(float(config['check_interval'])) |
||||
|
||||
|
||||
def run_prog(prog): |
||||
try: |
||||
log.info('launching %s', prog) |
||||
sp_args = [prog] |
||||
if args.debug or args.verbose: |
||||
sp_args.append('-d') |
||||
p = subprocess.Popen(sp_args, shell=False) |
||||
except OSError, e: |
||||
log.error('failed to exec %s: %s', prog, e) |
||||
if e.errno == errno.ENOENT: |
||||
log.error(' maybe it isn\'t in PATH') |
||||
else: |
||||
p.wait() |
||||
log.info('%s finished', prog) |
||||
|
||||
|
||||
def main(): |
||||
def run_fetcher(): |
||||
fetcher = FetcherThread() |
||||
fetcher.start() |
||||
return fetcher |
||||
|
||||
def run_checker(): |
||||
checker = CheckerThread() |
||||
checker.start() |
||||
return checker |
||||
|
||||
# if we're just started, wait while fetcher get some new hosts |
||||
fetcher = run_fetcher() |
||||
fetcher.join(300) # wait for 5 mins |
||||
# start checker and other |
||||
checker = run_checker() |
||||
|
||||
while True: |
||||
if fetcher.isAlive() == False: |
||||
fetcher = run_fetcher() |
||||
if checker.isAlive() == False: |
||||
checker = run_checker() |
||||
# do check every 30 mins |
||||
time.sleep(1800) |
||||
|
||||
# parse command line options |
||||
parser = argparse.ArgumentParser( |
||||
description='Master daemon for py-i2phosts.', |
||||
epilog='Report bugs to http://zzz.i2p/topics/733') |
||||
parser.add_argument('-d', '--debug', action='store_true', |
||||
help='run in debug mode without detaching from terminal'), |
||||
parser.add_argument('-v', '--verbose', action='store_true', |
||||
help='run in verbose mode without detaching from terminal'), |
||||
parser.add_argument('-c', '--config', default='/etc/py-i2phosts/master.conf', dest='config_file', |
||||
help='config file to use') |
||||
args = parser.parse_args() |
||||
|
||||
# read and validate config |
||||
spec = ''' |
||||
log_file = string(default='/var/log/py-i2phosts/master.log') |
||||
log_level = option('debug', 'info', 'warning', 'error', 'critical', default='info') |
||||
pid_file = string(default='/var/run/py-i2phosts/master.pid') |
||||
runas = string(default='_pyi2phosts') |
||||
run_fetcher = boolean(default=True) |
||||
run_checker = boolean(default=True) |
||||
run_maint = boolean(default=True) |
||||
run_builder = boolean(default=True) |
||||
check_interval = integer(default=43200) |
||||
fetch_interval = integer(default=1800) |
||||
''' |
||||
spec = spec.split('\n') |
||||
config = configobj.ConfigObj(args.config_file, configspec=spec) |
||||
if 'include' in config: |
||||
config_included = configobj.ConfigObj(config['include']) |
||||
config.merge(config_included) |
||||
|
||||
# django setup |
||||
DJANGO_SETTINGS_MODULE = 'settings' |
||||
if 'DJANGO_PROJECT_PATH' in config: |
||||
DJANGO_PROJECT_PATH = config['DJANGO_PROJECT_PATH'] |
||||
else: |
||||
DJANGO_PROJECT_PATH = os.path.dirname(sys.argv[0]) + '/web' |
||||
sys.path.insert(1, DJANGO_PROJECT_PATH) |
||||
os.environ['DJANGO_SETTINGS_MODULE'] = DJANGO_SETTINGS_MODULE |
||||
from web.lib.utils import get_logger |
||||
|
||||
# configure logger |
||||
if args.debug == True: |
||||
log_level = 'debug' |
||||
log_file = None |
||||
elif args.verbose == True: |
||||
log_level = 'info' |
||||
log_file = None |
||||
else: |
||||
log_level = config['log_level'] |
||||
log_file = config['log_file'] |
||||
|
||||
if not args.debug and not args.verbose: |
||||
# get pid object for daemon |
||||
pid = daemon.pidlockfile.TimeoutPIDLockFile(config['pid_file'], 10) |
||||
# create daemon context |
||||
d = daemon.DaemonContext(pidfile=pid, umask=077) |
||||
# write stderr to logfile # FIXME: and how we will deal with log rotation? |
||||
logfile = open(config['log_file'], 'a') |
||||
d.stderr = logfile |
||||
d.stdout = logfile |
||||
# drop privileges when started as root |
||||
if os.getuid() == 0: |
||||
runas = config['runas'] |
||||
pw_entry = pwd.getpwnam(runas) |
||||
d.uid = pw_entry[2] |
||||
d.gid = pw_entry[3] |
||||
d.open() # become daemon |
||||
log = get_logger(filename=log_file, log_level=log_level) |
||||
main() |
Loading…
Reference in new issue