Пример #1
0
    def __init__(self,
                 app=None,
                 pid_path=None,
                 work_directory=None,
                 uid=None,
                 gid=None):
        super(DaemonBase, self).__init__()

        self.app = app
        self.pid_path = pid_path if pid_path else self.config['pidfile']
        self.pidfile = PidFile(pid_path) if pid_path else PidFile(
            self.config['pidfile'])
        self.work_directory = work_directory if work_directory else self.config[
            'work_directory']
        self.stdout = sys.stdout if not self.config['detach_process'] else None
        self.stderr = sys.stderr if not self.config['detach_process'] else None
        self.detach_process = self.config['detach_process']
        self.uid = uid if uid else self.config['uid']
        self.gid = gid if gid else self.config['gid']

        self.daemon = DaemonContext(working_directory=self.work_directory,
                                    pidfile=self.pidfile,
                                    detach_process=self.detach_process,
                                    stdout=self.stdout,
                                    stderr=self.stderr,
                                    uid=self.uid,
                                    gid=self.gid,
                                    signal_map=self.get_signal_map())
        self.init_logger()
Пример #2
0
def main():
    args = parse_args(sys.argv[1:])

    if args.daemonize:
        pidfile = PidFile(args.pid_file)
        daemon = DaemonContext(pidfile=pidfile)
        syslog.syslog('Daemonizing')
        daemon.open()

    syslog.syslog('Daemonized')

    main_loop(args)
Пример #3
0
 def start(app):
     app.config = app.readConfig(app.config_file)
     app.daemon = DaemonContext(
         pidfile=PidFile(app.pid),
         signal_map={
             signal.SIGTERM: app.program_cleanup,
             signal.SIGHUP: app.terminate,
             signal.SIGUSR1: app.reload_program_config
         }
         #                                   ,files_preserve=(sys.stdout)
         ,
         stdout=open("/tmp/daemon_stdout.log", 'w'),
         stderr=open("/tmp/daemon_stderr.log", 'w'),
         gid=app.config["daemon"]["groupid"])
     print("daemon created")
     if app.nodaemon:
         print("no daemon")
         app.daemon.detach_process = False
     else:
         app.daemon.detach_process = True
     try:
         print("before daemon")
         app.daemon.open()
         print("after daemon")
         app.createLogger()
         app.logger.debug('After open')
         app.run()
     except:
         print("Unexpected error:", sys.exc_info()[0])
         raise
Пример #4
0
 def start(self, devel=False):
     self.config.read_file(open(self._config_file))
     if devel:
         self._app(devel=True)
     daemon = DaemonContext(pidfile=PidFile(self.pid))
     if self.nodaemon:
         daemon.detach_process = False
     dlog = open(self.config.get('main', 'dlog'), 'w')
     daemon.stderr = dlog
     daemon.stdout = dlog
     daemon.open()
     self._app()
Пример #5
0
 def start(self, devel=False):
     self.config.read_file(open(self._config_file))
     if devel:
         self._app(devel=True)
     daemon = DaemonContext(pidfile=PidFile(self.pid))
     if self.nodaemon:
         daemon.detach_process = False
     dlog = open(self.config.get("main", "dlog"), "w")
     daemon.stderr = dlog
     daemon.stdout = dlog
     daemon.open()
     self._app()
Пример #6
0
 def start(self):
     console_log = logging.StreamHandler()
     console_log.setLevel('DEBUG')
     self.log.addHandler(console_log)
     if not self._cfg_open():
         print("could not process config")
         sys.exit(1)
     daemon = DaemonContext(pidfile=PidFile(self.pid))
     if self.nodaemon:
         daemon.detach_process = False
     dlog = open(self.config.get('main', 'dlog_file'), 'w')
     daemon.stderr = dlog
     daemon.stdout = dlog
     daemon.open()
     signal.signal(signal.SIGHUP, self._reload)
     signal.signal(signal.SIGTERM, self._quit)
     self.log.removeHandler(console_log)
     self._run()
    def start(self):
        self.config=self.readConfig(self._config_file)
        self.daemon = DaemonContext(pidfile=PidFile(self.pid)
                               ,signal_map={
            signal.SIGTERM: self.program_cleanup,
            signal.SIGHUP: self.terminate,
            signal.SIGUSR1: self.reload_program_config},
                                    gid=self.config["daemon"]["groupid"])
        if self.nodaemon:
            self.daemon.detach_process = False
