From: Michael Tremer Date: Fri, 5 Mar 2021 11:28:47 +0000 (+0000) Subject: Remove old shell module X-Git-Tag: 0.9.28~1285^2~630 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=cade4c46f5a6e312b8884fffaf7f02f93cb7156d;p=pakfire.git Remove old shell module Signed-off-by: Michael Tremer --- diff --git a/Makefile.am b/Makefile.am index f823a2a25..c15625ead 100644 --- a/Makefile.am +++ b/Makefile.am @@ -129,7 +129,6 @@ pakfire_PYTHON = \ src/pakfire/hub.py \ src/pakfire/i18n.py \ src/pakfire/logger.py \ - src/pakfire/shell.py \ src/pakfire/system.py \ src/pakfire/util.py diff --git a/src/pakfire/shell.py b/src/pakfire/shell.py deleted file mode 100644 index 2c3376013..000000000 --- a/src/pakfire/shell.py +++ /dev/null @@ -1,265 +0,0 @@ -#!/usr/bin/python3 -############################################################################### -# # -# Pakfire - The IPFire package management system # -# Copyright (C) 2012 Pakfire development team # -# # -# This program is free software: you can redistribute it and/or modify # -# it under the terms of the GNU General Public License as published by # -# the Free Software Foundation, either version 3 of the License, or # -# (at your option) any later version. # -# # -# This program is distributed in the hope that it will be useful, # -# but WITHOUT ANY WARRANTY; without even the implied warranty of # -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # -# GNU General Public License for more details. # -# # -# You should have received a copy of the GNU General Public License # -# along with this program. If not, see . # -# # -############################################################################### - -import fcntl -import os -import select -import subprocess -import time - -from pakfire.i18n import _ -import pakfire.util as util -from .errors import * - -class ShellExecuteEnvironment(object): - def __init__(self, command, cwd=None, chroot_path=None, shell=False, timeout=0, env=None, - cgroup=None, logger=None, log_output=True, log_errors=True, record_output=False, record_stdout=True, record_stderr=True): - # The given command that should be executed. - self.command = command - - # Change into current working dir. - self.cwd = cwd - - # Chroot into this directory. - self.chroot_path = chroot_path - - # The logger where all the output goes. - self.logger = logger - - # Set timeout. - self.timeout = timeout - - # Shell. - self.shell = shell - self.env = env - - # cgroup to which the newly created process should be attached. - self.cgroup = cgroup - - # Timestamp, when execution has been started and ended. - self.time_start = None - self.time_end = None - - # Output, that has to be returned. - self.output = "" - self.record_output = record_output - self.record_stdout = record_stdout - self.record_stderr = record_stderr - - # Log the output and errors? - self.log_errors = log_errors - self.log_output = log_output - - # Exit code of command. - self.exitcode = None - - def execute(self): - # Save start time. - self.time_start = time.time() - - if self.logger: - self.logger.debug(_("Executing command: %s in %s") % (self.command, self.chroot_path or "/")) - - child = None - try: - # Create new child process - child = self.create_subprocess() - - # Record the output. - self.tee_log(child) - except: - # In case there has been an error, kill children if they aren't done - if child and child.returncode is None: - os.killpg(child.pid, 9) - - try: - if child: - os.waitpid(child.pid, 0) - except: - pass - - # Raise original exception. - raise - - finally: - # Save end time. - self.time_end = time.time() - - # wait until child is done, kill it if it passes timeout - nice_exit = True - while child.poll() is None: - if self.timeout_has_been_exceeded(): - nice_exit = False - os.killpg(child.pid, 15) - - if self.timeout_has_been_exceeded(3): - nice_exit = False - os.killpg(child.pid, 9) - - if not nice_exit: - raise commandTimeoutExpired(_("Command exceeded timeout (%(timeout)d): %(command)s") % (self.timeout, self.command)) - - # Save exitcode. - self.exitcode = child.returncode - - if self.logger: - self.logger.debug(_("Child returncode was: %s") % self.exitcode) - - if self.exitcode and self.log_errors: - raise ShellEnvironmentError(_("Command failed: %s") % self.command, self.exitcode) - - return self.exitcode - - def create_subprocess(self): - # Create preexecution thingy for command - preexec_fn = ChildPreExec(self.chroot_path, self.cwd) - - kwargs = { - "bufsize" : 0, - "close_fds" : True, - "env" : self.env, - "preexec_fn" : preexec_fn, - "shell" : self.shell, - } - - # File descriptors. - stdin = open("/dev/null", "r") - - if self.record_stdout: - stdout = subprocess.PIPE - else: - stdout = open("/dev/null", "w") - - if self.record_stderr: - stderr = subprocess.PIPE - else: - stderr = open("/dev/null", "w") - - kwargs.update({ - "stdin" : stdin, - "stdout" : stdout, - "stderr" : stderr, - }) - - child = subprocess.Popen(self.command, **kwargs) - - # If cgroup is given, attach the subprocess. - if self.cgroup: - self.cgroup.attach_task(child.pid) - - return child - - def timeout_has_been_exceeded(self, offset=0): - """ - Returns true when the command has been running - for more than 'timeout' seconds. - """ - # If no timeout has been configured, it can never be exceeded. - if not self.timeout: - return False - - # Check if the command has already been started. - if not self.time_start: - return False - - return (time.time() - self.time_start - offset) > self.timeout - - def tee_log(self, child): - fds = [] - - if self.record_stdout: - fds.append(child.stdout) - - if self.record_stderr: - fds.append(child.stderr) - - # Set all file descriptors as non-blocking. - for fd in fds: - # Skip already closed file descriptors. - if fd.closed: - continue - - flags = fcntl.fcntl(fd, fcntl.F_GETFL) - fcntl.fcntl(fd, fcntl.F_SETFL, flags | os.O_NONBLOCK) - - done = False - tail = "" - while not done: - # Check if timeout has been hit. - if self.timeout_has_been_exceeded(): - done = True - break - - # Start the select() call. - i_rdy, o_rdy, e_rdy = select.select(fds, [], [], 1) - - # Process output. - for s in i_rdy: - # Read as much data as possible. - input = s.read().decode() - - if input == "": - done = True - break - - if self.record_output: - self.output += input - - if self.log_output and self.logger: - lines = input.split("\n") - if tail: - lines[0] = tail + lines[0] - - # We may not have got all the characters of the last line. - tail = lines.pop() - - for line in lines: - self.logger.info(line) - - # Flush all handlers of the logger. - for h in self.logger.handlers: - h.flush() - - # Log the rest of the last line. - if tail and self.log_output and self.logger: - self.logger.info(tail) - - -class ChildPreExec(object): - def __init__(self, chroot_path, cwd): - self.chroot_path = chroot_path - self.cwd = cwd - - def __call__(self, *args, **kargs): - # Set a new process group - os.setpgrp() - - # Change into new root. - if self.chroot_path: - os.chdir(self.chroot_path) - os.chroot(self.chroot_path) - - # Change to cwd. - if self.cwd: - if not os.path.exists(self.cwd): - os.makedirs(self.cwd) - - os.chdir(self.cwd)