import subprocess import os class Server(): def __init__(self, first_server_p, first_monitor_p, n_servers) -> None: try: import psutil self.check_running_servers(psutil, first_server_p, first_monitor_p, n_servers) except ModuleNotFoundError: print("Info: Cannot check if the server is already running, because the psutil module was not found") self.first_server_p = first_server_p self.n_servers = n_servers self.rcss_processes = [] first_monitor_p = first_monitor_p + 100 # makes it easier to kill test servers without affecting train servers cmd = "rcssservermj" for i in range(n_servers): port = first_server_p + i mport = first_monitor_p + i server_cmd = f"{cmd} --aport {port} --mport {mport} --no-render --no-realtime" self.rcss_processes.append( subprocess.Popen( server_cmd.split(), stdout=subprocess.DEVNULL, stderr=subprocess.STDOUT, start_new_session=True ) ) def check_running_servers(self, psutil, first_server_p, first_monitor_p, n_servers): ''' Check if any server is running on chosen ports ''' found = False p_list = [p for p in psutil.process_iter() if p.cmdline() and "rcssservermj" in " ".join(p.cmdline())] range1 = (first_server_p, first_server_p + n_servers) range2 = (first_monitor_p,first_monitor_p + n_servers) bad_processes = [] for p in p_list: # currently ignoring remaining default port when only one of the ports is specified (uncommon scenario) ports = [int(arg) for arg in p.cmdline()[1:] if arg.isdigit()] if len(ports) == 0: ports = [60000,60100] # default server ports (changing this is unlikely) conflicts = [str(port) for port in ports if ( (range1[0] <= port < range1[1]) or (range2[0] <= port < range2[1]) )] if len(conflicts)>0: if not found: print("\nThere are already servers running on the same port(s)!") found = True bad_processes.append(p) print(f"Port(s) {','.join(conflicts)} already in use by \"{' '.join(p.cmdline())}\" (PID:{p.pid})") if found: print() while True: inp = input("Enter 'kill' to kill these processes or ctrl+c to abort. ") if inp == "kill": for p in bad_processes: p.kill() return def kill(self): for p in self.rcss_processes: p.kill() print(f"Killed {self.n_servers} rcssservermj processes starting at {self.first_server_p}")