#            daemon.stderr = "/tmp/pulse_err.out"
#            daemon.stdout = "/tmp/pulset.out"
        try:
            self.daemon.open()
            self.createLogger()
            self.logger.debug('After open')
            self.run()
        except:
            print ("Unexpected error:", sys.exc_info()[0])
            raise
Пример #8
0
def chellow_command():
    parser = argparse.ArgumentParser()
    parser.add_argument('action', choices=['start', 'stop', 'restart'])
    args = parser.parse_args()

    try:
        os.makedirs(app.instance_path)
    except BaseException:
        pass
    pidfile_path = os.path.join(app.instance_path, 'chellow.pid')
    pidfile = PidFile(pidfile_path)
    daemon = DaemonContext(
        pidfile=pidfile, stdin=sys.stdin, stderr=sys.stderr, stdout=sys.stdout)

    if args.action == 'start':
        chellow_start(daemon)
    elif args.action == 'stop':
        chellow_stop(pidfile_path)
    elif args.action == 'restart':
        chellow_stop(pidfile_path)
        chellow_start(daemon)
Пример #9
0
 def start(self, devel=False):
     self.config.read_file(open(self._config_file))
     self._config_dict = self._cfg_to_dict(self.config)
     try:
         jsonschema.validate(self.config_dict['main'], CHECK_CONFIG_MAIN)
     except jsonschema.exceptions.ValidationError as err:
         print("main section: {0}".format(err))
         sys.exit(1)
     if devel:
         self._app(devel=True)
         return
     daemon = DaemonContext(pidfile=PidFile(self.pid))
     if self.nodaemon:
         daemon.detach_process = False
     dlog = open(self.config.get('main', 'dlog'), 'w')
     daemon.stderr = dlog
     daemon.stdout = dlog
     daemon.open()
     self._app()
Пример #10
0
    def __init__(self, app=None, pid_path=None, work_directory=None, uid=None, gid=None):
        super(DaemonBase, self).__init__()

        self.app = app
        self.pid_path = pid_path if pid_path else self.config['pidfile']
        self.pidfile = PidFile(pid_path) if pid_path else PidFile(self.config['pidfile'])
        self.work_directory = work_directory if work_directory else self.config['work_directory']
        self.stdout = sys.stdout if not self.config['detach_process'] else None
        self.stderr = sys.stderr if not self.config['detach_process'] else None
        self.detach_process = self.config['detach_process']
        self.uid = uid if uid else self.config['uid']
        self.gid = gid if gid else self.config['gid']

        self.daemon = DaemonContext(working_directory=self.work_directory,
                                    pidfile=self.pidfile,
                                    detach_process=self.detach_process,
                                    stdout=self.stdout,
                                    stderr=self.stderr,
                                    uid=self.uid,
                                    gid=self.gid,
                                    signal_map=self.get_signal_map())
        self.init_logger()
Пример #11
0
def chellow_command():
    parser = argparse.ArgumentParser()
    parser.add_argument("action", choices=["start", "stop", "restart"])
    args = parser.parse_args()

    try:
        os.makedirs(app.instance_path)
    except BaseException:
        pass
    pidfile_path = os.path.join(app.instance_path, "chellow.pid")
    pidfile = PidFile(pidfile_path)
    daemon = DaemonContext(pidfile=pidfile,
                           stdin=sys.stdin,
                           stderr=sys.stderr,
                           stdout=sys.stdout)

    if args.action == "start":
        chellow_start(daemon)
    elif args.action == "stop":
        chellow_stop(pidfile_path)
    elif args.action == "restart":
        chellow_stop(pidfile_path)
        chellow_start(daemon)
