globalisierung von pargs und logger

This commit is contained in:
2017-03-03 11:36:44 +01:00
parent b6ac0b450f
commit 67b359a30b
5 changed files with 99 additions and 89 deletions

View File

@@ -1,7 +1,7 @@
[DEFAULT] [DEFAULT]
autoreload=1 autoreload=1
autostart=1 autostart=1
plcprogram=test.py plcprogram=program.py
plcslave=0 plcslave=0
xmlrpc=1 xmlrpc=1
xmlrpcport=55123 xmlrpcport=55123

View File

@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE Project SYSTEM "Project-5.1.dtd"> <!DOCTYPE Project SYSTEM "Project-5.1.dtd">
<!-- eric project file for project revpipyload --> <!-- eric project file for project revpipyload -->
<!-- Saved: 2017-02-26, 18:35:15 --> <!-- Saved: 2017-03-03, 11:10:33 -->
<!-- Copyright (C) 2017 Sven Sager, akira@narux.de --> <!-- Copyright (C) 2017 Sven Sager, akira@narux.de -->
<Project version="5.1"> <Project version="5.1">
<Language>en_US</Language> <Language>en_US</Language>
@@ -9,7 +9,7 @@
<ProgLanguage mixed="0">Python3</ProgLanguage> <ProgLanguage mixed="0">Python3</ProgLanguage>
<ProjectType>Console</ProjectType> <ProjectType>Console</ProjectType>
<Description>Dieser Loader wird über das Init-System geladen und führt das angegebene Pythonprogramm aus. Es ist für den RevolutionPi gedacht um automatisch das SPS-Programm zu starten.</Description> <Description>Dieser Loader wird über das Init-System geladen und führt das angegebene Pythonprogramm aus. Es ist für den RevolutionPi gedacht um automatisch das SPS-Programm zu starten.</Description>
<Version>0.2.0</Version> <Version>0.2.1</Version>
<Author>Sven Sager</Author> <Author>Sven Sager</Author>
<Email>akira@narux.de</Email> <Email>akira@narux.de</Email>
<Eol index="-1"/> <Eol index="-1"/>

View File

