diff --git a/supervisord.conf_template b/supervisord.conf_template index 0277cbe9d0fac799ad84842cae8925c01c67f2ab_c3VwZXJ2aXNvcmQuY29uZl90ZW1wbGF0ZQ==..477cbfec34ebde35dd8d888fc70970d8ee517dac_c3VwZXJ2aXNvcmQuY29uZl90ZW1wbGF0ZQ== 100644 --- a/supervisord.conf_template +++ b/supervisord.conf_template @@ -2,6 +2,8 @@ nodaemon = false user = system command = dev:[dir]supervisord.com +stdout_file=dev:[dir]supervisord.log +logfile=dev:[dir]supervisord_log.log [program:firstpgm] # default image to loginout # image=SYS$SYSTEM:LOGINOUT.EXE diff --git a/supervisord.py b/supervisord.py index 0277cbe9d0fac799ad84842cae8925c01c67f2ab_c3VwZXJ2aXNvcmQucHk=..477cbfec34ebde35dd8d888fc70970d8ee517dac_c3VwZXJ2aXNvcmQucHk= 100644 --- a/supervisord.py +++ b/supervisord.py @@ -453,7 +453,7 @@ if error is not None: logger.warning( f"Can' create process {self.process_name}, error {error}" - ) + ) lib.set_logical( self.process_name + b'_PID', hex(pid)[2:].upper(), @@ -828,6 +828,78 @@ start_timer() +def is_deamon() -> bool: + try: + pid = lib.get_logical( + b'SUPERVISORD' + b'_PID', + supervisord_table_name, + )[1] + cpid = lib.getjpi(jpidef.JPI__PID)[3] + return pid == cpid + except OSError as e: + if e.errno != ssdef.SS__NOLOGNAM: + raise + return False + + +def daemon_is_running() -> bool: + try: + v = lib.get_logical( + b'SUPERVISORD' + b'_PID', + supervisord_table_name, + )[1] + pid = int(v, 16) + lib.getjpi(jpidef.JPI__PID, pid) + return True + except OSError as e: + if e.errno == ssdef.SS__SUSPENDED: + return True + if e.errno == ssdef.SS__NONEXPR: + return False + raise + + +def daemonize(usrdaemon: str, comdaemon: str, stdout_file: str) -> int | None: + userpro = starlet.create_user_profile(usrnam=usrdaemon)[1] + persona_id = starlet.persona_create(usrpro=userpro)[1] + persona_previous_id = starlet.persona_assume(persona_id)[1] + error = None + try: + stsflg = ( + prcdef.PRC_M_IMPERSONATE + | prcdef.PRC_M_PARSE_EXTENDED + | prcdef.PRC_M_KT_LIMIT + | prcdef.PRC_M_HIBER + ) + + pid = PidType( + starlet.creprc( + image=b'SYS$SYSTEM:LOGINOUT.EXE', + input=comdaemon.encode(), + output=stdout_file.encode(), + prcnam=b'SUPERVISORD', + kt_limit=1, + baspri=4, + stsflg=stsflg, + )[1] + ) + lib.set_logical( + b'SUPERVISORD' + b'_PID', + hex(pid)[2:].upper(), + supervisord_table_name, + ) + starlet.wake(pid) + return pid + except OSError as e: + error = e + return None + finally: + starlet.persona_assume(persona_previous_id) + starlet.persona_delete(persona_id) + if error is not None: + print(f"Can' create process SUPERVISORD, error {error}") + + def main(): global logger, supervisorctl_pwd @@ -831,19 +903,6 @@ def main(): global logger, supervisorctl_pwd - logging_format = '%(asctime)s - %(name)s - %(levelname)s - %(message)s' - logging.basicConfig( - filename='/dev/null', level=logging.INFO, format=logging_format - ) - formatter = logging.Formatter(logging_format) - main_log = logging.getLogger() # root handler - main_log.setLevel(logging.INFO) - handler = logging.handlers.TimedRotatingFileHandler( - 'supervisord.log', 'midnight', backupCount=10 - ) - handler.setFormatter(formatter) - main_log.addHandler(handler) - # Required privileges: ALTPRI, SYSNAM, PRMMBX, IMPERSONATE, SETPRV, WORLD starlet.setprv( 1, @@ -878,6 +937,37 @@ config.read_file(args.configuration) args.configuration.close() + nodaemon = config['supervisord'].getboolean('nodaemon', False) + if not nodaemon and not is_deamon(): + usrdaemon = config['supervisord'].get('user', 'system') + stdout_file = config['supervisord'].get('stdout_file', 'NLA0:') + comdaemon = config['supervisord']['command'] + pid = daemonize(usrdaemon, comdaemon, stdout_file) + if pid is None: + print('Unable to start supervisord daemon') + else: + print(f'Daemon started {hex(pid)[2:].upper()}') + exit(0) + + logfile = config['supervisord'].get('logfile', 'supervisord.log') + + logging_format = '%(asctime)s - %(name)s - %(levelname)s - %(message)s' + logging.basicConfig( + filename='/dev/null', level=logging.INFO, format=logging_format + ) + formatter = logging.Formatter(logging_format) + main_log = logging.getLogger() # root handler + main_log.setLevel(logging.INFO) + logfn = crtl.from_vms(logfile) + if logfn is None: + print(f'{repr(logfile)} is invalid') + crtl.vms_exit(ssdef.SS__INVARG) + handler = logging.handlers.TimedRotatingFileHandler( + logfn, 'midnight', backupCount=10 + ) + handler.setFormatter(formatter) + main_log.addHandler(handler) + for sn in config.sections(): if sn.startswith('program:'): quotaslst = [