Пример #12
0
 def start(self):
     console_log = logging.StreamHandler()
     console_log.setLevel('DEBUG')
     self.log.addHandler(console_log)
     if not self._cfg_open():
         print("could not process config")
         sys.exit(1)
     daemon = DaemonContext(pidfile=PidFile(self.pid))
     if self.nodaemon:
         daemon.detach_process = False
     dlog = open(self.config.get('main', 'dlog_file'), 'w')
     daemon.stderr = dlog
     daemon.stdout = dlog
     daemon.open()
     signal.signal(signal.SIGHUP, self._reload)
     signal.signal(signal.SIGTERM, self._quit)
     self.log.removeHandler(console_log)
     self._run()
Пример #13
0
 def start(self, devel=False):
     self.config.read_file(open(self._config_file))
     self._config_dict = self._cfg_to_dict(self.config)
     try:
         jsonschema.validate(self.config_dict['main'], CHECK_CONFIG_MAIN)
     except jsonschema.exceptions.ValidationError as err:
         print("main section: {0}".format(err))
         sys.exit(1)
     if devel:
         self._app(devel=True)
         return
     daemon = DaemonContext(pidfile=PidFile(self.pid))
     if self.nodaemon:
         daemon.detach_process = False
     dlog = open(self.config.get('main', 'dlog'), 'w')
     daemon.stderr = dlog
     daemon.stdout = dlog
     daemon.open()
     self._app()
