def run_module_command(module_name, cmd): """ Run a command listed in the "commands" section, for the module, other than "start" of course, which is a *special* command. Please note that the module should be trusted when running this command, otherwise bad stuff can happen. Return if the command was successful, or if there was no command to run (meaning that if no entry for that command is specified, this function returns true). """ conf = get_config(module_name) if 'commands' not in conf or cmd not in conf['commands']: return True # run command ret = True cwd = os.getcwd() try: os.chdir(path.module_directory(module_name)) log_file = open(path.log_file(module_name), 'a') sp.check_call(conf['commands'][cmd], stdout=log_file, stderr=log_file, shell=True) except (sp.CalledProcessError, OSError) as e: logger.exception(e) ret = False finally: log_file.close() os.chdir(cwd) return ret
def execm(module_name, daemonize=True): """ Start a new module identified by its name *module_name*. The current processus is killed at the end of the module when it's not a daemon. If it is, the current processus is killed immediately. Use *invoke* instead if you want to create a new killable process. """ child_proc = None def signal_handler(signum, frame): """ Signal handler. If no child was created, it does nothing. Else, it broadcasts the signal to the child. """ logger.info('Received signal %s, broadcasting it to child' % signum) if child_proc is not None: child_proc.send_signal(signum) child_proc.wait() # Check that only one instance is running at the same time pid_file = path.pid_file(module_name) if os.path.exists(pid_file): raise RuntimeError('A pid file already exists for this module') sys.exit(1) # Get the start command from the configuration file module_config = packaging.get_config(module_name) if not 'start' in module_config: raise RuntimeError( 'Missing "start" entry in the module\'s configuration file') sys.exit(1) start_cmd = module_config['start'] # Add our bin directory to the PATH variable os.environ['PATH'] = path.bin_directory() + ':' + os.environ['PATH'] # Daemon or not Daemon ? if daemonize: # Create a daemon daemon.possess_me() # Redirect stdout and stderr into a log file sys.stdout = open(path.log_file(module_name), 'a') sys.stderr = sys.stdout # Change the directory to the module directory os.chdir(path.module_directory(module_name)) # Prepare to receive signal SIGINT and SIGTERM signal.signal(signal.SIGINT, signal_handler) signal.signal(signal.SIGTERM, signal_handler) return_code = 0 try: # Write the new daemon pid in a new file with open(pid_file, 'w') as f: f.write(str(os.getpid())) f.flush() except (OSError, IOError) as e: return_code = 1 else: # Execute the start command logger.info('Starting the module `%s`', module_name) try: child_proc = sp.Popen(shlex.split(start_cmd)) except OSError as e: logger.exception(e) return_code = 1 else: return_code = child_proc.wait() finally: # Remove the pid file and return the corresponding code logger.info('Shutting down the module `%s`', module_name) os.remove(pid_file) sys.exit(return_code) sys.exit(0)