#!/usr/bin/python3 import os import sys import signal import shutil import logging import tempfile import configparser from subprocess import Popen, PIPE ### функция перехвата сигнала от системы def receiveSignal(signalNumber, frame): print(f"I'm killed - {os.getpid()}") raise KeyboardInterrupt() ### функция для преобразования элемента в список def ini_item(value: str=""): tmp=value.split(',') if len(tmp) > 1: return tmp return value ### функция вычисления номера порта def set_port(value: list, c: int): if len(value) > 1: try: factor=int(value[2]) except Exception: factor=1 port=int(value[0])+1*factor*c if int(value[1])>int(value[0]) and port<=int(value[1]): return port elif c 0: c_ini = configparser.ConfigParser(strict=False) c_ini.optionxform = str # для правельного учета регистра # пробегаем парметры деррективы for key2, value in c_key: # разделяем ключ и значение c_param=ini_item(key2) # изменяем параметр if not c_param[0] in c_ini: c_ini[c_param[0]] = {} # дописываем индекс в название сервера if c_param[1] == 'ServerName' or c_param[1] == 'ClanMotto': value+=f" {server_id}" # обработка мараметра динамической конфигурации if c_param[1] == 'bUsedForTakeover': if int(value) > 0 and count < int(value): value="FALSE" else: value="TRUE" c_ini[c_param[0]][c_param[1]] = value # пишем изменения в файл with open(c_file_ini, "w") as f: c_ini.write(f) c_ini.clear() # запускаем бинарник сервера command=f"{cfg_settings['bin_server']} kf-bioticslab?Game={game}?Difficulty={dif} -Port={set_port(cfg_settings['port_game'], count)} -QueryPort={set_port(cfg_settings['port_query'], count)} -WebAdminPort={set_port(cfg_settings['port_webadmin'], count)} -ConfigSubDir={server_id}" # команды запуска while True: with Popen(command, stdout=PIPE, stderr=PIPE, shell=True, user=cfg_settings['sys_user'], group=cfg_settings['sys_group'], ) as process: # запускаем процесс от пользователя steam logging.info(f"Start: {command}") process.communicate() # ждём, пока работает процеес и есть вывод в терминал logging.info(f"Stop: {command}") except KeyboardInterrupt: None except Exception as err: logging.info(f"Unexpected termination: {err}") # при завершение подчищаем за собой tmp_dir.cleanup() try: shutil.rmtree(c_dir_ini, True) os.remove(c_dir_ini) except FileNotFoundError: None # убиваемся logging.info(f"Stop: {command}") os.killpg(os.getpgid(process.pid), signal.SIGINT) ### главная функция if __name__ == '__main__': sys.stderr = open('/dev/null') # ключи асоциативного массива c_args_name=['script', 'count', 'game', 'dif', 'config'] # если 2 аргумента, вызов из run скрипта if len(sys.argv) == 2: c_args_value=sys.argv[1].split() c_args_value.insert(0, sys.argv[0]) else: # если 4 аргумента, вызов из shell c_args_value=sys.argv # проверяем кол-во передынных параветров вызова if len(c_args_value) <= 4: print("Incorrect number of arguments") raise KeyError() # получаем ассоциативный массив аргументов c_args=dict(zip(c_args_name, c_args_value)) # перехватываем сигналы от системы signal.signal(signal.SIGHUP, receiveSignal) #signal.signal(signal.SIGINT, receiveSignal) signal.signal(signal.SIGQUIT, receiveSignal) signal.signal(signal.SIGILL, receiveSignal) signal.signal(signal.SIGTRAP, receiveSignal) signal.signal(signal.SIGABRT, receiveSignal) signal.signal(signal.SIGBUS, receiveSignal) signal.signal(signal.SIGFPE, receiveSignal) #signal.signal(signal.SIGKILL, receiveSignal) signal.signal(signal.SIGUSR1, receiveSignal) signal.signal(signal.SIGSEGV, receiveSignal) signal.signal(signal.SIGUSR2, receiveSignal) signal.signal(signal.SIGPIPE, receiveSignal) signal.signal(signal.SIGALRM, receiveSignal) signal.signal(signal.SIGTERM, receiveSignal) # запускаем экземпляр сервера daemon_server(int(c_args['count']), c_args['game'], int(c_args['dif']), c_args['config'])