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()
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)
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()
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, 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()
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()
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') logging.basicConfig(filename=args.logfile, format='%(asctime)s %(filename)s %(process)s %(levelname)s %(message)s', level=numeric_level) if(args.debug):
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