Beispiel #1
0
    def stop_scan_cleanup(
            self,
            kbdb: BaseDB,
            scan_id: str,
            ovas_process: psutil.Popen,  # pylint: disable=arguments-differ
    ):
        """Set a key in redis to indicate the wrapper is stopped.
        It is done through redis because it is a new multiprocess
        instance and it is not possible to reach the variables
        of the grandchild process.
        Indirectly sends SIGUSR1 to the running openvas scan process
        via an invocation of openvas with the --scan-stop option to
        stop it."""

        if kbdb:
            # Set stop flag in redis
            kbdb.stop_scan(scan_id)

            # Check if openvas is running
            if ovas_process.is_running():
                # Cleaning in case of Zombie Process
                if ovas_process.status() == psutil.STATUS_ZOMBIE:
                    logger.debug(
                        '%s: Process with PID %s is a Zombie process.'
                        ' Cleaning up...',
                        scan_id,
                        ovas_process.pid,
                    )
                    ovas_process.wait()
                # Stop openvas process and wait until it stopped
                else:
                    can_stop_scan = Openvas.stop_scan(
                        scan_id,
                        not self.is_running_as_root and self.sudo_available,
                    )
                    if not can_stop_scan:
                        logger.debug(
                            'Not possible to stop scan process: %s.',
                            ovas_process,
                        )
                        return

                    logger.debug('Stopping process: %s', ovas_process)

                    while ovas_process.is_running():
                        if ovas_process.status() == psutil.STATUS_ZOMBIE:
                            ovas_process.wait()
                        else:
                            time.sleep(0.1)
            else:
                logger.debug(
                    "%s: Process with PID %s already stopped",
                    scan_id,
                    ovas_process.pid,
                )

            # Clean redis db
            for scan_db in kbdb.get_scan_databases():
                self.main_db.release_database(scan_db)
Beispiel #2
0
def run_subprocess(
    command: Sequence[str],
    shell: bool = False,
    doexec: bool = True,
    monitor_log: logging.Logger = None,
    monitor_interval: int = 5,
    tile_id: str = None,
) -> bool:
    """Runs a subprocess with `psutil.Popen` and monitors its status.

    If subprocess returns non-zero exit code, STDERR is sent to the log.

    :param command: The command to execute.
    :param shell: Passed to `psutil.Popen`. Defaults to False.
    :param doexec: Do execute the subprocess or just print out the concatenated
        command. Used for testing.
    :param monitor_log: A resource logger, which is returned by
        :func:`~.recorder.configure_resource_logging`.
    :param monitor_interval: How often query the resource usage of the process?
        In seconds.
    :param tile_id: Used for monitoring only.
    :return: True/False on success/failure
    """
    if doexec:
        cmd = " ".join(command)
        if shell:
            command = cmd
        log.debug(f"Tile {tile_id} command: {command}")
        start = time()
        popen = Popen(command, shell=shell, stderr=PIPE, stdout=PIPE)
        if monitor_log is not None:
            while True:
                sleep(monitor_interval)
                monitor_log.info(
                    f"{tile_id}\t{popen.pid}\t{popen.cpu_times().user}"
                    f"\t{popen.memory_info().rss}")
                if (not popen.is_running() or popen.status() == STATUS_ZOMBIE
                        or popen.status() == STATUS_SLEEPING):
                    break
        stdout, stderr = popen.communicate()
        err = stderr.decode(getpreferredencoding(do_setlocale=True))
        out = stdout.decode(getpreferredencoding(do_setlocale=True))
        finish = time()
        log.info(f"Tile {tile_id} finished in {(finish-start)/60} minutes")
        if popen.returncode != 0:
            log.error(
                f"Tile {tile_id} process returned with {popen.returncode}")
        else:
            log.debug(
                f"Tile {tile_id} process returned with {popen.returncode}")
        log.debug(f"Tile {tile_id} stdout: \n{out}")
        log.debug(f"Tile {tile_id} stderr: \n{err}")
        return True if popen.returncode == 0 else False
    else:
        log.debug(f"Tile {tile_id} not executing {command}")
        return True
Beispiel #3
0
    def is_openvas_process_alive(openvas_process: psutil.Popen) -> bool:

        try:
            if openvas_process.status() == psutil.STATUS_ZOMBIE:
                logger.debug("Process is a Zombie, waiting for it to clean up")
                openvas_process.wait()
        except psutil.NoSuchProcess:
            return False

        return openvas_process.is_running()