@@ -8,6 +8,11 @@ from os import fork as osfork
from os.path import exists as ospexists from os.path import exists as ospexists
logapp = "revpipyloadapp.log"
logplc = "revpipyload.log"
logger = None
pargs = None
class ProgInit(): class ProgInit():
"""Programmfunktionen fuer Parameter und Logger.""" """Programmfunktionen fuer Parameter und Logger."""
@@ -30,7 +35,7 @@ class ProgInit():
) )
parser.add_argument( parser.add_argument(
"-c", "--conffile", dest="conffile", "-c", "--conffile", dest="conffile",
default="/etc/revpipyload/revpipyload.conf", default="revpipyload.conf",
help="Application configuration file" help="Application configuration file"
) )
parser.add_argument( parser.add_argument(
@@ -41,12 +46,13 @@ class ProgInit():
"-v", "--verbose", action="count", dest="verbose", "-v", "--verbose", action="count", dest="verbose",
help="Switch on verbose logging" help="Switch on verbose logging"
) )
self.pargs = parser.parse_args() global pargs
pargs = parser.parse_args()
# Prüfen ob als Daemon ausgeführt werden soll # Prüfen ob als Daemon ausgeführt werden soll
self.pidfile = "/var/run/revpipyload.pid" self.pidfile = "/var/run/revpipyload.pid"
self.pid = 0 self.pid = 0
if self.pargs.daemon: if pargs.daemon:
# Prüfen ob daemon schon läuft # Prüfen ob daemon schon läuft
if ospexists(self.pidfile): if ospexists(self.pidfile):
raise SystemError( raise SystemError(
@@ -54,41 +60,48 @@ class ProgInit():
self.pidfile self.pidfile
) )
) )
else:
self.pid = osfork()
if self.pid > 0:
with open(self.pidfile, "w") as f:
f.write(str(self.pid))
exit(0)
# Ausgaben umhängen in Logfile self.pid = osfork()
sys.stdout = open("/var/log/revpipyload", "a") if self.pid > 0:
sys.stderr = sys.stdout with open(self.pidfile, "w") as f:
f.write(str(self.pid))
exit(0)
global logapp
global logplc
# Ausgaben umhängen in Logfile
logapp = "/var/log/revpipyloadapp"
logplc = "/var/log/revpipyload"
pargs.conffile = "/etc/revpipyload/revpipyload.conf"
sys.stdout = open(logplc, "a")
sys.stderr = sys.stdout
# Initialize configparser globalconfig # Initialize configparser globalconfig
self.globalconffile = self.pargs.conffile self.globalconffile = pargs.conffile
self.globalconfig = ConfigParser() self.globalconfig = ConfigParser()
self.globalconfig.read(self.pargs.conffile) self.globalconfig.read(pargs.conffile)
# Program logger # Program logger
self.logger = logging.getLogger() global logger
logger = logging.getLogger()
logformat = logging.Formatter( logformat = logging.Formatter(
"{asctime} [{levelname:8}] {message}", "{asctime} [{levelname:8}] {message}",
datefmt="%Y-%m-%d %H:%M:%S", style="{" datefmt="%Y-%m-%d %H:%M:%S", style="{"
) )
lhandler = logging.StreamHandler(sys.stdout) lhandler = logging.StreamHandler(sys.stdout)
lhandler.setFormatter(logformat) lhandler.setFormatter(logformat)
self.logger.addHandler(lhandler) logger.addHandler(lhandler)
if self.pargs.logfile is not None: if pargs.logfile is not None:
lhandler = logging.FileHandler(filename=self.pargs.logfile) lhandler = logging.FileHandler(filename=pargs.logfile)
lhandler.setFormatter(logformat) lhandler.setFormatter(logformat)
self.logger.addHandler(lhandler) logger.addHandler(lhandler)
# Loglevel auswerten # Loglevel auswerten
if self.pargs.verbose is None: if pargs.verbose is None:
loglevel = logging.WARNING loglevel = logging.WARNING
elif self.pargs.verbose == 1: elif pargs.verbose == 1:
loglevel = logging.INFO loglevel = logging.INFO
elif self.pargs.verbose > 1: elif pargs.verbose > 1:
loglevel = logging.DEBUG loglevel = logging.DEBUG
self.logger.setLevel(loglevel) logger.setLevel(loglevel)

View File