Пример #14
0
class DaemonBase(DaemonStartupConfigureMixin, LoggerMixin, SignalHandleMixin,
                 CliInteractionMixin):

    STATUS_EXIT_OK = 0
    STATUS_EXIT_ERROR = 1

    def __init__(self,
                 app=None,
                 pid_path=None,
                 work_directory=None,
                 uid=None,
                 gid=None):
        super(DaemonBase, self).__init__()

        self.app = app
        self.pid_path = pid_path if pid_path else self.config['pidfile']
        self.pidfile = PidFile(pid_path) if pid_path else PidFile(
            self.config['pidfile'])
        self.work_directory = work_directory if work_directory else self.config[
            'work_directory']
        self.stdout = sys.stdout if not self.config['detach_process'] else None
        self.stderr = sys.stderr if not self.config['detach_process'] else None
        self.detach_process = self.config['detach_process']
        self.uid = uid if uid else self.config['uid']
        self.gid = gid if gid else self.config['gid']

        self.daemon = DaemonContext(working_directory=self.work_directory,
                                    pidfile=self.pidfile,
                                    detach_process=self.detach_process,
                                    stdout=self.stdout,
                                    stderr=self.stderr,
                                    uid=self.uid,
                                    gid=self.gid,
                                    signal_map=self.get_signal_map())
        self.init_logger()

    def get_logger_name(self):
        return 'daemon.log'

    def get_log_level(self):
        return logging.DEBUG

    def get_logger_handlers(self):
        handlers = super(DaemonBase, self).get_logger_handlers()
        if not self.config['detach_process']:
            sh = logging.StreamHandler(self.stdout)
            sh.setLevel(self.get_log_level())
            sh.setFormatter(self.get_handler_formatter())
            handlers.append(sh)

        return handlers

    def get_argparser(self):
        parser = super(DaemonBase, self).get_argparser()
        parser.add_argument('action',
                            choices=['start', 'stop', 'reload'],
                            help='Action')
        return parser

    def parse_cli_options(self, args):
        options = super(DaemonBase, self).parse_cli_options(args)
        options['action'] = args.action
        return options

    def daemon_stop(self):
        self.log_info('Stopping daemon...')
        pid = None
        if os.path.exists(self.pid_path):
            with open(self.pid_path, 'r') as pidfile:
                pidfile.seek(0)
                pid = int(pidfile.readline())
                self.log_info(
                    'Attempt shutdown process #{pid}'.format(pid=pid))
                try:
                    stop_process(pid)
                except ProcessLookupError as e:
                    self.log_info(
                        'Can not shutdown process with pid {}. Pid file exists but process missing'
                        .format(pid))
                    sys.exit(self.STATUS_EXIT_OK)

            attempts = 30
            while attempts:
                if not os.path.exists(self.pid_path):
                    sys.exit(self.STATUS_EXIT_OK)
                attempts -= 1
                time.sleep(1)

        if os.path.exists(self.pid_path):
            self.log_error('Can not shutdown daemon. Pid: {}'.format(pid))
        else:
            self.log_info('Daemon stopped.')
        sys.exit(self.STATUS_EXIT_OK)

    def daemon_start(self):
        """
        Dummy action for keep follow start daemon logic
        :return:
        """
        self.log_info('Start daemon')
        pass

    def daemon_reload(self):
        self.log_info('Action reload daemon not implemented')
        sys.exit(self.STATUS_EXIT_OK)

    def get_handlers(self):
        return {
            'start': self.daemon_start,
            'stop': self.daemon_stop,
            'reload': self.daemon_reload
        }

    def get_app(self):
        if self.app is None:
            raise ImproperlyConfigured(
                '{cls}: Missing app property.'.format(cls=self.__class__))
        return self.app

    def handle_jobs(self):
        app = self.get_app()
        app()

    def _is_force_mode(self):
        return self.config.get('force', False)

    def _check_uid(self):
        if self.uid == 0 and not self._is_force_mode():
            return False
        return True

    def daemonize(self):
        # stop logging for parent process
        self.clear_logger_handlers()
        self.log_info('test')
        try:
            self.daemon.open()
            try:
                # reinit logger after fork
                self.init_logger()
            except Exception as e:
                sys.__stdout__.write(
                    'Can not reinitializate logger for destination {dest}. Error: {err}, backtrace: {traceback}'
                    .format(dest=self.get_logfile_name(),
                            err=e,
                            traceback=traceback.format_exc()))
                self.daemon.close()
                sys.exit(self.STATUS_EXIT_ERROR)
        except DaemonError as e:
            msg = "Error occurred during fork, error: {message}, stacktrace: {traceback}".format(
                message=e, traceback=traceback.format_exc())
            print(msg)
            self.log_error(msg)
            sys.exit(self.STATUS_EXIT_ERROR)

    def terminate(self):
        self.log_info('Release resources...')
        self.daemon.close()
        self.log_info('Exit from process.')
        sys.exit(self.STATUS_EXIT_OK)

    def run(self):
        self.handle_action(self.config['action'])

        if not self._check_uid():
            msg = 'Detected attempt run process from root. For run daemon under root use -f or --force option.'
            print(msg)
            self.log_warn(msg)
            sys.exit(0)

        self.daemonize()
        self.log_info('Running...')
        self.log_info('Try handling jobs')

        try:
            self.handle_jobs()
        except Exception as e:
            self.log_error(
                'Error occurred: {err}, traceback: {traceback}'.format(
                    err=e, traceback=traceback.format_exc()))
        finally:
            self.log_info(
                'Shutdown master process: {pid}'.format(pid=os.getpid()))
            self.terminate()
