From 7b03dd3da4462947cfc45458b13e05d8a4cf2b10 Mon Sep 17 00:00:00 2001 From: computergeek125 Date: Sat, 13 Feb 2021 05:47:30 +0000 Subject: [PATCH 1/4] forward-port the noshell branch from 3.x --- app/classes/shared/server.py | 42 ++++++++---------------------------- app/config/version.json | 4 ++-- 2 files changed, 11 insertions(+), 35 deletions(-) diff --git a/app/classes/shared/server.py b/app/classes/shared/server.py index 6f5c27ec..1df9c2d3 100644 --- a/app/classes/shared/server.py +++ b/app/classes/shared/server.py @@ -120,47 +120,23 @@ class Server: console.info("Launching Server {} with command {}".format(self.name, self.server_command)) if os.name == "nt": - logger.info("Windows Detected - launching cmd") + logger.info("Windows Detected") self.server_command = self.server_command.replace('\\', '/') - logging.info("Opening CMD prompt") - self.process = pexpect.popen_spawn.PopenSpawn('cmd \r\n', timeout=None, encoding=None) - - drive_letter = self.server_path[:1] - - if drive_letter.lower() != "c": - logger.info("Server is not on the C drive, changing drive letter to {}:".format(drive_letter)) - self.process.send("{}:\r\n".format(drive_letter)) - - logging.info("changing directories to {}".format(self.server_path.replace('\\', '/'))) - self.process.send('cd {} \r\n'.format(self.server_path.replace('\\', '/'))) - logging.info("Sending command {} to CMD".format(self.server_command)) - self.process.send(self.server_command + "\r\n") - - self.is_crashed = False else: - logger.info("Linux Detected - launching Bash") - self.process = pexpect.popen_spawn.PopenSpawn('/bin/bash \n', timeout=None, encoding=None) + logger.info("Linux Detected") - logger.info("Changing directory to {}".format(self.server_path)) - self.process.send('cd {} \n'.format(self.server_path)) - - logger.info("Sending server start command: {} to shell".format(self.server_command)) - self.process.send(self.server_command + '\n') - self.is_crashed = False + logger.info("Starting server in {p} with command: {c}".format(p=self.server_path, c=self.server_command)) + self.is_crashed = False ts = time.time() self.start_time = str(datetime.datetime.fromtimestamp(ts).strftime('%Y-%m-%d %H:%M:%S')) if psutil.pid_exists(self.process.pid): - parent = psutil.Process(self.process.pid) - time.sleep(.5) - children = parent.children(recursive=True) - for c in children: - self.PID = c.pid - logger.info("Server {} running with PID {}".format(self.name, self.PID)) - console.info("Server {} running with PID {}".format(self.name, self.PID)) - self.is_crashed = False - stats.record_stats() + self.PID = self.process.pod + logger.info("Server {} running with PID {}".format(self.name, self.PID)) + console.info("Server {} running with PID {}".format(self.name, self.PID)) + self.is_crashed = False + stats.record_stats() else: logger.warning("Server PID {} died right after starting - is this a server config issue?".format(self.PID)) console.warning("Server PID {} died right after starting - is this a server config issue?".format(self.PID)) diff --git a/app/config/version.json b/app/config/version.json index 35afb1e0..67dbc605 100644 --- a/app/config/version.json +++ b/app/config/version.json @@ -1,5 +1,5 @@ { "major": 4, "minor": 0, - "sub": "Alpha 2" -} \ No newline at end of file + "sub": "Alpha 2+noshell" +} From 90465410f898a2181e67784158ff8737e4a88e0d Mon Sep 17 00:00:00 2001 From: computergeek125 Date: Sat, 13 Feb 2021 06:00:28 +0000 Subject: [PATCH 2/4] Forgot to start the process. You saw nothing --- app/classes/shared/server.py | 1 + 1 file changed, 1 insertion(+) diff --git a/app/classes/shared/server.py b/app/classes/shared/server.py index 1df9c2d3..4ef5982c 100644 --- a/app/classes/shared/server.py +++ b/app/classes/shared/server.py @@ -126,6 +126,7 @@ class Server: logger.info("Linux Detected") logger.info("Starting server in {p} with command: {c}".format(p=self.server_path, c=self.server_command)) + self.process = pexpect.popen_spawn.PopenSpawn(self.server_command, cwd=self.server_path, timeout=None, encoding=None) self.is_crashed = False ts = time.time() From d2c81eafe0b49a4de7aa5c167579bdfba26c3ce2 Mon Sep 17 00:00:00 2001 From: computergeek125 Date: Sat, 13 Feb 2021 06:02:27 +0000 Subject: [PATCH 3/4] These are not the typos you're looking for --- app/classes/shared/server.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/classes/shared/server.py b/app/classes/shared/server.py index 4ef5982c..c5de8105 100644 --- a/app/classes/shared/server.py +++ b/app/classes/shared/server.py @@ -133,7 +133,7 @@ class Server: self.start_time = str(datetime.datetime.fromtimestamp(ts).strftime('%Y-%m-%d %H:%M:%S')) if psutil.pid_exists(self.process.pid): - self.PID = self.process.pod + self.PID = self.process.pid logger.info("Server {} running with PID {}".format(self.name, self.PID)) console.info("Server {} running with PID {}".format(self.name, self.PID)) self.is_crashed = False From a0448f54083dfed6b51a04914f9b3c172b8c1966 Mon Sep 17 00:00:00 2001 From: computergeek125 Date: Sat, 6 Mar 2021 14:48:02 -0600 Subject: [PATCH 4/4] Theoretically this fixes tasks scheduler --- app/classes/shared/cmd.py | 7 +++-- app/classes/shared/controller.py | 1 - app/classes/shared/server.py | 17 ++++++---- app/classes/shared/tasks.py | 3 -- app/classes/web/panel_handler.py | 4 +-- main.py | 53 ++++++++++++++++++++++---------- 6 files changed, 54 insertions(+), 31 deletions(-) diff --git a/app/classes/shared/cmd.py b/app/classes/shared/cmd.py index a46c1b49..ea2bae32 100644 --- a/app/classes/shared/cmd.py +++ b/app/classes/shared/cmd.py @@ -9,7 +9,6 @@ logger = logging.getLogger(__name__) from app.classes.shared.console import console from app.classes.shared.helpers import helper -from app.classes.shared.tasks import tasks_manager try: import requests @@ -25,6 +24,10 @@ class MainPrompt(cmd.Cmd): # overrides the default Prompt prompt = "Crafty Controller v{} > ".format(helper.get_version_string()) + def __init__(self, tasks_manager): + super().__init__() + self.tasks_manager = tasks_manager + @staticmethod def emptyline(): pass @@ -45,7 +48,7 @@ class MainPrompt(cmd.Cmd): console.info("Stopping all server daemons / threads - This may take a few seconds") self._clean_shutdown() while True: - if tasks_manager.get_main_thread_run_status(): + if self.tasks_manager.get_main_thread_run_status(): sys.exit(0) time.sleep(1) diff --git a/app/classes/shared/controller.py b/app/classes/shared/controller.py index 65be08f2..3b93d5cb 100644 --- a/app/classes/shared/controller.py +++ b/app/classes/shared/controller.py @@ -135,7 +135,6 @@ class Controller: def stop_all_servers(self): servers = self.list_running_servers() - print(servers) logger.info("Found {} running server(s)".format(len(servers))) console.info("Found {} running server(s)".format(len(servers))) diff --git a/app/classes/shared/server.py b/app/classes/shared/server.py index c5de8105..421e2437 100644 --- a/app/classes/shared/server.py +++ b/app/classes/shared/server.py @@ -19,7 +19,7 @@ logger = logging.getLogger(__name__) try: - from pexpect.popen_spawn import PopenSpawn + import pexpect except ModuleNotFoundError as e: logger.critical("Import Error: Unable to load {} module".format(e, e.name)) @@ -126,7 +126,7 @@ class Server: logger.info("Linux Detected") logger.info("Starting server in {p} with command: {c}".format(p=self.server_path, c=self.server_command)) - self.process = pexpect.popen_spawn.PopenSpawn(self.server_command, cwd=self.server_path, timeout=None, encoding=None) + self.process = pexpect.spawn(self.server_command, cwd=self.server_path, timeout=None, encoding=None) self.is_crashed = False ts = time.time() @@ -178,13 +178,13 @@ class Server: if x >= 30: logger.info("Server {} is still running - Forcing the process down".format(server_name)) console.info("Server {} is still running - Forcing the process down".format(server_name)) - self.killpid(server_pid) + self.process.terminate(force=True) logger.info("Stopped Server {} with PID {}".format(server_name, server_pid)) console.info("Stopped Server {} with PID {}".format(server_name, server_pid)) else: - self.killpid(self.PID) + self.process.terminate(force=True) # massive resetting of variables self.cleanup_server_object() @@ -217,10 +217,15 @@ class Server: return running try: - running = psutil.pid_exists(self.PID) + alive = self.process.isalive() + if type(alive) is not bool: + self.last_rc = alive + running = False + else: + running = alive except Exception as e: - logger.error("Unable to find if server PID exists: {}".format(self.PID)) + logger.error("Unable to find if server PID exists: {}".format(self.PID), exc_info=True) pass return running diff --git a/app/classes/shared/tasks.py b/app/classes/shared/tasks.py index 237d850c..8ac0c2fd 100644 --- a/app/classes/shared/tasks.py +++ b/app/classes/shared/tasks.py @@ -132,6 +132,3 @@ class TasksManager: logger.info("Scheduling Serverjars.com cache refresh service every 12 hours") schedule.every(12).hours.do(server_jar_obj.refresh_cache) - - -tasks_manager = TasksManager() diff --git a/app/classes/web/panel_handler.py b/app/classes/web/panel_handler.py index c380ff5d..27ab5af9 100644 --- a/app/classes/web/panel_handler.py +++ b/app/classes/web/panel_handler.py @@ -302,7 +302,7 @@ class PanelHandler(BaseHandler): user_data = json.loads(self.get_secure_cookie("user_data")) exec_user = db_helper.get_user(user_data['user_id']) - if not exec_user.superuser: + if not exec_user['superuser']: self.redirect("/panel/error?error=Unauthorized access: not superuser") return False elif server_id is None: @@ -546,4 +546,4 @@ class PanelHandler(BaseHandler): "Edited role {} (RID:{}) with servers {}".format(role_name, role_id, servers), server_id=0, source_ip=self.get_remote_ip()) - self.redirect("/panel/panel_config") \ No newline at end of file + self.redirect("/panel/panel_config") diff --git a/main.py b/main.py index 7ef4b02f..d905f842 100644 --- a/main.py +++ b/main.py @@ -11,6 +11,7 @@ from app.classes.shared.helpers import helper from app.classes.shared.models import installer from app.classes.shared.controller import controller +from app.classes.shared.tasks import TasksManager from app.classes.shared.cmd import MainPrompt @@ -68,6 +69,11 @@ if __name__ == '__main__': help="Sets logging level to debug." ) + parser.add_argument('-d', '--daemon', + action='store_true', + help="Runs Crafty in daemon mode (no prompt)" + ) + args = parser.parse_args() helper.ensure_logging_setup() @@ -91,15 +97,6 @@ if __name__ == '__main__': installer.create_tables() installer.default_settings() - # now the tables are created, we can load the tasks_manger - from app.classes.shared.tasks import tasks_manager - - tasks_manager.start_webserver() - tasks_manager.start_scheduler() - - # slowing down reporting just for a 1/2 second so messages look cleaner - time.sleep(.5) - # init servers logger.info("Initializing all servers defined") console.info("Initializing all servers defined") @@ -107,6 +104,15 @@ if __name__ == '__main__': controller.init_all_servers() servers = controller.list_defined_servers() + # now the tables are created, we can load the tasks_manger + tasks_manager = TasksManager() + + tasks_manager.start_webserver() + tasks_manager.start_scheduler() + + # slowing down reporting just for a 1/2 second so messages look cleaner + time.sleep(.5) + # start stats logging tasks_manager.start_stats_recording() @@ -116,11 +122,24 @@ if __name__ == '__main__': # this should always be last tasks_manager.start_main_kill_switch_watcher() - Crafty = MainPrompt() - Crafty.cmdloop() - - # our main loop - eventually a shell - # while True: - # if tasks_manager.get_main_thread_run_status(): - # sys.exit(0) - # time.sleep(1) + Crafty = MainPrompt(tasks_manager) + if not args.daemon: + Crafty.cmdloop() + else: + print("Crafty started in daemon mode, no shell will be printed") + while True: + try: + if tasks_manager.get_main_thread_run_status(): + break + time.sleep(1) + except KeyboardInterrupt: + logger.info("Recieved SIGTERM, stopping Crafty") + break + + logger.info("Stopping all server daemons / threads") + console.info("Stopping all server daemons / threads - This may take a few seconds") + Crafty._clean_shutdown() + while True: + if tasks_manager.get_main_thread_run_status(): + sys.exit(0) + time.sleep(1)