def _try_generate_thumbnail(cls, ffmpeg, movie_path): logger = logging.getLogger(__name__) try: thumb_path = create_thumbnail_path(movie_path) commandline = settings().get( ["webcam", "ffmpegThumbnailCommandline"]) thumb_command_str = cls._create_ffmpeg_command_string( commandline=commandline, ffmpeg=ffmpeg, input=movie_path, output=thumb_path, fps=None, videocodec=None, threads=None, bitrate=None, ) c = CommandlineCaller() returncode, stdout_text, stderr_text = c.call(thumb_command_str, delimiter=b"\r", buffer_size=512) if returncode != 0: logger.warning("Failed to generate optional thumbnail %r: %s" % (returncode, stderr_text)) return True except Exception as ex: logger.warning( "Failed to generate thumbnail from {} to {} ({})".format( movie_path, thumb_path, ex)) return False
def run_system_command(command, password=None): logger = logging.getLogger( "octoprint.plugins.ws281x_led_status.commandline") caller = CommandlineCaller() try: if password: returncode, stdout, stderr = caller.call(command, input=password) else: returncode, stdout, stderr = caller.call(command) except Exception as e: logger.error("Error running command `{}`".format("".join(command))) logger.exception(e) return None, "exception" if returncode != 0: logger.error("Command for `{}` failed with return code {}".format( "".join(command), returncode)) logger.error("STDOUT: {}".format(stdout)) logger.error("STDOUT: {}".format(stderr)) error = "command" else: # Convert output to joined string instead of list stdout = "\n".join(stdout) stderr = "\n".join(stderr) if stderr and "Sorry" in stderr or "no password" in stdout: error = "password" else: error = None return stdout, error
def execute(): # we run this with shell=True since we have to trust whatever # our admin configured as command and since we want to allow # shell-alike handling here... return_code, stdout_lines, stderr_lines = CommandlineCaller().call( command_spec["command"], shell=True) if not do_ignore and return_code != 0: stdout = "\n".join(stdout_lines) stderr = "\n".join(stderr_lines) error = f"Command for {source}:{command} failed with return code {return_code}:\n\nSTDOUT:\n{stdout}\n\nSTDERR:\n{stderr}" logger.warning(prefix_multilines(error, prefix="! ")) if not do_async: raise CommandFailed(error)
def __init__(self, *args, **kwargs): click.MultiCommand.__init__(self, *args, **kwargs) from octoprint.util.commandline import CommandlineCaller from functools import partial def log_util(f): def log(*lines): for line in lines: f(line) return log self.command_caller = CommandlineCaller() self.command_caller.on_log_call = log_util(lambda x: click.echo(">> {}".format(x))) self.command_caller.on_log_stdout = log_util(click.echo) self.command_caller.on_log_stderr = log_util(partial(click.echo, err=True))
def restart_octoprint(self): command = self._octoprint_settings.get(["server", "commands", "serverRestartCommand"]) if not command: self._logger.warning("No command configured, can't restart") return caller = CommandlineCaller() try: code, stdout, stderr = caller.call(command, **{"shell": True}) # Use shell=True, as we have to trust user input except Exception as e: self._logger.error("Error calling command to restart server {}".format(command)) self._logger.exception(e) return if code != 0: self._logger.error("Non zero return code running '{}' to restart server: {}".format(command, code)) self._logger.exception("STDOUT: {}".format(stdout)) self._logger.exception("STDERR: {}".format(stderr))
def _get_caller(log_cb=None): def _log_call(*lines): _log(lines, prefix=" ", stream="call") def _log_stdout(*lines): _log(lines, prefix=">", stream="stdout") def _log_stderr(*lines): _log(lines, prefix="!", stream="stderr") def _log(lines, prefix=None, stream=None): if log_cb is None: return log_cb(lines, prefix=prefix, stream=stream) caller = CommandlineCaller() if log_cb is not None: caller.on_log_call = _log_call caller.on_log_stdout = _log_stdout caller.on_log_stderr = _log_stderr return caller
def _do_copy_log(self): # Get the name of the tarball we're going to copy the log # files to. tarball_filename = self.build_tarball_filename() self._log("tarball = <%s>" % tarball_filename) # Get the location where we're going to save the tarball. logpath = self.find_logpath() self._log("logpath = <%s>" % logpath) # Build the full path to the tarball tarball_path = os.path.join(logpath, tarball_filename) self._log("tarball_path = <%s>" % tarball_path) # Get the names of the log files logfiles = self.get_log_file_names() self._log("logfiles = <%s>" % logfiles) # Now build the command. command = "tar cvf %s %s" % (tarball_path, logfiles) self._log("command = <%s>" % command) # Construct a commandline caller to run the tar command. caller = CommandlineCaller() caller.on_log_call = self.display_call_stdout caller.on_log_stdout = self.display_call_stdout caller.on_log_stderr = self.display_stderr # Execute the command. self.display("") caller.call(command) # Finish off with a message stating that the tarball has been # created. done_message = "Logs copied to file \"%s\"" % tarball_path self._log(done_message) self.display("\n" + done_message) self.display("")
def _render(self): """Rendering runnable.""" ffmpeg = settings().get(["webcam", "ffmpeg"]) commandline = settings().get(["webcam", "ffmpegCommandline"]) bitrate = settings().get(["webcam", "bitrate"]) if ffmpeg is None or bitrate is None: self._logger.warning( "Cannot create movie, path to ffmpeg or desired bitrate is unset" ) return if self._videocodec == "mpeg2video": extension = "mpg" else: extension = "mp4" input = os.path.join( self._capture_dir, self._capture_format.format( prefix=self._prefix, postfix=self._postfix if self._postfix is not None else "", ), ) output_name = self._output_format.format( prefix=self._prefix, postfix=self._postfix if self._postfix is not None else "", extension=extension, ) temporary = os.path.join(self._output_dir, ".{}".format(output_name)) output = os.path.join(self._output_dir, output_name) for i in range(4): if os.path.exists(input % i): break else: self._logger.warning("Cannot create a movie, no frames captured") self._notify_callback( "fail", output, returncode=0, stdout="", stderr="", reason="no_frames" ) return hflip = settings().getBoolean(["webcam", "flipH"]) vflip = settings().getBoolean(["webcam", "flipV"]) rotate = settings().getBoolean(["webcam", "rotate90"]) watermark = None if settings().getBoolean(["webcam", "watermark"]): watermark = os.path.join( os.path.dirname(__file__), "static", "img", "watermark.png" ) if sys.platform == "win32": # Because ffmpeg hiccups on windows' drive letters and backslashes we have to give the watermark # path a special treatment. Yeah, I couldn't believe it either... watermark = watermark.replace("\\", "/").replace(":", "\\\\:") # prepare ffmpeg command command_str = self._create_ffmpeg_command_string( commandline, ffmpeg, self._fps, bitrate, self._threads, input, temporary, self._videocodec, hflip=hflip, vflip=vflip, rotate=rotate, watermark=watermark, ) self._logger.debug("Executing command: {}".format(command_str)) with self.render_job_lock: try: self._notify_callback("start", output) self._logger.debug("Parsing ffmpeg output") c = CommandlineCaller() c.on_log_stderr = self._process_ffmpeg_output returncode, stdout_text, stderr_text = c.call( command_str, delimiter=b"\r", buffer_size=512 ) self._logger.debug("Done with parsing") if returncode == 0: shutil.move(temporary, output) self._notify_callback("success", output) else: self._logger.warning( "Could not render movie, got return code %r: %s" % (returncode, stderr_text) ) self._notify_callback( "fail", output, returncode=returncode, stdout=stdout_text, stderr=stderr_text, reason="returncode", ) except Exception: self._logger.exception("Could not render movie due to unknown error") self._notify_callback("fail", output, reason="unknown") finally: try: if os.path.exists(temporary): os.remove(temporary) except Exception: self._logger.warning( "Could not delete temporary timelapse {}".format(temporary) ) self._notify_callback("always", output)
def __init__(self): self._logger = logging.getLogger(__name__) self._caller = CommandlineCaller()
def __init__(self, simply_print): self.simply_print = simply_print self._logger = logging.getLogger( "octoprint.plugins.SimplyPrint.comm.startup") self.startup_thread = None self.command_line = CommandlineCaller()