class App:

    config = None
    db = None
    ser = None
    logger = None
    loggerfh = None
    cursor = None
    daemon = None

    def reload_program_config(self,signum, frame):
        conf=self.readConfig(self._config_file)
        if conf is not None:
            self.config=conf
            self.close_resources()
            self.openConnections()
            self.createLogger()

    def terminate(self,signum, frame):
        self.logger.info("terminate")

    def readConfig(self,conf_file=None):
        config = SafeConfigParser()
        if (conf_file is None):
            conf_file = 'read_kwh_pulse_mysql.ini'
        config.read(conf_file)
        confData = {}
        #Mandatory configurations
        try:
            mysqlData = {}
            mysqlData['host'] = config.get('mysql', 'host')
            mysqlData['user'] = config.get('mysql', 'user')
            mysqlData['passwd'] = config.get('mysql', 'passwd')
            mysqlData['database'] = config.get('mysql', 'database')

            serialData = {}
            serialData['device'] = config.get('serial', 'device')

            daemonData = {}
            groupname = config.get('daemon', 'group')
            daemonData['groupid'] = grp.getgrnam(groupname)[2]


        except NoSectionError:
            if self.daemon is not None and self.daemon.is_open:
                self.logger.error("Error in "+str(conf_file))
                return None
            else:
                print ('Error in '+conf_file)
                exit()

        #Optional configurations
        loggerData = {}
        try:
            try:
                loggerData['formatter'] = config.get('logger', 'formatter')
            except  NoOptionError:
                loggerData['formatter'] = None
            try:
                loggerData['file'] = config.get('logger', 'file')
            except  NoOptionError:
                loggerData['file'] = None
            try:
                loggerData['level'] = config.get('logger', 'level')
            except  NoOptionError:
                loggerData['level'] = None
        except NoSectionError:
            loggerData['formatter'] = None
            loggerData['file'] = None
            loggerData['level'] = None

        confData['mysql'] = mysqlData
        confData['serial'] = serialData
        confData['logger'] = loggerData
        confData['daemon'] = daemonData
        if self.daemon is not None and self.daemon.is_open:
            self.logger.info("Config loaded from " + str(conf_file))
        else:
            print("Config loaded from " + str(conf_file))
        return confData

    def __init__(self, cfg, pid, nodaemon):
        self._config_file = cfg
        self._pid = pid
        self._nodaemon = nodaemon

    def program_cleanup(self,signum, frame):
        self.logger.info('Program cleanup')
        self.close_resources()
        raise SystemExit('Terminating on signal {0}'.format(signum))

    def close_resources(self):
        if self.db is not None:
            self.cursor.close(

            )
            self.db.close()
        if self.ser is not None:
            self.ser.close()

    def createLogger(self):
        loggerConf = self.config['logger']
        if self.logger is None:
            self.logger = logging.getLogger('PulseReader')

        formatter = logging.Formatter("%(asctime)s - %(name)s - %(levelname)s - %(message)s" if loggerConf["formatter"]==None else loggerConf["formatter"])
        if self.loggerfh is not None:
            self.loggerfh.close()
            self.logger.removeHandler(self.loggerfh)
        self.loggerfh = logging.FileHandler("/var/log/pulsereader/pulsereader.log" if loggerConf["file"]==None else loggerConf["file"])
        self.loggerfh.setFormatter(formatter)
        self.logger.addHandler(self.loggerfh)
        level = {
            "CRITICAL": logging.CRITICAL,
            "ERROR": logging.ERROR,
            "WARNING": logging.WARNING,
            "INFO": logging.INFO,
            "DEBUG": logging.DEBUG,
            "NOTSET": logging.NOTSET
        }
        self.logger.setLevel(level.get(loggerConf["level"],logging.INFO))
        self.logger.debug('Logger created.')

    def openConnections(self):
        self.logger.debug("openConnections")
        # connect
        mysqlConf = self.config['mysql']
        self.logger.debug("MySql "+str(mysqlConf))
        if mysqlConf['host']!='None':
            self.db = MySQLdb.connect(host=mysqlConf['host'], user=mysqlConf['user'], passwd=mysqlConf['passwd'],
                                      db=mysqlConf['database'])
            self.logger.info("Connected to MySql")
            # create a cursor
            self.cursor = self.db.cursor()
        else:
            self.db = None
            self.logger.info('MySql host None, not connected.')

        try:
            serialConfig = self.config['serial']
            self.logger.debug("Serial " + str(serialConfig))
            # configure the serial connections (the parameters differs on the device you are connecting to)
            self.ser = serial.Serial(
                port=serialConfig['device'],
                baudrate=9600,
                parity=serial.PARITY_NONE,
                stopbits=serial.STOPBITS_ONE,
                bytesize=serial.EIGHTBITS
            )
            if not self.ser.isOpen():
                self.logger.error("Serial did not open " + str(serialConfig))
            # Arduinos bootloader prints a newline somewhere in boot, wait for it
            # TODO put in conf
            time.sleep(10)
            out = ""
            while self.ser.inWaiting() > 0:
                out += self.ser.read(1)
            self.logger.info('Serial is open. ' + serialConfig['device'])
            self.logger.debug("Serial output:"+out)
        except:
            self.logger.error(sys.exc_info()[0])
            self.logger.error(sys.exc_info()[1])
            self.logger.error(sys.exc_info()[2])
            raise

    def run(self):
        self.openConnections()
        self.logger.debug("Run")
        # pulse counter
        counter1 = 0
        counter2 = 0

        # sensorid of kWh counter
        sensorId1 = 116  # MLP
        sensorId2 = 115  # total

        # input from arduino "Counters: n,n"
        inputPattern = re.compile('Counters: (\\d*),(\\d*)',re.MULTILINE)
        self.logger.debug("Is serial open "+str(self.ser.isOpen()))

        self.logger.debug("Start")
        while True:
            try:
                time.sleep(59)

                self.logger.debug("Request counter values")
                #request counter values
                self.ser.write('GET\n')
                out = ''
                # let's wait one second before reading output (let's give device time to answer)
                time.sleep(1)
                while self.ser.inWaiting() > 0:
                    out += self.ser.read(1)
                if out != '':
                    m = inputPattern.match(out)
                    self.logger.debug("Got '"+out+"'")
                    if m:
                        counter1 = int(m.group(1))
                        counter2 = int(m.group(2))
                    else:
                        self.logger.warn("No count "+out)

                self.logger.debug(time.strftime('%H:%M') + ' ' + str(counter1) + ' ' + str(sensorId1) + ' ' + str(counter2) + ' ' + str(sensorId2))

                if self.db is not None:
                    self.logger.debug("Insert values")
                    self.cursor.execute(
                        'INSERT INTO data (sensorid,time,value) VALUES (%s,str_to_date(date_format(now(),"%%d.%%m.%%Y %%H:%%i"),"%%d.%%m.%%Y %%H:%%i"), %s)',
                        (sensorId1, counter1))
                    self.cursor.execute(
                        'INSERT INTO data (sensorid,time,value) VALUES (%s,str_to_date(date_format(now(),"%%d.%%m.%%Y %%H:%%i"),"%%d.%%m.%%Y %%H:%%i"), %s)',
                        (sensorId2, counter2))
                    self.cursor.execute('COMMIT')
                else:
                    self.logger.debug("No database, not inserted.")
                counter1 = 0
                counter2 = 0
            except:
                self.logger.error(sys.exc_info()[0])
                self.logger.error(sys.exc_info()[1])
                self.logger.error(sys.exc_info()[2])
                raise

    @property
    def config(self):
        return self._config

    @config.setter
    def config(self, value):
        'setting'
        self._config = value

    @property
    def pid(self):
        return self._pid


    @property
    def nodaemon(self):
        return self._nodaemon


    def stop(self):
        try:
            pid = open(self.pid).readline()
        except IOError:
            print("Daemon already gone, or pidfile was deleted manually")
            sys.exit(1)
        print("terminating Daemon with Pid: {0}".format(pid))
        os.kill(int(pid), signal.SIGTERM)
        sys.stdout.write("Waiting...")
        while os.path.isfile(self.pid):
            sys.stdout.write(".")
            sys.stdout.flush()
            time.sleep(0.5)
        print("Gone")

    def reload(self):
        try:
            pid = open(self.pid).readline()
        except IOError:
            print("Daemon not running, or pidfile was deleted manually")
            sys.exit(1)
        print("Sending SIGUSR1 to Daemon with Pid: {0}".format(pid))
        os.kill(int(pid), signal.SIGUSR1)
        sys.stdout.write("Ok")

    def start(self):
        self.config=self.readConfig(self._config_file)
        self.daemon = DaemonContext(pidfile=PidFile(self.pid)
                               ,signal_map={
            signal.SIGTERM: self.program_cleanup,
            signal.SIGHUP: self.terminate,
            signal.SIGUSR1: self.reload_program_config},
                                    gid=self.config["daemon"]["groupid"])
        if self.nodaemon:
            self.daemon.detach_process = False
