Loading README.md +17 −14 Original line number Diff line number Diff line Loading @@ -22,16 +22,19 @@ pip install -r requirements.txt mysql > ^C ## Настраиваем ./sopds/settings.py SOPDS_ROOT_LIB = < Путь к каталогу с книгами > SOPDS_AUTH = < False | True > SOPDS_SCAN_SHED_MIN = '0' SOPDS_SCAN_SHED_HOUR = '0' ## Готовим базу данных python manage.py migrate python manage.py createsuperuser (admin:ma*ka) python manage.py sopds_util --clear ## Вручную запускаем сканирование коллекции книг manage.py sopds_scanner --scan ## Вручную запускаем разовое сканирование коллекции книг manage.py sopds_scanner scan ## Запускаем http/opds сервер manage.py sopds_server start --daemon Loading opds_catalog/__pycache__/settings.cpython-35.pyc +271 B (3.26 KiB) File changed.No diff preview for this file type. View original file View changed file opds_catalog/management/commands/__pycache__/sopds_scanner.cpython-35.pyc +2.65 KiB (4.59 KiB) File changed.No diff preview for this file type. View original file View changed file opds_catalog/management/commands/__pycache__/sopds_server.cpython-35.pyc −265 B (3.27 KiB) File changed.No diff preview for this file type. View original file View changed file opds_catalog/management/commands/sopds_scanner.py +104 −17 Original line number Diff line number Diff line import os import signal import sys import logging from apscheduler.schedulers.blocking import BlockingScheduler from django.core.management.base import BaseCommand from django.db import transaction from django.conf import settings from opds_catalog.models import Counter from opds_catalog.sopdscan import opdsScanner from opds_catalog import settings from opds_catalog.settings import SCANNER_LOG, SCAN_SHED_DAY, SCAN_SHED_DOW, SCAN_SHED_HOUR, SCAN_SHED_MIN, LOGLEVEL class Command(BaseCommand): help = 'Scan Books Collection.' def add_arguments(self, parser): parser.add_argument('command', help='Use [ scan | start | stop | restart ]') parser.add_argument('--verbose',action='store_true', dest='verbose', default=False, help='Set verbosity level for books collection scan.') parser.add_argument('--scan',action='store_true', dest='scan', default=False, help='Scan book collection.') parser.add_argument('--daemon',action='store_true', dest='daemonize', default=False, help='Daemonize server') def handle(self, *args, **options): logger = logging.getLogger('') logger.setLevel(logging.DEBUG) self.pidfile = os.path.join(settings.BASE_DIR, "sopds-scanner.pid") action = options['command'] self.logger = logging.getLogger('') self.logger.setLevel(logging.DEBUG) formatter=logging.Formatter('%(asctime)s %(levelname)-8s %(message)s') if settings.LOGLEVEL!=logging.NOTSET: if LOGLEVEL!=logging.NOTSET: # Создаем обработчик для записи логов в файл fh = logging.FileHandler(settings.LOGFILE) fh.setLevel(settings.LOGLEVEL) fh = logging.FileHandler(SCANNER_LOG) fh.setLevel(LOGLEVEL) fh.setFormatter(formatter) logger.addHandler(fh) self.logger.addHandler(fh) if options['verbose']: # Создадим обработчик для вывода логов на экран с максимальным уровнем вывода ch = logging.StreamHandler() ch.setLevel(logging.DEBUG) ch.setFormatter(formatter) logger.addHandler(ch) self.logger.addHandler(ch) if options['scan']: self.stdout.write('Startup book-scan function.') self.scan(logger, options['verbose']) if (options["daemonize"] and (action in ["start", "scan"])): if sys.platform == "win32": self.stdout.write("On Windows platform Daemonize not working.") else: daemonize() def scan(self, logger, verbose=False): scanner=opdsScanner(logger) if action=='scan': self.stdout.write('Startup once book-scan.') self.scan() self.stdout.write('Complete book-scan.') elif action == "start": self.start() elif action == "stop": pid = open(self.pidfile, "r").read() self.stop(pid) elif action == "restart": pid = open(self.pidfile, "r").read() self.restart(pid) def scan(self): scanner=opdsScanner(self.logger) with transaction.atomic(): scanner.scan_all() Counter.objects.update_known_counters() def start(self): writepid(self.pidfile) self.stdout.write('Startup scheduled book-scan (min=%s, hour=%s, day_of_week=%s, day=%s).'%(SCAN_SHED_MIN,SCAN_SHED_HOUR,SCAN_SHED_DOW,SCAN_SHED_DAY)) sched = BlockingScheduler() sched.add_job(self.scan, 'cron', day=SCAN_SHED_DAY, day_of_week=SCAN_SHED_DOW, hour=SCAN_SHED_HOUR, minute=SCAN_SHED_MIN) quit_command = 'CTRL-BREAK' if sys.platform == 'win32' else 'CONTROL-C' self.stdout.write("Quit the server with %s.\n"%quit_command) try: sched.start() except (KeyboardInterrupt, SystemExit): pass def stop(self, pid): try: os.kill(int(pid), signal.SIGTERM) except OSError as e: self.stdout.write("Error stopping sopds_scanner: %s"%str(e)) def restart(self, pid): self.stop(pid) self.start() def writepid(pid_file): """ Write the process ID to disk. """ fp = open(pid_file, "w") fp.write(str(os.getpid())) fp.close() def daemonize(): """ Detach from the terminal and continue as a daemon. """ # swiped from twisted/scripts/twistd.py # See http://www.erlenstar.demon.co.uk/unix/faq_toc.html#TOC16 if os.fork(): # launch child and... os._exit(0) # kill off parent os.setsid() if os.fork(): # launch child and... os._exit(0) # kill off parent again. os.umask(0) std_in = open("/dev/null", 'r') std_out = open(SCANNER_LOG, 'a+') os.dup2(std_in.fileno(), sys.stdin.fileno()) os.dup2(std_out.fileno(), sys.stdout.fileno()) os.dup2(std_out.fileno(), sys.stderr.fileno()) # null = os.open("/dev/null", os.O_RDWR) # for i in range(3): # try: # os.dup2(null, i) # except OSError as e: # if e.errno != errno.EBADF: # raise os.close(std_in.fileno()) os.close(std_out.fileno()) Loading
README.md +17 −14 Original line number Diff line number Diff line Loading @@ -22,16 +22,19 @@ pip install -r requirements.txt mysql > ^C ## Настраиваем ./sopds/settings.py SOPDS_ROOT_LIB = < Путь к каталогу с книгами > SOPDS_AUTH = < False | True > SOPDS_SCAN_SHED_MIN = '0' SOPDS_SCAN_SHED_HOUR = '0' ## Готовим базу данных python manage.py migrate python manage.py createsuperuser (admin:ma*ka) python manage.py sopds_util --clear ## Вручную запускаем сканирование коллекции книг manage.py sopds_scanner --scan ## Вручную запускаем разовое сканирование коллекции книг manage.py sopds_scanner scan ## Запускаем http/opds сервер manage.py sopds_server start --daemon Loading
opds_catalog/__pycache__/settings.cpython-35.pyc +271 B (3.26 KiB) File changed.No diff preview for this file type. View original file View changed file
opds_catalog/management/commands/__pycache__/sopds_scanner.cpython-35.pyc +2.65 KiB (4.59 KiB) File changed.No diff preview for this file type. View original file View changed file
opds_catalog/management/commands/__pycache__/sopds_server.cpython-35.pyc −265 B (3.27 KiB) File changed.No diff preview for this file type. View original file View changed file
opds_catalog/management/commands/sopds_scanner.py +104 −17 Original line number Diff line number Diff line import os import signal import sys import logging from apscheduler.schedulers.blocking import BlockingScheduler from django.core.management.base import BaseCommand from django.db import transaction from django.conf import settings from opds_catalog.models import Counter from opds_catalog.sopdscan import opdsScanner from opds_catalog import settings from opds_catalog.settings import SCANNER_LOG, SCAN_SHED_DAY, SCAN_SHED_DOW, SCAN_SHED_HOUR, SCAN_SHED_MIN, LOGLEVEL class Command(BaseCommand): help = 'Scan Books Collection.' def add_arguments(self, parser): parser.add_argument('command', help='Use [ scan | start | stop | restart ]') parser.add_argument('--verbose',action='store_true', dest='verbose', default=False, help='Set verbosity level for books collection scan.') parser.add_argument('--scan',action='store_true', dest='scan', default=False, help='Scan book collection.') parser.add_argument('--daemon',action='store_true', dest='daemonize', default=False, help='Daemonize server') def handle(self, *args, **options): logger = logging.getLogger('') logger.setLevel(logging.DEBUG) self.pidfile = os.path.join(settings.BASE_DIR, "sopds-scanner.pid") action = options['command'] self.logger = logging.getLogger('') self.logger.setLevel(logging.DEBUG) formatter=logging.Formatter('%(asctime)s %(levelname)-8s %(message)s') if settings.LOGLEVEL!=logging.NOTSET: if LOGLEVEL!=logging.NOTSET: # Создаем обработчик для записи логов в файл fh = logging.FileHandler(settings.LOGFILE) fh.setLevel(settings.LOGLEVEL) fh = logging.FileHandler(SCANNER_LOG) fh.setLevel(LOGLEVEL) fh.setFormatter(formatter) logger.addHandler(fh) self.logger.addHandler(fh) if options['verbose']: # Создадим обработчик для вывода логов на экран с максимальным уровнем вывода ch = logging.StreamHandler() ch.setLevel(logging.DEBUG) ch.setFormatter(formatter) logger.addHandler(ch) self.logger.addHandler(ch) if options['scan']: self.stdout.write('Startup book-scan function.') self.scan(logger, options['verbose']) if (options["daemonize"] and (action in ["start", "scan"])): if sys.platform == "win32": self.stdout.write("On Windows platform Daemonize not working.") else: daemonize() def scan(self, logger, verbose=False): scanner=opdsScanner(logger) if action=='scan': self.stdout.write('Startup once book-scan.') self.scan() self.stdout.write('Complete book-scan.') elif action == "start": self.start() elif action == "stop": pid = open(self.pidfile, "r").read() self.stop(pid) elif action == "restart": pid = open(self.pidfile, "r").read() self.restart(pid) def scan(self): scanner=opdsScanner(self.logger) with transaction.atomic(): scanner.scan_all() Counter.objects.update_known_counters() def start(self): writepid(self.pidfile) self.stdout.write('Startup scheduled book-scan (min=%s, hour=%s, day_of_week=%s, day=%s).'%(SCAN_SHED_MIN,SCAN_SHED_HOUR,SCAN_SHED_DOW,SCAN_SHED_DAY)) sched = BlockingScheduler() sched.add_job(self.scan, 'cron', day=SCAN_SHED_DAY, day_of_week=SCAN_SHED_DOW, hour=SCAN_SHED_HOUR, minute=SCAN_SHED_MIN) quit_command = 'CTRL-BREAK' if sys.platform == 'win32' else 'CONTROL-C' self.stdout.write("Quit the server with %s.\n"%quit_command) try: sched.start() except (KeyboardInterrupt, SystemExit): pass def stop(self, pid): try: os.kill(int(pid), signal.SIGTERM) except OSError as e: self.stdout.write("Error stopping sopds_scanner: %s"%str(e)) def restart(self, pid): self.stop(pid) self.start() def writepid(pid_file): """ Write the process ID to disk. """ fp = open(pid_file, "w") fp.write(str(os.getpid())) fp.close() def daemonize(): """ Detach from the terminal and continue as a daemon. """ # swiped from twisted/scripts/twistd.py # See http://www.erlenstar.demon.co.uk/unix/faq_toc.html#TOC16 if os.fork(): # launch child and... os._exit(0) # kill off parent os.setsid() if os.fork(): # launch child and... os._exit(0) # kill off parent again. os.umask(0) std_in = open("/dev/null", 'r') std_out = open(SCANNER_LOG, 'a+') os.dup2(std_in.fileno(), sys.stdin.fileno()) os.dup2(std_out.fileno(), sys.stdout.fileno()) os.dup2(std_out.fileno(), sys.stderr.fileno()) # null = os.open("/dev/null", os.O_RDWR) # for i in range(3): # try: # os.dup2(null, i) # except OSError as e: # if e.errno != errno.EBADF: # raise os.close(std_in.fileno()) os.close(std_out.fileno())