@@ -1,7 +1,7 @@
#!/usr/bin/python3 #!/usr/bin/python3
# #
# RevPiPyLoad # RevPiPyLoad
# Version: 0.2.0 # Version: 0.2.1
# #
# Webpage: https://revpimodio.org/ # Webpage: https://revpimodio.org/
# (c) Sven Sager, License: LGPLv3 # (c) Sven Sager, License: LGPLv3
@@ -22,18 +22,16 @@ class LogReader():
def __init__(self): def __init__(self):
self.fhapp = None self.fhapp = None
self.logapp = "/var/log/revpipyloadapp"
self.posapp = 0 self.posapp = 0
self.fhplc = None self.fhplc = None
self.logplc = "/var/log/revpipyload"
self.posplc = 0 self.posplc = 0
def get_applines(self): def get_applines(self):
if not os.access(self.logapp, os.R_OK): if not os.access(proginit.logapp, os.R_OK):
return None return None
else: else:
if self.fhapp is None or self.fhapp.closed: if self.fhapp is None or self.fhapp.closed:
self.fhapp = open(self.logapp) self.fhapp = open(proginit.logapp)
lst_new = [] lst_new = []
while True: while True:
@@ -47,20 +45,20 @@ class LogReader():
return lst_new return lst_new
def get_applog(self): def get_applog(self):
if not os.access(self.logapp, os.R_OK): if not os.access(proginit.logapp, os.R_OK):
return None return None
else: else:
if self.fhapp is None or self.fhapp.closed: if self.fhapp is None or self.fhapp.closed:
self.fhapp = open(self.logapp) self.fhapp = open(proginit.logapp)
self.fhapp.seek(0) self.fhapp.seek(0)
return self.fhapp.read() return self.fhapp.read()
def get_plclines(self): def get_plclines(self):
if not os.access(self.logplc, os.R_OK): if not os.access(proginit.logplc, os.R_OK):
return None return None
else: else:
if self.fhplc is None or self.fhplc.closed: if self.fhplc is None or self.fhplc.closed:
self.fhplc = open(self.logplc) self.fhplc = open(proginit.logplc)
lst_new = [] lst_new = []
while True: while True:
@@ -74,41 +72,40 @@ class LogReader():
return lst_new return lst_new
def get_plclog(self): def get_plclog(self):
if not os.access(self.logplc, os.R_OK): if not os.access(proginit.logplc, os.R_OK):
return None return None
else: else:
if self.fhplc is None or self.fhplc.closed: if self.fhplc is None or self.fhplc.closed:
self.fhplc = open(self.logplc) self.fhplc = open(proginit.logplc)
self.fhplc.seek(0) self.fhplc.seek(0)
return self.fhplc.read() return self.fhplc.read()
class RevPiPlc(Thread): class RevPiPlc(Thread):
def __init__(self, pargs, logger, program): def __init__(self, program):
super().__init__() super().__init__()
self.autoreload = False self.autoreload = False
self._evt_exit = Event() self._evt_exit = Event()
self.exitcode = 0 self.exitcode = 0
self._lst_proc = shlex.split("/usr/bin/env python3 -u " + program) self._lst_proc = shlex.split("/usr/bin/env python3 -u " + program)
self._logger = logger
self._pargs = pargs
self._procplc = None self._procplc = None
self.zeroonexit = False self.zeroonexit = False
def run(self): def run(self):
# Prozess starten # Prozess starten
self._logger.info("start plc program") proginit.logger.info("start plc program")
fh = None fh = None
if self._pargs.daemon: if proginit.pargs.daemon:
if os.access("/var/log", os.R_OK | os.W_OK): if os.access(os.path.dirname(proginit.logapp), os.R_OK | os.W_OK):
fh = "/var/log/revpipyloadapp" fh = proginit.logapp
elif self._pargs.logfile is not None: elif proginit.pargs.logfile is not None:
fh = self._pargs.logfile fh = proginit.pargs.logfile
if fh is not None: if fh is not None:
fh = open(fh, "a") fh = open(fh, "a")
fh.write("started {}\n".format(asctime())) fh.write("-" * 40)
fh.write("\nplc app started: {}\n".format(asctime()))
fh.flush() fh.flush()
# Prozess erstellen # Prozess erstellen
@@ -125,21 +122,21 @@ class RevPiPlc(Thread):
if self.exitcode > 0: if self.exitcode > 0:
# PLC Python Programm abgestürzt # PLC Python Programm abgestürzt
self._logger.error( proginit.logger.error(
"plc program chrashed - exitcode: {}".format( "plc program chrashed - exitcode: {}".format(
self.exitcode self.exitcode
) )
) )
if self.zeroonexit: if self.zeroonexit and os.exists("/dev/piControl0"):
# piControl0 auf NULL setzen # piControl0 auf NULL setzen
f = open("/dev/piControl0", "w+b", 0) f = open("/dev/piControl0", "w+b", 0)
f.write(bytes(4096)) f.write(bytes(4096))
self._logger.warning("set piControl0 to ZERO") proginit.logger.warning("set piControl0 to ZERO")
else: else:
# PLC Python Programm sauber beendet # PLC Python Programm sauber beendet
self._logger.info("plc program did a clean exit") proginit.logger.info("plc program did a clean exit")
if not self._evt_exit.is_set() and self.autoreload: if not self._evt_exit.is_set() and self.autoreload:
# Prozess neu starten # Prozess neu starten
@@ -148,11 +145,11 @@ class RevPiPlc(Thread):
stderr=subprocess.STDOUT stderr=subprocess.STDOUT
) )
if self.exitcode == 0: if self.exitcode == 0:
self._logger.warning( proginit.logger.warning(
"restart plc program after clean exit" "restart plc program after clean exit"
) )
else: else:
self._logger.warning("restart plc program after crash") proginit.logger.warning("restart plc program after crash")
else: else:
break break
@@ -160,18 +157,18 @@ class RevPiPlc(Thread):
# Prozess beenden # Prozess beenden
count = 0 count = 0
self._logger.info("term plc program") proginit.logger.info("term plc program")
self._procplc.terminate() self._procplc.terminate()
while self._procplc.poll() is None and count < 10: while self._procplc.poll() is None and count < 10:
count += 1 count += 1
self._logger.debug( proginit.logger.debug(
"wait term plc program {} seconds".format(count * 0.5) "wait term plc program {} seconds".format(count * 0.5)
) )
sleep(0.5) sleep(0.5)
if self._procplc.poll() is None: if self._procplc.poll() is None:
self._logger.warning("can not term plc program") proginit.logger.warning("can not term plc program")
self._procplc.kill() self._procplc.kill()
self._logger.warning("killed plc program") proginit.logger.warning("killed plc program")
self.exitcode = self._procplc.poll() self.exitcode = self._procplc.poll()
@@ -208,14 +205,14 @@ class RevPiPyLoad(proginit.ProgInit):
self.evt_loadconfig.clear() self.evt_loadconfig.clear()
pauseproc = False pauseproc = False
if not self._exit: if not self._exit:
self.logger.info( proginit.logger.info(
"shutdown python plc program while getting new config" "shutdown python plc program while getting new config"
) )
self.stop() self.stop()
pauseproc = True pauseproc = True
# Konfigurationsdatei laden # Konfigurationsdatei laden
self.logger.info( proginit.logger.info(
"loading config file: {}".format(self.globalconffile) "loading config file: {}".format(self.globalconffile)
) )
self.globalconfig.read(self.globalconffile) self.globalconfig.read(self.globalconffile)
@@ -229,11 +226,11 @@ class RevPiPyLoad(proginit.ProgInit):
self.zeroonexit = int(self.globalconfig["DEFAULT"].get("zeroonexit", 1)) self.zeroonexit = int(self.globalconfig["DEFAULT"].get("zeroonexit", 1))
# PLC Thread konfigurieren # PLC Thread konfigurieren
self.plc = self.plcthread() self.plc = self._plcthread()
# XMLRPC-Server Instantiieren und konfigurieren # XMLRPC-Server Instantiieren und konfigurieren
if self.xmlrpc: if self.xmlrpc:
self.logger.debug("create xmlrpc server") proginit.logger.debug("create xmlrpc server")
self.xsrv = SimpleXMLRPCServer( self.xsrv = SimpleXMLRPCServer(
( (
"", "",
@@ -255,46 +252,46 @@ class RevPiPyLoad(proginit.ProgInit):
self.xsrv.register_function(self.xml_plcstop, "plcstop") self.xsrv.register_function(self.xml_plcstop, "plcstop")
self.xsrv.register_function(self.xml_plcupload, "plcupload") self.xsrv.register_function(self.xml_plcupload, "plcupload")
self.xsrv.register_function(self.xml_reload, "reload") self.xsrv.register_function(self.xml_reload, "reload")
self.logger.debug("created xmlrpc server") proginit.logger.debug("created xmlrpc server")
if pauseproc: if pauseproc:
self.logger.info( proginit.logger.info(
"start python plc program after getting new config" "start python plc program after getting new config"
) )
self.start() self.start()
def _plcthread(self):
"""Konfiguriert den PLC-Thread fuer die Ausfuehrung.
@returns: PLC-Thread Object"""
proginit.logger.debug("create PLC watcher")
th_plc = RevPiPlc(self.plcprog)
th_plc.autoreload = self.autoreload
th_plc.zeroonexit = self.zeroonexit
proginit.logger.debug("created PLC watcher")
return th_plc
def _sigexit(self, signum, frame): def _sigexit(self, signum, frame):
"""Signal handler to clean an exit program.""" """Signal handler to clean an exit program."""
self.logger.debug("got exit signal") proginit.logger.debug("got exit signal")
self.stop() self.stop()
def _sigloadconfig(self, signum, frame): def _sigloadconfig(self, signum, frame):
"""Signal handler to load configuration.""" """Signal handler to load configuration."""
self.logger.debug("got reload config signal") proginit.logger.debug("got reload config signal")
self.evt_loadconfig.set() self.evt_loadconfig.set()
def plcthread(self):
"""Konfiguriert den PLC-Thread fuer die Ausfuehrung.
@returns: PLC-Thread Object"""
self.logger.debug("create PLC watcher")
th_plc = RevPiPlc(self.pargs, self.logger, self.plcprog)
th_plc.autoreload = self.autoreload
th_plc.zeroonexit = self.zeroonexit
self.logger.debug("created PLC watcher")
return th_plc
def start(self): def start(self):
"""Start plcload and PLC python program.""" """Start plcload and PLC python program."""
self.logger.info("starting revpipyload") proginit.logger.info("starting revpipyload")
self._exit = False self._exit = False
if self.xmlrpc: if self.xmlrpc:
self.logger.info("start xmlrpc-server") proginit.logger.info("start xmlrpc-server")
self.tpe = futures.ThreadPoolExecutor(max_workers=1) self.tpe = futures.ThreadPoolExecutor(max_workers=1)
self.tpe.submit(self.xsrv.serve_forever) self.tpe.submit(self.xsrv.serve_forever)
if self.autostart: if self.autostart:
self.logger.info("starting plc program {}".format(self.plcprog)) proginit.logger.info("starting plc program {}".format(self.plcprog))
self.plc.start() self.plc.start()
while not self._exit \ while not self._exit \
@@ -302,20 +299,20 @@ class RevPiPyLoad(proginit.ProgInit):
self.evt_loadconfig.wait(1) self.evt_loadconfig.wait(1)
if not self._exit: if not self._exit:
self.logger.info("exit python plc program to reload config") proginit.logger.info("exit python plc program to reload config")
self._loadconfig() self._loadconfig()
def stop(self): def stop(self):
"""Stop PLC python program and plcload.""" """Stop PLC python program and plcload."""
self.logger.info("stopping revpipyload") proginit.logger.info("stopping revpipyload")
self._exit = True self._exit = True
self.logger.info("stopping plc program {}".format(self.plcprog)) proginit.logger.info("stopping plc program {}".format(self.plcprog))
self.plc.stop() self.plc.stop()
self.plc.join() self.plc.join()
if self.xmlrpc: if self.xmlrpc:
self.logger.info("shutting down xmlrpc-server") proginit.logger.info("shutting down xmlrpc-server")
self.xsrv.shutdown() self.xsrv.shutdown()
self.tpe.shutdown() self.tpe.shutdown()
self.xsrv.server_close() self.xsrv.server_close()
@@ -324,24 +321,24 @@ class RevPiPyLoad(proginit.ProgInit):
pass pass
def xml_plcexitcode(self): def xml_plcexitcode(self):
self.logger.debug("xmlrpc call plcexitcode") proginit.logger.debug("xmlrpc call plcexitcode")
return -1 if self.plc.is_alive() else self.plc.exitcode return -1 if self.plc.is_alive() else self.plc.exitcode
def xml_plcrunning(self): def xml_plcrunning(self):
self.logger.debug("xmlrpc call plcrunning") proginit.logger.debug("xmlrpc call plcrunning")
return self.plc.is_alive() return self.plc.is_alive()
def xml_plcstart(self): def xml_plcstart(self):
self.logger.debug("xmlrpc call plcstart") proginit.logger.debug("xmlrpc call plcstart")
if self.plc.is_alive(): if self.plc.is_alive():
return -1 return -1
else: else:
self.plc = self.plcthread() self.plc = self._plcthread()
self.plc.start() self.plc.start()
return self.plc.exitcode return self.plc.exitcode
def xml_plcstop(self): def xml_plcstop(self):
self.logger.debug("xmlrpc call plcstop") proginit.logger.debug("xmlrpc call plcstop")
self.plc.stop() self.plc.stop()
self.plc.join() self.plc.join()
return self.plc.exitcode return self.plc.exitcode
@@ -350,7 +347,7 @@ class RevPiPyLoad(proginit.ProgInit):
pass pass
def xml_reload(self): def xml_reload(self):
self.logger.debug("xmlrpc call reload") proginit.logger.debug("xmlrpc call reload")
self.evt_loadconfig.set() self.evt_loadconfig.set()

View File

@@ -27,7 +27,7 @@ setup(
license="LGPLv3", license="LGPLv3",
name="revpipyload", name="revpipyload",
version="0.2.0", version="0.2.1",
scripts=["data/revpipyload"], scripts=["data/revpipyload"],