#            daemon.stderr = "/tmp/pulse_err.out"
#            daemon.stdout = "/tmp/pulset.out"
        try:
            self.daemon.open()
            self.createLogger()
            self.logger.debug('After open')
            self.run()
        except:
            print ("Unexpected error:", sys.exc_info()[0])
            raise
Пример #16
0
class DaemonBase(DaemonStartupConfigureMixin, LoggerMixin, SignalHandleMixin, CliInteractionMixin):

    STATUS_EXIT_OK = 0
    STATUS_EXIT_ERROR = 1

    def __init__(self, app=None, pid_path=None, work_directory=None, uid=None, gid=None):
        super(DaemonBase, self).__init__()

        self.app = app
        self.pid_path = pid_path if pid_path else self.config['pidfile']
        self.pidfile = PidFile(pid_path) if pid_path else PidFile(self.config['pidfile'])
        self.work_directory = work_directory if work_directory else self.config['work_directory']
        self.stdout = sys.stdout if not self.config['detach_process'] else None
        self.stderr = sys.stderr if not self.config['detach_process'] else None
        self.detach_process = self.config['detach_process']
        self.uid = uid if uid else self.config['uid']
        self.gid = gid if gid else self.config['gid']

        self.daemon = DaemonContext(working_directory=self.work_directory,
                                    pidfile=self.pidfile,
                                    detach_process=self.detach_process,
                                    stdout=self.stdout,
                                    stderr=self.stderr,
                                    uid=self.uid,
                                    gid=self.gid,
                                    signal_map=self.get_signal_map())
        self.init_logger()

    def get_logger_name(self):
        return 'daemon.log'

    def get_log_level(self):
        return logging.DEBUG

    def get_logger_handlers(self):
        handlers = super(DaemonBase, self).get_logger_handlers()
        if not self.config['detach_process']:
            sh = logging.StreamHandler(self.stdout)
            sh.setLevel(self.get_log_level())
            sh.setFormatter(self.get_handler_formatter())
            handlers.append(sh)

        return handlers

    def get_argparser(self):
        parser = super(DaemonBase, self).get_argparser()
        parser.add_argument('action', choices=['start', 'stop', 'reload'], help='Action')
        return parser

    def parse_cli_options(self, args):
        options = super(DaemonBase, self).parse_cli_options(args)
        options['action'] = args.action
        return options

    def daemon_stop(self):
        self.log_info('Stopping daemon...')
        pid = None
        if os.path.exists(self.pid_path):
            with open(self.pid_path, 'r') as pidfile:
                pidfile.seek(0)
                pid = int(pidfile.readline())
                self.log_info('Attempt shutdown process #{pid}'.format(pid=pid))
                try:
                    stop_process(pid)
                except ProcessLookupError as e:
                    self.log_info('Can not shutdown process with pid {}. Pid file exists but process missing'.format(pid))
                    sys.exit(self.STATUS_EXIT_OK)

            attempts = 30
            while attempts:
                if not os.path.exists(self.pid_path):
                    sys.exit(self.STATUS_EXIT_OK)
                attempts -= 1
                time.sleep(1)

        if os.path.exists(self.pid_path):
            self.log_error('Can not shutdown daemon. Pid: {}'.format(pid))
        else:
            self.log_info('Daemon stopped.')
        sys.exit(self.STATUS_EXIT_OK)

    def daemon_start(self):
        """
        Dummy action for keep follow start daemon logic
        :return:
        """
        self.log_info('Start daemon')
        pass

    def daemon_reload(self):
        self.log_info('Action reload daemon not implemented')
        sys.exit(self.STATUS_EXIT_OK)

    def get_handlers(self):
        return {
            'start': self.daemon_start,
            'stop': self.daemon_stop,
            'reload': self.daemon_reload
        }

    def get_app(self):
        if self.app is None:
            raise ImproperlyConfigured('{cls}: Missing app property.'.format(cls=self.__class__))
        return self.app

    def handle_jobs(self):
        app = self.get_app()
        app()

    def _is_force_mode(self):
        return self.config.get('force', False)

    def _check_uid(self):
        if self.uid == 0 and not self._is_force_mode():
            return False
        return True

    def daemonize(self):
        # stop logging for parent process
        self.clear_logger_handlers()
        self.log_info('test')
        try:
            self.daemon.open()
            try:
                # reinit logger after fork
                self.init_logger()
            except Exception as e:
                sys.__stdout__.write(
                    'Can not reinitializate logger for destination {dest}. Error: {err}, backtrace: {traceback}'.format(
                        dest=self.get_logfile_name(), err=e, traceback=traceback.format_exc()
                    ))
                self.daemon.close()
                sys.exit(self.STATUS_EXIT_ERROR)
        except DaemonError as e:
            msg = "Error occurred during fork, error: {message}, stacktrace: {traceback}".format(
                message=e, traceback=traceback.format_exc()
            )
            print(msg)
            self.log_error(msg)
            sys.exit(self.STATUS_EXIT_ERROR)

    def terminate(self):
        self.log_info('Release resources...')
        self.daemon.close()
        self.log_info('Exit from process.')
        sys.exit(self.STATUS_EXIT_OK)

    def run(self):
        self.handle_action(self.config['action'])

        if not self._check_uid():
            msg = 'Detected attempt run process from root. For run daemon under root use -f or --force option.'
            print(msg)
            self.log_warn(msg)
            sys.exit(0)

        self.daemonize()
        self.log_info('Running...')
        self.log_info('Try handling jobs')

        try:
            self.handle_jobs()
        except Exception as e:
            self.log_error('Error occurred: {err}, traceback: {traceback}'.format(
                err=e, traceback=traceback.format_exc()
            ))
        finally:
            self.log_info('Shutdown master process: {pid}'.format(pid=os.getpid()))
            self.terminate()
Пример #17
0
    type=int) # default=12000
parser.add_argument("-a", "--bindaddress", help="IP Address to bind to") # default='0.0.0.0'
parser.add_argument("-f", "--config", help="Use this config file", default='/etc/local/adcpiv2.conf')
parser.add_argument("-m", "--daemon", help="Run in daemon mode (background)", action="store_true")
parser.add_argument("-s", "--graphiteServer", help="Set the graphite server name", action="store_true")
parser.add_argument("-r", "--graphitePort", help="Set the port to send data to on the graphite server", action="store_true")

# Go grab all the command line options
args = parser.parse_args()

# If daemon option was specified, background ourselves immediately
if (args.daemon):
    pid='/var/run/{}.pid'.format(os.path.basename(__file__))

    pidfile = PidFile(pid)
    daemon = DaemonContext(pidfile=pidfile,detach_process=False,stdout=sys.stdout,stderr=sys.stderr)
    # we could have written this also as:
    # daemon.pidfile = pidfile
    print ('{}: Backgrounding'.format(os.path.basename(__file__)))
    daemon.open()
else:
    print ('{}: Not backgrounding'.format(os.path.basename(__file__)))

print ('{} pid : {}'.format(os.path.basename(__file__),os.getpid()))
# Start logging
numeric_level = getattr(logging, args.loglevel.upper(), None)
if not isinstance(numeric_level, int):
    raise ValueError('Invalid log level: %s' % loglevel)

logFormatter = logging.Formatter('%(asctime)s %(filename)s %(process)s %(levelname)s %(message)s')