def run(base_dir, timeout): """run the program. return (ok?, msg)""" cmd = ['./a.out'] out_path = os.path.join(base_dir, 'test.out') in_path = os.path.join(base_dir, 'test.in') with open(out_path, 'w') as fout, open(in_path) as fin: p = Popen(cmd, stdin=fin, stdout=fout, cwd=base_dir) try: p.wait(timeout) except TimeoutExpired: p.kill() return False, 'time limit exceed' else: if p.returncode == 0: return True, '' else: return False, 'runtime error'
def makeMOBIWorker(item): item = item[0] kindlegenErrorCode = 0 kindlegenError = '' try: if os.path.getsize(item) < 629145600: output = Popen('kindlegen -dont_append_source -locale en "' + item + '"', stdout=PIPE, stderr=STDOUT, stdin=PIPE, shell=True) for line in output.stdout: line = line.decode('utf-8') # ERROR: Generic error if "Error(" in line: kindlegenErrorCode = 1 kindlegenError = line # ERROR: EPUB too big if ":E23026:" in line: kindlegenErrorCode = 23026 if kindlegenErrorCode > 0: break if ":I1036: Mobi file built successfully" in line: output.terminate() else: # ERROR: EPUB too big kindlegenErrorCode = 23026 return [kindlegenErrorCode, kindlegenError, item] except Exception as err: # ERROR: KCC unknown generic error kindlegenErrorCode = 1 kindlegenError = format(err) return [kindlegenErrorCode, kindlegenError, item]
def sshcmd_shell(self, dst, cmd): output = [] errors = [] ex = [ 'ssh', '-l root', '-q', '-o UserKnownHostsFile=/dev/null', '-o StrictHostKeyChecking=no', '-o ConnectTimeout=10', dst ] ex += cmd self.logger.debug("Execution list: %r", ex) execline = ' '.join(ex) self.logger.debug("Exec line: %r", execline) sp = Popen(execline, env=os.environ, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) out, err = sp.communicate() output = [l.strip() for l in out.decode('utf-8').split('\n') if len(l)] self.logger.debug("SSH CMD return code: %r", sp.returncode) return sp.returncode, output, errors
def shell_exec(args, cwd=None, stdout=PIPE, stderr=PIPE, stdin=PIPE): """ Wrapper for subprocess starting :param stderr: :param stdout: :param cwd: :param stdin: :type args: basestring or list :return: """ if isinstance(args, six.string_types): args = shlex.split(args) logging.getLogger(__name__).debug("Executing shell: %s", args) if platform.system() == 'Windows': return Popen(args, stdout=stdout, stderr=stderr, stdin=stdin, bufsize=0, cwd=cwd) else: return Popen(args, stdout=stdout, stderr=stderr, stdin=stdin, bufsize=0, preexec_fn=os.setpgrp, close_fds=True, cwd=cwd)
def __init__(self, ros_port, ws_port, uid): self.ros_port = ros_port self.ws_port = ws_port self.uid = uid self.vis = Popen( shlex.split('python start_ros.py {} {}'.format(ros_port, ws_port)))
def shell_exec(args, cwd=None, stdout=PIPE, stderr=PIPE, stdin=PIPE, shell=False, env=None): """ Wrapper for subprocess starting :param stderr: :param stdout: :param cwd: :param stdin: :type args: basestring or list :return: """ if stdout and not isinstance(stdout, int) and not isinstance(stdout, file_type): logging.warning("stdout is not IOBase: %s", stdout) stdout = None if stderr and not isinstance(stderr, int) and not isinstance(stderr, file_type): logging.warning("stderr is not IOBase: %s", stderr) stderr = None if isinstance(args, string_types) and not shell: args = shlex.split(args, posix=not is_windows()) logging.getLogger(__name__).debug("Executing shell: %s", args) if env: env = {k: str(v) for k, v in iteritems(env)} if is_windows(): return Popen(args, stdout=stdout, stderr=stderr, stdin=stdin, bufsize=0, cwd=cwd, shell=shell, env=env) else: return Popen(args, stdout=stdout, stderr=stderr, stdin=stdin, bufsize=0, preexec_fn=os.setpgrp, close_fds=True, cwd=cwd, shell=shell, env=env)
def _run(self): """Run McStas simulation executable. The current settings of the instrument parameters will be transferred to it. """ try: shutil.rmtree(self.mcstasdir) except (IOError, OSError): self.log.info('could not remove old data') command = '%s -n 1e8 -d %s %s' % (self.mcstasprog, self.mcstasdir, self._mcstas_params) self.log.debug('run %s', command) try: self._process = Popen(command.split(), stdout=PIPE, stderr=PIPE, cwd=self._workdir) out, err = self._process.communicate() if out: self.log.debug('McStas output:') for line in out.splitlines(): self.log.debug('[McStas] %s', line) if err: self.log.warning('McStas found some problems:') for line in err.splitlines(): self.log.warning('[McStas] %s', line) except OSError as e: self.log.error('Execution failed: %s', e) self._process.wait() self._process = None
def start_exec(self, command, work_dir: str = None, shell: bool = False, errors=(), successes=()): self.clean() logger.debug(f"Using work dir: {work_dir}") work_path = Path(work_dir) work_path.mkdir(exist_ok=True, parents=True) self.output_file = work_path / f"encoder_output_{secrets.token_hex(6)}.log" self.error_output_file = work_path / f"encoder_error_output_{secrets.token_hex(6)}.log" logger.debug(f"command output file set to: {self.output_file}") logger.debug(f"command error output file set to: {self.error_output_file}") self.output_file.touch(exist_ok=True) self.error_output_file.touch(exist_ok=True) self.error_message = errors self.success_message = successes logger.info(f"Running command: {command}") self.process = Popen( shlex.split(command.replace("\\", "\\\\")) if not shell and isinstance(command, str) else command, shell=shell, cwd=work_dir, stdout=open(self.output_file, "w"), stderr=open(self.error_output_file, "w"), stdin=PIPE, # FFmpeg can try to read stdin and wrecks havoc on linux encoding="utf-8", ) self.started_at = datetime.datetime.now(datetime.timezone.utc) Thread(target=self.read_output).start()
def test_failed_worker_is_replaced(popen: Popen, config: Dict[str, Any]): worker_config = config.get("worker") queue_name = worker_config.get("queue_name") worker_name = worker_config.get("worker_name") worker = initialize_worker(queue_name, worker_name, config) assert worker is not None assert worker.running is False assert worker.workers_count == 0 proc1 = MagicMock() proc2 = MagicMock() popen.side_effect = [proc1, proc2] proc1.is_running.return_value = True proc2.is_running.return_value = True try: worker.start() assert worker.running is True assert worker.workers_count == 1 popen.assert_called_with(ANY, stdout=None, stderr=None, shell=False, cwd=tempfile.tempdir) proc1.is_running.return_value = False time.sleep(0.2) assert worker.workers_count == 1 assert worker._processes[0] == proc2 finally: worker.stop() assert worker.running is False assert worker.workers_count == 0
def shell_exec(args, cwd=None, stdout=PIPE, stderr=PIPE, stdin=PIPE, shell=False): """ Wrapper for subprocess starting :param stderr: :param stdout: :param cwd: :param stdin: :type args: basestring or list :return: """ if stdout and not isinstance(stdout, int) and not isinstance(stdout, file_type): logging.warning("stdout is not IOBase: %s", stdout) stdout = None if stderr and not isinstance(stderr, int) and not isinstance(stderr, file_type): logging.warning("stderr is not IOBase: %s", stderr) stderr = None if isinstance(args, string_types) and not shell: args = shlex.split(args) logging.getLogger(__name__).debug("Executing shell: %s", args) if platform.system() == 'Windows': return Popen(args, stdout=stdout, stderr=stderr, stdin=stdin, bufsize=0, cwd=cwd, shell=shell) else: return Popen(args, stdout=stdout, stderr=stderr, stdin=stdin, bufsize=0, preexec_fn=os.setpgrp, close_fds=True, cwd=cwd, shell=shell)
def reset(self): self.gazebo.unpauseSim() self.check_all_sensors_ready() self.z_collision = 0 self.depth = 0 self.command.twist.linear.x = 0 self.pub.publish(self.command) self.pub2.publish(0) self.pub3.publish(0) self.node_process.terminate() self.set_init_pose() obs = self._get_obs() now = rospy.get_rostime() self._is_done(obs, now) self.gazebo.pauseSim() self.gazebo.resetSim() self.node_process = Popen( shlex.split('rosrun robil_lihi C_response_loader.py')) self.gazebo.unpauseSim() self.command.twist.linear.x = 0 self.pub.publish(self.command) self.pub2.publish(0) self.pub3.publish(0) self.set_init_pose() self.init_env_variables() self.check_all_sensors_ready() rospy.sleep(1) self.gazebo.pauseSim() self.init_env_variables() obs = self._get_obs() simplified_obs = self.convert_obs_to_state(obs) plt.clf() return simplified_obs
def create_new_process(self): ''' Creating a new process ''' if 'win' in PLATFORM: self._stdout = open(self._stdout_path, 'w+b') self._process = Popen(args=self._command, stdin=PIPE, stdout=self._stdout) self._pipe = self._process.stdin else: if os.path.exists(self._pipe_path): os.unlink(self._pipe_path) os.mkfifo(self._pipe_path) self._pipe = open(self._pipe_path, 'w+b') if os.path.exists(self._stdout_path): os.remove(self._stdout_path) self._stdout = open(self._stdout_path, 'w+b') self._process = Popen(args=self._command, stdin=self._pipe, stdout=self._stdout) self._player_answer = open(self._stdout_path, 'r') self._pid = self._process.pid # Writing pid to file pid_file = open(self._pid_path, 'w') pid_file.write(str(self._pid)) pid_file.close() # Passing pipe and stdout to properties class self.properties.__init__(self._pipe, self._player_answer, self._debug)
def start_exec(self, command, work_dir: str = None, shell: bool = False, errors=(), successes=()): self.clean() logger.info(f"Running command: {command}") Path(work_dir).mkdir(exist_ok=True, parents=True) self.output_file = Path( work_dir) / f"encoder_output_{secrets.token_hex(6)}.log" self.error_output_file = Path( work_dir) / f"encoder_error_output_{secrets.token_hex(6)}.log" self.output_file.touch(exist_ok=True) self.error_output_file.touch(exist_ok=True) self.error_message = errors self.success_message = successes self.process = Popen( shlex.split(command) if not shell and isinstance(command, str) else command, shell=shell, cwd=work_dir, stdout=open(self.output_file, "w"), stderr=open(self.error_output_file, "w"), stdin=PIPE, # FFmpeg can try to read stdin and wrecks havoc on linux encoding="utf-8", ) Thread(target=self.read_output).start()
def addFile(self, sourcefile): if self.type in ['RAR', 'RAR5']: raise NotImplementedError process = Popen('7z a -y "' + self.filepath + '" "' + sourcefile + '"', stdout=PIPE, stderr=STDOUT, stdin=PIPE, shell=True) process.communicate() if process.returncode != 0: raise OSError('Failed to add the file.')
def spawn(self): sockets_fds = self._get_sockets_fds() args = self.format_args(sockets_fds=sockets_fds) def preexec_fn(): streams = [sys.stdin] if self.close_child_stdout: streams.append(sys.stdout) if self.close_child_stderr: streams.append(sys.stderr) self._null_streams(streams) os.setsid() for limit, value in self.rlimits.items(): res = getattr(resource, 'RLIMIT_%s' % limit.upper(), None) if res is None: raise ValueError('unknown rlimit "%s"' % limit) # TODO(petef): support hard/soft limits resource.setrlimit(res, (value, value)) if self.gid: try: os.setgid(self.gid) except OverflowError: if not ctypes: raise # versions of python < 2.6.2 don't manage unsigned int for # groups like on osx or fedora os.setgid(-ctypes.c_int(-self.gid).value) os.initgroups(self.username, self.gid) if self.uid: os.setuid(self.uid) extra = {} if self.pipe_stdout: extra['stdout'] = PIPE if self.pipe_stderr: extra['stderr'] = PIPE self._worker = Popen(args, cwd=self.working_dir, shell=self.shell, preexec_fn=preexec_fn, env=self.env, close_fds=not self.use_fds, executable=self.executable, **extra) # let go of sockets created only for self._worker to inherit self._sockets = [] self.started = time.time()
def test_get_info(self): worker = Popen(["python -c 'import time;time.sleep(5)'"], shell=True) try: info = get_info(worker) finally: worker.terminate() self.assertTrue(isinstance(info["pid"], int)) self.assertEqual(info["nice"], 0)
def test_get_info(self): worker = Popen(["python -c 'import time;time.sleep(5)'"], shell=True) try: info = get_info(worker) finally: worker.terminate() self.assertTrue(isinstance(info['pid'], int)) self.assertEqual(info['nice'], 0)
def extractMetadata(self): process = Popen('7z x -y -so "' + self.filepath + '" ComicInfo.xml', stdout=PIPE, stderr=STDOUT, stdin=PIPE, shell=True) xml = process.communicate() if process.returncode != 0: raise OSError('Failed to extract archive.') try: return parseString(xml[0]) except ExpatError: return None
def test_get_info(self): worker = Popen(['top'], shell=True) try: info = get_info(worker) finally: worker.terminate() self.assertTrue(isinstance(info['pid'], int)) self.assertEqual(info['nice'], 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()
def popen_wrapper(args, universal_newlines=True): p = Popen(args, shell=False, stdout=PIPE, stderr=PIPE, close_fds=os.name != 'nt', universal_newlines=universal_newlines) output, errors = p.communicate() return ( output, errors, p.returncode )
def checkTools(source): source = source.upper() if source.endswith('.CBR') or source.endswith('.RAR'): rarExitCode = Popen('unrar', stdout=PIPE, stderr=STDOUT, stdin=PIPE, shell=True) rarExitCode = rarExitCode.wait() if rarExitCode != 0 and rarExitCode != 1 and rarExitCode != 7: print('ERROR: UnRAR is missing!') exit(1) elif source.endswith('.CB7') or source.endswith('.7Z'): sevenzaExitCode = Popen('7za', stdout=PIPE, stderr=STDOUT, stdin=PIPE, shell=True) sevenzaExitCode = sevenzaExitCode.wait() if sevenzaExitCode != 0 and sevenzaExitCode != 7: print('ERROR: 7za is missing!') exit(1) if options.format == 'MOBI': kindleGenExitCode = Popen('kindlegen -locale en', stdout=PIPE, stderr=STDOUT, stdin=PIPE, shell=True) if kindleGenExitCode.wait() != 0: print('ERROR: KindleGen is missing!') exit(1)
class ROSWebVis: def __init__(self, ros_port, ws_port, uid): self.ros_port = ros_port self.ws_port = ws_port self.uid = uid self.vis = Popen( shlex.split('python start_ros.py {} {}'.format(ros_port, ws_port))) def terminate(self): self.vis.terminate()
def run_command(cmd, data, location, chw): cwd = os.getcwd() if location is not None and chw is True: cwd = location elif location is not None and chw is False: cmd = '{0} {1}'.format(cmd, location) r = Popen(shlex.split(cmd), stdout=PIPE, stdin=PIPE, stderr=PIPE, cwd=cwd) if data is None: output = r.communicate()[0].decode('utf-8') else: output = r.communicate(input=data)[0] return output
def test_get_info(self): worker = Popen(["python", "-c", SLEEP % 5]) try: info = get_info(worker) finally: worker.terminate() self.assertTrue(isinstance(info['pid'], int)) if IS_WINDOWS: self.assertEqual(info['nice'], psutil.NORMAL_PRIORITY_CLASS) else: self.assertEqual(info['nice'], 0)
def system(cmd, timeout = 60): global proc logger().info(u"Executing command '{0}'".format(cmd)) proc = Popen(cmd, close_fds=True, shell=True, stdout=PIPE) logger().info(u"PID is {0} for command '{1}'".format(proc.pid, cmd)) for line in proc.stdout: logger().info(u"Process output: {0}".format(line.decode('latin1'))) ## Kill process after timeout seconds. _timer = Timer(timeout, terminate_process, [proc]) _timer.start() proc.wait(timeout=3) ## Wait for process to complete, increase timeout parameter if default 3 seconds is not enough _timer.cancel() return proc
def convert_to_mobi(assembled_ebooks): converted_ebooks = {} kindle_gen_exists = Popen('kindlegen', stdout=PIPE, stderr=STDOUT, stdin=PIPE, shell=True) kindle_gen_exists.communicate() if kindle_gen_exists.returncode == 0: for volume, ebook_file in assembled_ebooks.items(): info('Converting file "{}" to MOBI...'.format(ebook_file)) kindle_gen_convert = Popen('kindlegen "{}" -c2'.format(ebook_file), stdout=PIPE, stderr=STDOUT, stdin=PIPE, shell=True) kindle_gen_convert.communicate() if kindle_gen_convert.returncode not in [ 0, 1 ]: # acceptable exit codes error('Error to convert file "{}" to MOBI'.format(ebook_file)) continue os.remove(ebook_file) converted_ebooks[volume] = os.path.join( ebook_file, str(ebook_file).replace('.epub', '.mobi')) else: warning('KindleGen not found!') return converted_ebooks
def test_streams(self): self.sniff_log(logging.getLogger('')) print('test1') with log_std_streams(logger=self.captured_logger, stdout_level=logging.DEBUG): print('test2') with log_std_streams(stdout_level=logging.DEBUG): print('test3') with log_std_streams(stdout_level=logging.DEBUG): sys.stdout.write('test3') with log_std_streams(logger=self.captured_logger, stdout_level=logging.DEBUG): process = Popen(['echo', '"test5"']) process.wait() missed_file = get_uniq_name('.', 'test6', '') with log_std_streams(logger=self.captured_logger, stderr_level=logging.WARNING): process = Popen(['dir', missed_file]) process.wait() debug_buf = self.log_recorder.debug_buff.getvalue() warn_buf = self.log_recorder.warn_buff.getvalue() self.assertNotIn('test1', debug_buf) self.assertIn('test2', debug_buf) self.assertNotIn('test3', debug_buf) self.assertIn('test5', debug_buf) self.assertTrue(len(warn_buf) > 0)
def raw_cmd(arguments, shell=False, **kwargs): """ Launch a subprocess. This function ensure that: * subprocess arguments will be converted to a string if `shell` is True * subprocess.args is set to the arguments of the subprocess """ arguments_list = to_args_list(arguments) process = Popen(to_args_string(arguments_list) if shell else arguments_list, shell=shell, **kwargs) if not hasattr(process, "args"): process.args = arguments_list return process
def test_streams(self): self.log = logging.getLogger('') handler = RecordingHandler() self.log.addHandler(handler) print('test1') with log_std_streams(logger=self.log, stdout_level=logging.DEBUG): print('test2') with log_std_streams(stdout_level=logging.DEBUG): print('test3') with log_std_streams(stdout_level=logging.DEBUG): sys.stdout.write('test3') with log_std_streams(logger=self.log, stdout_level=logging.DEBUG): process = Popen(['echo', '"test5"']) process.wait() missed_file = get_uniq_name('.', 'test6', '') with log_std_streams(logger=self.log, stderr_level=logging.WARNING): process = Popen(['dir', missed_file]) process.wait() self.log.removeHandler(handler) debug_buf = handler.debug_buff.getvalue() warn_buf = handler.warn_buff.getvalue() self.assertNotIn('test1', debug_buf) self.assertIn('test2', debug_buf) self.assertNotIn('test3', debug_buf) self.assertIn('test5', debug_buf) self.assertTrue(len(warn_buf) > 0)
def __init__(self): # Need to find GNU time. If /usr/bin/time is not GNU time # then PUQ expects it to be in the path and called 'gtime' tstr = 'gtime' try: ver = Popen("/usr/bin/time --version", shell=True, stderr=PIPE).stderr.read() if ver.startswith(b"GNU"): tstr = '/usr/bin/time' except: pass self.timestr = tstr + " -f \"HDF5:{'name':'time','value':%e,'desc':''}:5FDH\"" self.run_num = 0
def close_spider(self, spider): logger = logging.getLogger() logger.info('Starting MOBI generation of scrapped images') storage = IMAGES_STORE folder_name = spider.folder_name results_path = path.abspath(path.join(storage, folder_name)) chapter_directories = listdir(results_path) for i in range(len(chapter_directories)): chapter_directory = chapter_directories[i] logger.info('Generating MOBI file for %s (%d/%d)' % (chapter_directory, i + 1, len(chapter_directories))) chapter_number = "" if '.' in chapter_directory: chapter_number = "##%05.1f" % float(chapter_directory) else: chapter_number = "#%03d" % int(chapter_directory) chapter_title = folder_name + " " + chapter_number pipe = Popen( 'kcc-c2e -m -p KPW --whiteborders -f MOBI -u -r 2 -t "%s" "%s"' % (chapter_title, path.join(results_path, chapter_directory)), stdout=PIPE, stderr=STDOUT, stdin=PIPE, shell=True) try: pipe.wait(60) generated_file_name = path.join(results_path, chapter_directory) + ".mobi" rename(generated_file_name, path.join(results_path, chapter_title) + ".mobi") logger.info('MOBI file generated successfully') except TimeoutExpired: logger.error('Unable to generate MOBI file for %s' % (chapter_directory)) logger.info('Finalized MOBI generation of scrapped images')
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)
def raise_process(self): venv = self.ensure_environment() args = [ os.path.join(venv.path, "bin", "python"), "-m", self.package_name, ] process = Popen(args, env=self.env, stdout=subprocess.PIPE) process.wait() retcode = process.returncode output = process.stdout.read().decode("utf-8") self._process_return_value = retcode, output
def make(base_dir, timeout=5): """compile source code. return (ok?, msg)""" cmd = ['clang++', '-std=c++11', 'main.cpp'] p = Popen(cmd, stderr=PIPE, cwd=base_dir) try: p.wait(timeout) except TimeoutExpired: return False, 'compilation take too much time.' else: if p.returncode == 0: return True, '' else: return False, p.communicate()[1]
def __init__(self, filepath): self.filepath = filepath self.type = None if not os.path.isfile(self.filepath): raise OSError('File not found.') process = Popen('7z l -y -p1 "' + self.filepath + '"', stderr=STDOUT, stdout=PIPE, stdin=PIPE, shell=True) for line in process.stdout: if b'Type =' in line: self.type = line.rstrip().decode().split(' = ')[1].upper() break process.communicate() if process.returncode != 0: raise OSError('Archive is corrupted or encrypted.') elif self.type not in ['7Z', 'RAR', 'RAR5', 'ZIP']: raise OSError('Unsupported archive format.')
def spawn(self): sockets_fds = self._get_sockets_fds() args = self.format_args(sockets_fds=sockets_fds) def preexec_fn(): streams = [sys.stdin] if self.close_child_stdout: streams.append(sys.stdout) if self.close_child_stderr: streams.append(sys.stderr) self._null_streams(streams) os.setsid() for limit, value in self.rlimits.items(): res = getattr(resource, 'RLIMIT_%s' % limit.upper(), None) if res is None: raise ValueError('unknown rlimit "%s"' % limit) # TODO(petef): support hard/soft limits resource.setrlimit(res, (value, value)) if self.gid: try: os.setgid(self.gid) except OverflowError: if not ctypes: raise # versions of python < 2.6.2 don't manage unsigned int for # groups like on osx or fedora os.setgid(-ctypes.c_int(-self.gid).value) if self.username is not None: try: os.initgroups(self.username, self.gid) except (OSError, AttributeError): # not support on Mac or 2.6 pass if self.uid: os.setuid(self.uid) extra = {} if self.pipe_stdout: extra['stdout'] = PIPE if self.pipe_stderr: extra['stderr'] = PIPE self._worker = Popen(args, cwd=self.working_dir, shell=self.shell, preexec_fn=preexec_fn, env=self.env, close_fds=not self.use_fds, executable=self.executable, **extra) # let go of sockets created only for self._worker to inherit self._sockets = [] self.started = time.time()
def extract(self, targetdir): if not os.path.isdir(targetdir): raise OSError('Target directory don\'t exist.') process = Popen('7z x -y -xr!__MACOSX -xr!.DS_Store -xr!thumbs.db -xr!Thumbs.db -o"' + targetdir + '" "' + self.filepath + '"', stdout=PIPE, stderr=STDOUT, stdin=PIPE, shell=True) process.communicate() if process.returncode != 0: raise OSError('Failed to extract archive.') tdir = os.listdir(targetdir) if 'ComicInfo.xml' in tdir: tdir.remove('ComicInfo.xml') if len(tdir) == 1 and os.path.isdir(os.path.join(targetdir, tdir[0])): for f in os.listdir(os.path.join(targetdir, tdir[0])): move(os.path.join(targetdir, tdir[0], f), targetdir) os.rmdir(os.path.join(targetdir, tdir[0])) return targetdir
def __init__(self, wid, cmd, working_dir, shell, uid=None, gid=None, env=None): self.wid = wid self.working_dir = working_dir self.shell = shell self.env = env self.cmd = cmd.replace("$WID", str(self.wid)) self.uid = to_uid(uid) self.gid = to_gid(gid) def preexec_fn(): os.setsid() if self.gid: try: os.setgid(self.gid) except OverflowError: if not ctypes: raise # versions of python < 2.6.2 don't manage unsigned int for # groups like on osx or fedora os.setgid(-ctypes.c_int(-self.gid).value) if self.uid: os.setuid(self.uid) self._worker = Popen( self.cmd.split(), cwd=self.working_dir, shell=self.shell, preexec_fn=preexec_fn, env=self.env, close_fds=True, ) self.started = time.time()
def extractCB7(self, targetdir): # Workaround for some wide UTF-8 + Popen abnormalities if sys.platform.startswith('darwin'): copy( self.origFileName, os.path.join(os.path.dirname(self.origFileName), 'TMP_KCC_TMP')) self.origFileName = os.path.join( os.path.dirname(self.origFileName), 'TMP_KCC_TMP') output = Popen( '7za x "' + self.origFileName + '" -xr!__MACOSX -xr!.DS_Store -xr!thumbs.db -xr!Thumbs.db -o"' + targetdir + '"', stdout=PIPE, stderr=STDOUT, stdin=PIPE, shell=True) extracted = False for line in output.stdout: if b"Everything is Ok" in line: extracted = True if sys.platform.startswith('darwin'): os.remove(self.origFileName) if not extracted: raise OSError
def spawn(self): args = self.format_args() def preexec_fn(): os.setsid() for limit, value in self.rlimits.items(): res = getattr(resource, 'RLIMIT_%s' % limit.upper(), None) if res is None: raise ValueError('unknown rlimit "%s"' % limit) # TODO(petef): support hard/soft limits resource.setrlimit(res, (value, value)) if self.gid: try: os.setgid(self.gid) except OverflowError: if not ctypes: raise # versions of python < 2.6.2 don't manage unsigned int for # groups like on osx or fedora os.setgid(-ctypes.c_int(-self.gid).value) if self.uid: os.setuid(self.uid) self._worker = Popen(args, cwd=self.working_dir, shell=self.shell, preexec_fn=preexec_fn, env=self.env, close_fds=not self.use_fds, stdout=PIPE, stderr=PIPE, executable=self.executable) self.started = time.time()
def find_device(self): for drive in disk_partitions(False): if 'removable' in drive[3]: if os.path.isdir(os.path.join(drive[1], 'system')) and \ os.path.isdir(os.path.join(drive[1], 'documents')): return drive[1] # print(self.config['GENERAL']['SSHEnabled']) if self.config['GENERAL']['SSHEnabled'] == "True": ssh = Popen('"' + self.config['SSH']['PLinkPath'] + '" root@' + self.config['SSH']['KindleIP'] + ' whoami', stdout=PIPE, stderr=STDOUT, shell=True) ssh_check = ssh.wait() if ssh_check == 0: self.ssh = True return self.config['SSH']['KindleIP'] else: raise OSError('Can\'t connect to Kindle!') else: raise OSError('Not found any connected Kindle!')
def __init__(self, wid, cmd, working_dir=None, shell=False, uid=None, gid=None, env=None, rlimits=None): self.wid = wid if working_dir is None: self.working_dir = get_working_dir() else: self.working_dir = working_dir self.shell = shell self.env = env if rlimits is not None: self.rlimits = rlimits else: self.rlimits = {} self.cmd = cmd.replace('$WID', str(self.wid)) if uid is None: self.uid = None else: self.uid = to_uid(uid) if gid is None: self.gid = None else: self.gid = to_gid(gid) def preexec_fn(): os.setsid() for limit, value in self.rlimits.items(): res = getattr(resource, 'RLIMIT_%s' % limit.upper(), None) if res is None: raise ValueError('unknown rlimit "%s"' % limit) # TODO(petef): support hard/soft limits resource.setrlimit(res, (value, value)) if self.gid: try: os.setgid(self.gid) except OverflowError: if not ctypes: raise # versions of python < 2.6.2 don't manage unsigned int for # groups like on osx or fedora os.setgid(-ctypes.c_int(-self.gid).value) if self.uid: os.setuid(self.uid) self._worker = Popen(self.cmd.split(), cwd=self.working_dir, shell=self.shell, preexec_fn=preexec_fn, env=self.env, close_fds=True, stdout=PIPE, stderr=PIPE) self.started = time.time()
def _start(self, ini, xml): """start the process""" if self.isRunning: return # write the Halcyon.ini config file f = open(os.path.join(self.startDir, 'Halcyon.ini'), 'w') f.write(ini) f.close() # write the Regions.cfg file if not os.path.exists(os.path.join(self.startDir, 'Regions')): os.mkdir(os.path.join(self.startDir, 'Regions')) f = open(os.path.join(self.startDir, 'Regions', 'default.xml'), 'w') f.write(xml) f.close() self.proc = Popen(self.startString.split(" "), cwd=self.startDir, stdout=DEVNULL, stderr=DEVNULL) #write a pidfile f = open(self.pidFile, 'w') f.write(str(self.proc.pid)) f.close()
def checkTools(source): source = source.upper() if source.endswith('.CBR') or source.endswith('.RAR'): rarExitCode = Popen('unrar', stdout=PIPE, stderr=STDOUT, stdin=PIPE, shell=True) rarExitCode = rarExitCode.wait() if rarExitCode != 0 and rarExitCode != 7: print('ERROR: UnRAR is missing!') exit(1) elif source.endswith('.CB7') or source.endswith('.7Z'): sevenzaExitCode = Popen('7za', stdout=PIPE, stderr=STDOUT, stdin=PIPE, shell=True) sevenzaExitCode = sevenzaExitCode.wait() if sevenzaExitCode != 0 and sevenzaExitCode != 7: print('ERROR: 7za is missing!') exit(1) if options.format == 'MOBI': kindleGenExitCode = Popen('kindlegen -locale en', stdout=PIPE, stderr=STDOUT, stdin=PIPE, shell=True) if kindleGenExitCode.wait() != 0: print('ERROR: KindleGen is missing!') exit(1)
def test_streams(self): self.sniff_log() print('test1') with log_std_streams(logger=self.captured_logger, stdout_level=logging.DEBUG): print('test2') with log_std_streams(stdout_level=logging.DEBUG): print('test3') with log_std_streams(stdout_level=logging.DEBUG): sys.stdout.write('test3') with log_std_streams(logger=self.captured_logger, stdout_level=logging.DEBUG): cmd = ['echo', '"test5"'] if is_windows(): cmd = ['cmd', '/c'] + cmd process = Popen(cmd) process.wait() missed_file = get_uniq_name('.', 'test6', '') with log_std_streams(logger=self.captured_logger, stderr_level=logging.WARNING): if is_windows(): cmd = ['cmd', '/c', 'dir'] else: cmd = ['ls'] process = Popen(cmd + [missed_file]) process.wait() debug_buf = self.log_recorder.debug_buff.getvalue() warn_buf = self.log_recorder.warn_buff.getvalue() self.assertNotIn('test1', debug_buf) self.assertIn('test2', debug_buf) self.assertNotIn('test3', debug_buf) self.assertIn('test5', debug_buf) self.assertTrue(len(warn_buf) > 0)
class Process(object): """Wraps a process. Options: - **wid**: the process unique identifier. This value will be used to replace the *$WID* string in the command line if present. - **cmd**: the command to run. May contain any of the variables available that are being passed to this class. They will be replaced using the python format syntax. - **args**: the arguments for the command to run. Can be a list or a string. If **args** is a string, it's splitted using :func:`shlex.split`. Defaults to None. - **executable**: When executable is given, the first item in the args sequence obtained from **cmd** is still treated by most programs as the command name, which can then be different from the actual executable name. It becomes the display name for the executing program in utilities such as **ps**. - **working_dir**: the working directory to run the command in. If not provided, will default to the current working directory. - **shell**: if *True*, will run the command in the shell environment. *False* by default. **warning: this is a security hazard**. - **uid**: if given, is the user id or name the command should run with. The current uid is the default. - **gid**: if given, is the group id or name the command should run with. The current gid is the default. - **env**: a mapping containing the environment variables the command will run with. Optional. - **rlimits**: a mapping containing rlimit names and values that will be set before the command runs. - **use_fds**: if True, will not close the fds in the subprocess. default: False. - **pipe_stdout**: if True, will open a PIPE on stdout. default: True. - **pipe_stderr**: if True, will open a PIPE on stderr. default: True. - **close_child_stdout**: If True, redirects the child process' stdout to /dev/null after the fork. default: False. - **close_child_stderr**: If True, redirects the child process' stdout to /dev/null after the fork. default: False. """ def __init__(self, wid, cmd, args=None, working_dir=None, shell=False, uid=None, gid=None, env=None, rlimits=None, executable=None, use_fds=False, watcher=None, spawn=True, pipe_stdout=True, pipe_stderr=True, close_child_stdout=False, close_child_stderr=False): self.wid = wid self.cmd = cmd self.args = args self.working_dir = working_dir or get_working_dir() self.shell = shell self.uid = to_uid(uid) if uid else None self.gid = to_gid(gid) if gid else None self.env = env or {} self.rlimits = rlimits or {} self.executable = executable self.use_fds = use_fds self.watcher = watcher self.pipe_stdout = pipe_stdout self.pipe_stderr = pipe_stderr self.close_child_stdout = close_child_stdout self.close_child_stderr = close_child_stderr self.stopping = False if spawn: self.spawn() def _null_streams(self, streams): devnull = os.open(os.devnull, os.O_RDWR) try: for stream in streams: if not hasattr(stream, 'fileno'): # we're probably dealing with a file-like continue try: stream.flush() os.dup2(devnull, stream.fileno()) except IOError: # some streams, like stdin - might be already closed. pass finally: os.close(devnull) def spawn(self): args = self.format_args() def preexec_fn(): streams = [sys.stdin] if self.close_child_stdout: streams.append(sys.stdout) if self.close_child_stderr: streams.append(sys.stderr) self._null_streams(streams) os.setsid() for limit, value in self.rlimits.items(): res = getattr(resource, 'RLIMIT_%s' % limit.upper(), None) if res is None: raise ValueError('unknown rlimit "%s"' % limit) # TODO(petef): support hard/soft limits resource.setrlimit(res, (value, value)) if self.gid: try: os.setgid(self.gid) except OverflowError: if not ctypes: raise # versions of python < 2.6.2 don't manage unsigned int for # groups like on osx or fedora os.setgid(-ctypes.c_int(-self.gid).value) if self.uid: os.setuid(self.uid) extra = {} if self.pipe_stdout: extra['stdout'] = PIPE if self.pipe_stderr: extra['stderr'] = PIPE self._worker = Popen(args, cwd=self.working_dir, shell=self.shell, preexec_fn=preexec_fn, env=self.env, close_fds=not self.use_fds, executable=self.executable, **extra) self.started = time.time() def format_args(self): """ It's possible to use environment variables and some other variables that are available in this context, when spawning the processes. """ logger.debug('cmd: ' + bytestring(self.cmd)) logger.debug('args: ' + str(self.args)) current_env = ObjectDict(self.env.copy()) format_kwargs = { 'wid': self.wid, 'shell': self.shell, 'args': self.args, 'env': current_env, 'working_dir': self.working_dir, 'uid': self.uid, 'gid': self.gid, 'rlimits': self.rlimits, 'executable': self.executable, 'use_fds': self.use_fds} if self.watcher is not None: format_kwargs['sockets'] = self.watcher._get_sockets_fds() for option in self.watcher.optnames: if option not in format_kwargs\ and hasattr(self.watcher, option): format_kwargs[option] = getattr(self.watcher, option) cmd = replace_gnu_args(self.cmd, **format_kwargs) if '$WID' in cmd or (self.args and '$WID' in self.args): msg = "Using $WID in the command is deprecated. You should use "\ "the python string format instead. In you case, this means "\ "replacing the $WID in your command by $(WID)." warnings.warn(msg, DeprecationWarning) self.cmd = cmd.replace('$WID', str(self.wid)) if self.args is not None: if isinstance(self.args, string_types): args = shlex.split(bytestring(replace_gnu_args( self.args, **format_kwargs))) else: args = [bytestring(replace_gnu_args(arg, **format_kwargs)) for arg in self.args] args = shlex.split(bytestring(cmd)) + args else: args = shlex.split(bytestring(cmd)) logger.debug("process args: %s", args) return args @debuglog def poll(self): return self._worker.poll() @debuglog def is_alive(self): return self.poll() is None @debuglog def send_signal(self, sig): """Sends a signal **sig** to the process.""" logger.debug("sending signal %s to %s" % (sig, self.pid)) return self._worker.send_signal(sig) @debuglog def stop(self): """Stop the process and close stdout/stderr If the corresponding process is still here (normally it's already killed by the watcher), a SIGTERM is sent, then a SIGKILL after 1 second. The shutdown process (SIGTERM then SIGKILL) is normally taken by the watcher. So if the process is still there here, it's a kind of bad behavior because the graceful timeout won't be respected here. """ try: try: if self._worker.poll() is None: return self._worker.terminate() finally: if self._worker.stderr is not None: self._worker.stderr.close() if self._worker.stdout is not None: self._worker.stdout.close() except NoSuchProcess: pass def age(self): """Return the age of the process in seconds.""" return time.time() - self.started def info(self): """Return process info. The info returned is a mapping with these keys: - **mem_info1**: Resident Set Size Memory in bytes (RSS) - **mem_info2**: Virtual Memory Size in bytes (VMS). - **cpu**: % of cpu usage. - **mem**: % of memory usage. - **ctime**: process CPU (user + system) time in seconds. - **pid**: process id. - **username**: user name that owns the process. - **nice**: process niceness (between -20 and 20) - **cmdline**: the command line the process was run with. """ try: info = get_info(self._worker) except NoSuchProcess: return "No such process (stopped?)" info["age"] = self.age() info["started"] = self.started info["children"] = [] for child in self._worker.get_children(): info["children"].append(get_info(child)) return info def children(self): """Return a list of children pids.""" return [child.pid for child in self._worker.get_children()] def is_child(self, pid): """Return True is the given *pid* is a child of that process.""" pids = [child.pid for child in self._worker.get_children()] if pid in pids: return True return False @debuglog def send_signal_child(self, pid, signum): """Send signal *signum* to child *pid*.""" children = dict([(child.pid, child) for child in self._worker.get_children()]) children[pid].send_signal(signum) @debuglog def send_signal_children(self, signum): """Send signal *signum* to all children.""" for child in self._worker.get_children(): try: child.send_signal(signum) except OSError as e: if e.errno != errno.ESRCH: raise @property def status(self): """Return the process status as a constant - RUNNING - DEAD_OR_ZOMBIE - UNEXISTING - OTHER """ try: if self._worker.status in (STATUS_ZOMBIE, STATUS_DEAD): return DEAD_OR_ZOMBIE except NoSuchProcess: return UNEXISTING if self._worker.is_running(): return RUNNING return OTHER @property def pid(self): """Return the *pid*""" return self._worker.pid @property def stdout(self): """Return the *stdout* stream""" return self._worker.stdout @property def stderr(self): """Return the *stdout* stream""" return self._worker.stderr def __eq__(self, other): return self is other def __lt__(self, other): return self.started < other.started def __gt__(self, other): return self.started > other.started
class Process(object): """Wraps a process. Options: - **wid**: the process unique identifier. This value will be used to replace the *$WID* string in the command line if present. - **cmd**: the command to run. May contain *$WID*, which will be replaced by **wid**. - **args**: the arguments for the command to run. Can be a list or a string. If **args** is a string, it's splitted using :func:`shlex.split`. Defaults to None. - **executable**: When executable is given, the first item in the args sequence obtained from **cmd** is still treated by most programs as the command name, which can then be different from the actual executable name. It becomes the display name for the executing program in utilities such as **ps**. - **working_dir**: the working directory to run the command in. If not provided, will default to the current working directory. - **shell**: if *True*, will run the command in the shell environment. *False* by default. **warning: this is a security hazard**. - **uid**: if given, is the user id or name the command should run with. The current uid is the default. - **gid**: if given, is the group id or name the command should run with. The current gid is the default. - **env**: a mapping containing the environment variables the command will run with. Optional. - **rlimits**: a mapping containing rlimit names and values that will be set before the command runs. """ def __init__(self, wid, cmd, args=None, working_dir=None, shell=False, uid=None, gid=None, env=None, rlimits=None, executable=None): self.wid = wid if working_dir is None: self.working_dir = get_working_dir() else: self.working_dir = working_dir self.shell = shell self.env = env if rlimits is not None: self.rlimits = rlimits else: self.rlimits = {} self.cmd = cmd.replace('$WID', str(self.wid)) if uid is None: self.uid = None else: self.uid = to_uid(uid) if gid is None: self.gid = None else: self.gid = to_gid(gid) def preexec_fn(): os.setsid() for limit, value in self.rlimits.items(): res = getattr(resource, 'RLIMIT_%s' % limit.upper(), None) if res is None: raise ValueError('unknown rlimit "%s"' % limit) # TODO(petef): support hard/soft limits resource.setrlimit(res, (value, value)) if self.gid: try: os.setgid(self.gid) except OverflowError: if not ctypes: raise # versions of python < 2.6.2 don't manage unsigned int for # groups like on osx or fedora os.setgid(-ctypes.c_int(-self.gid).value) if self.uid: os.setuid(self.uid) logger.debug('cmd: ' + cmd) logger.debug('args: ' + str(args)) if args is not None: if isinstance(args, str): args_ = shlex.split(bytestring(args)) else: args_ = args[:] args_ = shlex.split(bytestring(cmd)) + args_ else: args_ = shlex.split(bytestring(cmd)) logger.debug('Running %r' % ' '.join(args_)) self._worker = Popen(args_, cwd=self.working_dir, shell=self.shell, preexec_fn=preexec_fn, env=self.env, close_fds=True, stdout=PIPE, stderr=PIPE, executable=executable) self.started = time.time() @debuglog def poll(self): return self._worker.poll() @debuglog def send_signal(self, sig): """Sends a signal **sig** to the process.""" return self._worker.send_signal(sig) @debuglog def stop(self): """Terminate the process.""" try: if self._worker.poll() is None: return self._worker.terminate() finally: self._worker.stderr.close() self._worker.stdout.close() def age(self): """Return the age of the process in seconds.""" return time.time() - self.started def info(self): """Return process info. The info returned is a mapping with these keys: - **mem_info1**: Resident Set Size Memory in bytes (RSS) - **mem_info2**: Virtual Memory Size in bytes (VMS). - **cpu**: % of cpu usage. - **mem**: % of memory usage. - **ctime**: process CPU (user + system) time in seconds. - **pid**: process id. - **username**: user name that owns the process. - **nice**: process niceness (between -20 and 20) - **cmdline**: the command line the process was run with. """ try: info = get_info(self._worker) except NoSuchProcess: return "No such process (stopped?)" info["children"] = [] for child in self._worker.get_children(): info["children"].append(get_info(child)) return info def children(self): """Return a list of children pids.""" return [child.pid for child in self._worker.get_children()] def is_child(self, pid): """Return True is the given *pid* is a child of that process.""" pids = [child.pid for child in self._worker.get_children()] if pid in pids: return True return False @debuglog def send_signal_child(self, pid, signum): """Send signal *signum* to child *pid*.""" children = dict([(child.pid, child) \ for child in self._worker.get_children()]) children[pid].send_signal(signum) @debuglog def send_signal_children(self, signum): """Send signal *signum* to all children.""" for child in self._worker.get_children(): try: child.send_signal(signum) except OSError as e: if e.errno != errno.ESRCH: raise @property def status(self): """Return the process status as a constant - RUNNING - DEAD_OR_ZOMBIE - OTHER """ try: if self._worker.status in (STATUS_ZOMBIE, STATUS_DEAD): return DEAD_OR_ZOMBIE except NoSuchProcess: return OTHER if self._worker.is_running(): return RUNNING return OTHER @property def pid(self): """Return the *pid*""" return self._worker.pid @property def stdout(self): """Return the *stdout* stream""" return self._worker.stdout @property def stderr(self): """Return the *stdout* stream""" return self._worker.stderr
class Process(object): """Wraps a process. Options: - **wid**: the process unique identifier. This value will be used to replace the *$WID* string in the command line if present. - **cmd**: the command to run. May contain any of the variables available that are being passed to this class. They will be replaced using the python format syntax. - **args**: the arguments for the command to run. Can be a list or a string. If **args** is a string, it's splitted using :func:`shlex.split`. Defaults to None. - **executable**: When executable is given, the first item in the args sequence obtained from **cmd** is still treated by most programs as the command name, which can then be different from the actual executable name. It becomes the display name for the executing program in utilities such as **ps**. - **working_dir**: the working directory to run the command in. If not provided, will default to the current working directory. - **shell**: if *True*, will run the command in the shell environment. *False* by default. **warning: this is a security hazard**. - **uid**: if given, is the user id or name the command should run with. The current uid is the default. - **gid**: if given, is the group id or name the command should run with. The current gid is the default. - **env**: a mapping containing the environment variables the command will run with. Optional. - **rlimits**: a mapping containing rlimit names and values that will be set before the command runs. - **use_fds**: if True, will not close the fds in the subprocess. Must be be set to True on Windows if stdout or stderr are redirected. default: False. - **pipe_stdout**: if True, will open a PIPE on stdout. default: True. - **pipe_stderr**: if True, will open a PIPE on stderr. default: True. - **close_child_stdin**: If True, redirects the child process' stdin to /dev/null after the fork. default: True. - **close_child_stdout**: If True, redirects the child process' stdout to /dev/null after the fork. default: False. - **close_child_stderr**: If True, redirects the child process' stdout to /dev/null after the fork. default: False. """ def __init__(self, name, wid, cmd, args=None, working_dir=None, shell=False, uid=None, gid=None, env=None, rlimits=None, executable=None, use_fds=False, watcher=None, spawn=True, pipe_stdout=True, pipe_stderr=True, close_child_stdin=True, close_child_stdout=False, close_child_stderr=False): self.name = name self.wid = wid self.cmd = cmd self.args = args self.working_dir = working_dir or get_working_dir() self.shell = shell if uid: self.uid = to_uid(uid) self.username = get_username_from_uid(self.uid) else: self.username = None self.uid = None self.gid = to_gid(gid) if gid else None self.env = env or {} self.rlimits = rlimits or {} self.executable = executable self.use_fds = use_fds self.watcher = watcher self.pipe_stdout = pipe_stdout self.pipe_stderr = pipe_stderr self.close_child_stdin = close_child_stdin self.close_child_stdout = close_child_stdout self.close_child_stderr = close_child_stderr self.stopping = False # sockets created before fork, should be let go after. self._sockets = [] self._worker = None self.redirected = False self.started = 0 if self.uid is not None and self.gid is None: self.gid = get_default_gid(self.uid) if IS_WINDOWS: if not self.use_fds and (self.pipe_stderr or self.pipe_stdout): raise ValueError("On Windows, you can't close the fds if " "you are redirecting stdout or stderr") if spawn: self.spawn() def _null_streams(self, streams): devnull = os.open(os.devnull, os.O_RDWR) try: for stream in streams: if not hasattr(stream, 'fileno'): # we're probably dealing with a file-like continue try: stream.flush() os.dup2(devnull, stream.fileno()) except IOError: # some streams, like stdin - might be already closed. pass finally: os.close(devnull) def _get_sockets_fds(self): """Returns sockets dict. If this worker's cmd indicates use of a SO_REUSEPORT socket, a new socket is created and bound. This new socket's FD replaces original socket's FD in returned dict. This method populates `self._sockets` list. This list should be let go after `fork()`. """ sockets_fds = None if self.watcher is not None and self.watcher.sockets is not None: sockets_fds = self.watcher._get_sockets_fds() reuseport_sockets = tuple((sn, s) for (sn, s) in self.watcher.sockets.items() if s.so_reuseport) for sn, s in reuseport_sockets: # watcher.cmd uses this reuseport socket if 'circus.sockets.%s' % sn in self.watcher.cmd: sock = CircusSocket.load_from_config(s._cfg) sock.bind_and_listen() # replace original socket's fd sockets_fds[sn] = sock.fileno() # keep new socket until fork returns self._sockets.append(sock) return sockets_fds def spawn(self): self.started = time.time() sockets_fds = self._get_sockets_fds() args = self.format_args(sockets_fds=sockets_fds) def preexec(): streams = [] if self.close_child_stdin: streams.append(sys.stdin) if self.close_child_stdout: streams.append(sys.stdout) if self.close_child_stderr: streams.append(sys.stderr) self._null_streams(streams) os.setsid() if resource: for limit, value in self.rlimits.items(): res = getattr( resource, 'RLIMIT_%s' % limit.upper(), None ) if res is None: raise ValueError('unknown rlimit "%s"' % limit) # TODO(petef): support hard/soft limits # for the NOFILE limit, if we fail to set an unlimited # value then check the existing hard limit because we # probably can't bypass it due to a kernel limit - so just # assume that the caller means they want to use the kernel # limit when they pass the unlimited value. This is better # than failing to start the process and forcing the caller # to always be aware of what the kernel configuration is. # If they do pass in a real limit value, then we'll just # raise the failure as they should know that their # expectations couldn't be met. # TODO - we can't log here as this occurs in the child # process after the fork but it would be very good to # notify the admin of the situation somehow. retry = False try: resource.setrlimit(res, (value, value)) except ValueError: if res == resource.RLIMIT_NOFILE and \ value == resource.RLIM_INFINITY: _soft, value = resource.getrlimit(res) retry = True else: raise if retry: resource.setrlimit(res, (value, value)) if self.gid: try: os.setgid(self.gid) except OverflowError: if not ctypes: raise # versions of python < 2.6.2 don't manage unsigned int for # groups like on osx or fedora os.setgid(-ctypes.c_int(-self.gid).value) if self.username is not None: try: os.initgroups(self.username, self.gid) except (OSError, AttributeError): # not support on Mac or 2.6 pass if self.uid: os.setuid(self.uid) if IS_WINDOWS: # On Windows we can't use a pre-exec function preexec_fn = None else: preexec_fn = preexec extra = {} if self.pipe_stdout: extra['stdout'] = PIPE if self.pipe_stderr: extra['stderr'] = PIPE self._worker = Popen(args, cwd=self.working_dir, shell=self.shell, preexec_fn=preexec_fn, env=self.env, close_fds=not self.use_fds, executable=self.executable, **extra) # let go of sockets created only for self._worker to inherit self._sockets = [] def format_args(self, sockets_fds=None): """ It's possible to use environment variables and some other variables that are available in this context, when spawning the processes. """ logger.debug('cmd: ' + bytestring(self.cmd)) logger.debug('args: ' + str(self.args)) current_env = ObjectDict(self.env.copy()) format_kwargs = { 'wid': self.wid, 'shell': self.shell, 'args': self.args, 'env': current_env, 'working_dir': self.working_dir, 'uid': self.uid, 'gid': self.gid, 'rlimits': self.rlimits, 'executable': self.executable, 'use_fds': self.use_fds} if sockets_fds is not None: format_kwargs['sockets'] = sockets_fds if self.watcher is not None: for option in self.watcher.optnames: if option not in format_kwargs\ and hasattr(self.watcher, option): format_kwargs[option] = getattr(self.watcher, option) cmd = replace_gnu_args(self.cmd, **format_kwargs) if '$WID' in cmd or (self.args and '$WID' in self.args): msg = "Using $WID in the command is deprecated. You should use "\ "the python string format instead. In your case, this "\ "means replacing the $WID in your command by $(WID)." warnings.warn(msg, DeprecationWarning) self.cmd = cmd.replace('$WID', str(self.wid)) if self.args is not None: if isinstance(self.args, string_types): args = shlex.split(bytestring(replace_gnu_args( self.args, **format_kwargs))) else: args = [bytestring(replace_gnu_args(arg, **format_kwargs)) for arg in self.args] args = shlex.split(bytestring(cmd), posix=not IS_WINDOWS) + args else: args = shlex.split(bytestring(cmd), posix=not IS_WINDOWS) if self.shell: # subprocess.Popen(shell=True) implies that 1st arg is the # requested command, remaining args are applied to sh. args = [' '.join(quote(arg) for arg in args)] shell_args = format_kwargs.get('shell_args', None) if shell_args and IS_WINDOWS: logger.warn("shell_args won't apply for " "windows platforms: %s", shell_args) elif isinstance(shell_args, string_types): args += shlex.split(bytestring(replace_gnu_args( shell_args, **format_kwargs))) elif shell_args: args += [bytestring(replace_gnu_args(arg, **format_kwargs)) for arg in shell_args] elif format_kwargs.get('shell_args', False): logger.warn("shell_args is defined but won't be used " "in this context: %s", format_kwargs['shell_args']) logger.debug("process args: %s", args) return args def returncode(self): return self._worker.returncode @debuglog def poll(self): return self._worker.poll() @debuglog def is_alive(self): return self.poll() is None @debuglog def send_signal(self, sig): """Sends a signal **sig** to the process.""" logger.debug("sending signal %s to %s" % (sig, self.pid)) return self._worker.send_signal(sig) @debuglog def stop(self): """Stop the process and close stdout/stderr If the corresponding process is still here (normally it's already killed by the watcher), a SIGTERM is sent, then a SIGKILL after 1 second. The shutdown process (SIGTERM then SIGKILL) is normally taken by the watcher. So if the process is still there here, it's a kind of bad behavior because the graceful timeout won't be respected here. """ try: try: if self.is_alive(): try: return self._worker.terminate() except AccessDenied: # It can happen on Windows if the process # dies after poll returns (unlikely) pass finally: self.close_output_channels() except NoSuchProcess: pass def close_output_channels(self): if self._worker.stderr is not None: self._worker.stderr.close() if self._worker.stdout is not None: self._worker.stdout.close() def wait(self, timeout=None): """ Wait for the process to terminate, in the fashion of waitpid. Accepts a timeout in seconds. """ self._worker.wait(timeout) def age(self): """Return the age of the process in seconds.""" return time.time() - self.started def info(self): """Return process info. The info returned is a mapping with these keys: - **mem_info1**: Resident Set Size Memory in bytes (RSS) - **mem_info2**: Virtual Memory Size in bytes (VMS). - **cpu**: % of cpu usage. - **mem**: % of memory usage. - **ctime**: process CPU (user + system) time in seconds. - **pid**: process id. - **username**: user name that owns the process. - **nice**: process niceness (between -20 and 20) - **cmdline**: the command line the process was run with. """ try: info = get_info(self._worker) except NoSuchProcess: return "No such process (stopped?)" info["age"] = self.age() info["started"] = self.started info["children"] = [] info['wid'] = self.wid for child in get_children(self._worker): info["children"].append(get_info(child)) return info def children(self): """Return a list of children pids.""" return [child.pid for child in get_children(self._worker)] def is_child(self, pid): """Return True is the given *pid* is a child of that process.""" pids = [child.pid for child in get_children(self._worker)] if pid in pids: return True return False @debuglog def send_signal_child(self, pid, signum): """Send signal *signum* to child *pid*.""" children = dict((child.pid, child) for child in get_children(self._worker)) try: children[pid].send_signal(signum) except KeyError: raise NoSuchProcess(pid) @debuglog def send_signal_children(self, signum, recursive=False): """Send signal *signum* to all children.""" for child in get_children(self._worker, recursive): try: child.send_signal(signum) except OSError as e: if e.errno != errno.ESRCH: raise @property def status(self): """Return the process status as a constant - RUNNING - DEAD_OR_ZOMBIE - UNEXISTING - OTHER """ try: if get_status(self._worker) in (STATUS_ZOMBIE, STATUS_DEAD): return DEAD_OR_ZOMBIE except NoSuchProcess: return UNEXISTING if self._worker.is_running(): return RUNNING return OTHER @property def pid(self): """Return the *pid*""" return self._worker.pid @property def stdout(self): """Return the *stdout* stream""" return self._worker.stdout @property def stderr(self): """Return the *stdout* stream""" return self._worker.stderr def __eq__(self, other): return self is other def __lt__(self, other): return self.started < other.started def __gt__(self, other): return self.started > other.started
def spawn(self): self.started = time.time() sockets_fds = self._get_sockets_fds() args = self.format_args(sockets_fds=sockets_fds) def preexec(): streams = [] if self.close_child_stdin: streams.append(sys.stdin) if self.close_child_stdout: streams.append(sys.stdout) if self.close_child_stderr: streams.append(sys.stderr) self._null_streams(streams) os.setsid() if resource: for limit, value in self.rlimits.items(): res = getattr( resource, 'RLIMIT_%s' % limit.upper(), None ) if res is None: raise ValueError('unknown rlimit "%s"' % limit) # TODO(petef): support hard/soft limits # for the NOFILE limit, if we fail to set an unlimited # value then check the existing hard limit because we # probably can't bypass it due to a kernel limit - so just # assume that the caller means they want to use the kernel # limit when they pass the unlimited value. This is better # than failing to start the process and forcing the caller # to always be aware of what the kernel configuration is. # If they do pass in a real limit value, then we'll just # raise the failure as they should know that their # expectations couldn't be met. # TODO - we can't log here as this occurs in the child # process after the fork but it would be very good to # notify the admin of the situation somehow. retry = False try: resource.setrlimit(res, (value, value)) except ValueError: if res == resource.RLIMIT_NOFILE and \ value == resource.RLIM_INFINITY: _soft, value = resource.getrlimit(res) retry = True else: raise if retry: resource.setrlimit(res, (value, value)) if self.gid: try: os.setgid(self.gid) except OverflowError: if not ctypes: raise # versions of python < 2.6.2 don't manage unsigned int for # groups like on osx or fedora os.setgid(-ctypes.c_int(-self.gid).value) if self.username is not None: try: os.initgroups(self.username, self.gid) except (OSError, AttributeError): # not support on Mac or 2.6 pass if self.uid: os.setuid(self.uid) if IS_WINDOWS: # On Windows we can't use a pre-exec function preexec_fn = None else: preexec_fn = preexec extra = {} if self.pipe_stdout: extra['stdout'] = PIPE if self.pipe_stderr: extra['stderr'] = PIPE self._worker = Popen(args, cwd=self.working_dir, shell=self.shell, preexec_fn=preexec_fn, env=self.env, close_fds=not self.use_fds, executable=self.executable, **extra) # let go of sockets created only for self._worker to inherit self._sockets = []
def cmd(command, user=None, input=None, cli_input=None, cli_output=False, communicate=True, timeout=None, fail=True, log=None, tries=1, delay_min=5, delay_max=10, **kwargs): """ Calls the `command` and returns a dictionary with process, stdout, stderr, and the returncode. Returned returncode, stdout and stderr will be None if `communicate` is set to False. :param user: If set, this will use ``sudo -u <user> ...`` to execute `command` as `user`. :type user: unicode :param input: If set, sended to stdin (if `communicate` is True). :type input: unicode :param cli_input: If set, sended to stdin (no condition). :type cli_input: unicode :param cli_output: Set to True to output (in real-time) stdout to stdout and stderr to stderr. :type cli_output: bool :param fail: Set to False to avoid the exception `subprocess.CalledProcessError`. :type fail: bool :param log: A function to log/print details about what is executed/any failure, can be a logger. :type log: callable, logging.Logger :param communicate: Set to True to communicate with the process, this is a locking call (if timeout is None). :type communicate: bool :param timeout: Time-out for the communication with the process, in seconds. :type timeout: float :param tries: How many times you want the command to be retried ? :type tries: int :param delay_min: Minimum delay to sleep after every attempt communicate must be True. :type delay: float, int :param delay_max: Maximum delay to sleep after every attempt communicate must be True. :type delay: float, int * Delay will be a random number in range (`delay_min`, `delay_max`) * Set kwargs with any argument of the :mod:`subprocess`.Popen constructor excepting stdin, stdout and stderr. """ # convert log argument to logging functions log_debug = log_warning = log_exception = None if isinstance(log, logging.Logger): log_debug, log_warning, log_exception = log.debug, log.warning, log.exception elif hasattr(log, '__call__'): log_debug = log_warning = log_exception = log # create a list and a string of the arguments if isinstance(command, string_types): if user is not None: command = 'sudo -u {0} {1}'.format(user, command) args_list, args_string = shlex.split(to_bytes(command)), command else: if user is not None: command = ['sudo', '-u', user] + command args_list = [to_bytes(a) for a in command if a is not None] args_string = ' '.join([to_unicode(a) for a in command if a is not None]) # log the execution if log_debug: log_debug('Execute {0}{1}{2}'.format( '' if input is None else 'echo {0}|'.format(repr(input)), args_string, '' if cli_input is None else ' < {0}'.format(repr(cli_input)))) for trial in xrange(tries): # noqa # create the sub-process try: process = Popen( args_list, stdin=subprocess.PIPE, stdout=None if cli_output else subprocess.PIPE, stderr=None if cli_output else subprocess.PIPE, **kwargs) except OSError as e: # unable to execute the program (e.g. does not exist) if log_exception: log_exception(e) if fail: raise return {'process': None, 'stdout': '', 'stderr': e, 'returncode': 2} # write to stdin (answer to questions, ...) if cli_input is not None: process.stdin.write(to_bytes(cli_input)) process.stdin.flush() # interact with the process and wait for the process to terminate if communicate: data = {} # thanks http://stackoverflow.com/questions/1191374/subprocess-with-timeout def communicate_with_timeout(data=None): data['stdout'], data['stderr'] = process.communicate(input=input) thread = threading.Thread(target=communicate_with_timeout, kwargs={'data': data}) thread.start() thread.join(timeout=timeout) if thread.is_alive(): try: process.terminate() thread.join() except OSError as e: # Manage race condition with process that may terminate just after the call to # thread.is_alive() ! if e.errno != errno.ESRCH: raise stdout, stderr = data['stdout'], data['stderr'] else: # get a return code that may be None of course ... process.poll() stdout = stderr = None result = { 'process': process, 'stdout': stdout, 'stderr': stderr, 'returncode': process.returncode } if process.returncode == 0: break # failed attempt, may retry do_retry = trial < tries - 1 delay = random.uniform(delay_min, delay_max) if log_warning: log_warning('Attempt {0} out of {1}: {2}'.format(trial+1, tries, 'Will retry in {0} seconds'.format(delay) if do_retry else 'Failed')) # raise if this is the last try if fail and not do_retry: raise subprocess.CalledProcessError(process.returncode, args_string, stderr) if do_retry: time.sleep(delay) return result
def check_cmd_output(cmd): proc = Popen(cmd, stdout=PIPE, shell=True) exit_code = proc.wait(timeout=5) if exit_code != 0: raise ValueError(u"No HDHR device found") return proc.stdout
def save_file(self, cover,directory,getcover,cloud, cover_size): if(self.mode=='reader'): # need.cover means that directory system/thumbnails has been found on the Kindle (this is Kindle PW) if self.kindle.need_cover: if cover != '': try: ready_cover = Image.open(cover) # ready_cover.thumbnail((217, 330), Image.ANTIALIAS) if self.cover_size =='pw': ready_cover = ready_cover.resize((217, 330), Image.ANTIALIAS) else: ready_cover = ready_cover.resize((330, 470), Image.ANTIALIAS) ready_cover = ready_cover.convert('L') self.txt2img(self.title, self.seqnumber, ready_cover, self.position) except: raise OSError('Failed to load custom cover!') else: if getcover=='search': # search for cover try: ready_cover = self.get_cover_image() except: if(self.write_thumb): #raise OSError('Failed to extract cover!') try: if sys.frozen or sys.importers: butler_dir = os.path.dirname(sys.executable) except AttributeError: butler_dir = os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe()))) path_to_cover = butler_dir + "\\default_banner.jpeg" ready_cover = Image.open(path_to_cover) if self.cover_size =='pw': ready_cover = ready_cover.resize((217, 330), Image.ANTIALIAS) else: ready_cover = ready_cover.resize((330, 470), Image.ANTIALIAS) ready_cover = ready_cover.convert('L') self.txt2defaultcover(self.title, self.author, self.seqnumber, ready_cover, self.position ) else: # extract cover try: # ready_cover = self.get_cover_image() extractcover_34.extractThumbnail(self.path, "tmpdir.$$$"); shutil.rmtree("tmpdir.$$$") coverfile = 'images.$$$' + '\\' + self.infilename +'.cover' + '.jpeg' ready_cover = Image.open(coverfile) ready_cover = ready_cover.resize((217, 330), Image.ANTIALIAS) ready_cover = ready_cover.convert('L') self.txt2img(self.title, self.seqnumber, ready_cover, self.position) shutil.rmtree("images.$$$") except: if(self.write_thumb): #shutil.rmtree("images.$$$") #raise OSError('Failed to extract cover!') try: if sys.frozen or sys.importers: butler_dir = os.path.dirname(sys.executable) except AttributeError: butler_dir = os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe()))) path_to_cover = butler_dir + "\\default_banner.jpeg" ready_cover = Image.open(path_to_cover) if self.cover_size =='pw': ready_cover = ready_cover.resize((217, 330), Image.ANTIALIAS) else: ready_cover = ready_cover.resize((330, 470), Image.ANTIALIAS) ready_cover = ready_cover.convert('L') self.txt2defaultcover(self.title, self.author, self.seqnumber, ready_cover, self.position) if self.kindle.ssh: tmp_cover = os.path.join(gettempdir(), 'KindleButlerCover') ready_cover.save(tmp_cover, 'JPEG') ssh = Popen('"' + self.config['SSH']['PSCPPath'] + '" "' + tmp_cover + '" root@' + self.kindle.path + ':/mnt/us/system/thumbnails/thumbnail_' + self.asin + '_EBOK_portrait.jpg', stdout=PIPE, stderr=STDOUT, shell=True) ssh_check = ssh.wait() if ssh_check != 0: raise OSError('Failed to upload cover!') os.remove(tmp_cover) else: if(self.write_thumb): if(cloud=='no'): ready_cover.save(os.path.join(self.kindle.path, 'system', 'thumbnails', 'thumbnail_' + self.asin + '_EBOK_portrait.jpg'), 'JPEG') else: # get ASIN from file section = KindleUnpack.Sectionizer(self.path) mhlst = [KindleUnpack.MobiHeader(section, 0)] mh = mhlst[0] metadata = mh.getmetadata() assa = metadata.get('ASIN') assassin = assa[0].decode("utf-8") if assassin==None: assassin='None' ready_cover.save(os.path.join(self.kindle.path, 'system', 'thumbnails', 'thumbnail_' + assassin + '_PDOC_portrait.jpg'), 'JPEG') # for all modes prepare processed file try: # noinspection PyArgumentList ready_file = DualMetaFix.DualMobiMetaFix(self.path, bytes(self.asin,'UTF-8'),cloud) except: raise OSError('E-Book modification failed!') ready_file, source_size = ready_file.getresult() # save processed file to reader if(self.mode=='reader'): if source_size < self.kindle.get_free_space(): if self.kindle.ssh: tmp_book = os.path.join(gettempdir(), os.path.basename(self.path)) open(tmp_book, 'wb').write(ready_file.getvalue()) ssh = Popen('"' + self.config['SSH']['PSCPPath'] + '" "' + tmp_book + '" root@' + self.kindle.path + ':/mnt/us/documents/', stdout=PIPE, stderr=STDOUT, shell=True) for line in ssh.stdout: for inside_line in line.split(b'\r'): if b'|' in inside_line: inside_line = inside_line.decode('utf-8').split(' | ')[-1].rstrip()[:-1] self.progressbar['value'] = int(inside_line) ssh_check = ssh.wait() os.remove(tmp_book) if ssh_check != 0: raise OSError('Failed to upload E-Book!') Popen('"' + self.config['SSH']['PLinkPath'] + '" root@' + self.kindle.path + ' "dbus-send --system /default com.lab126.powerd.resuming int32:1"', stdout=PIPE, stderr=STDOUT, shell=True) else: if cloud=='no': saved = 0 if directory == None: target = open(os.path.join(self.kindle.path, 'documents', os.path.basename(self.path)), 'wb') else: new_dir = self.kindle.path + 'documents' + '\\' + directory self.make_sure_path_exists(new_dir) target = open(new_dir + '\\' + os.path.basename(self.path), 'wb') # target = open(os.path.join(self.kindle.path, 'documents' + '\\directory', os.path.basename(self.path)), 'wb') while True: chunk = ready_file.read(32768) if not chunk: break target.write(chunk) saved += len(chunk) self.progressbar['value'] = int((saved/source_size)*100) else: raise OSError('Not enough space on target device!') # save cover and processed book to pc if(self.mode=='pc'): # prepare and save cover # if key -a asin then self.write_thumb=False and no need to save cover if cover != '': # means that cover was imported from external file try: ready_cover = Image.open(cover) if self.cover_size =='pw': ready_cover = ready_cover.resize((217, 330), Image.ANTIALIAS) else: ready_cover = ready_cover.resize((330, 470), Image.ANTIALIAS) ready_cover = ready_cover.convert('L') self.txt2img(self.title, self.seqnumber, ready_cover, self.position) except: raise OSError('Failed to load custom cover!') else: # search/extract cover from inside the book if(getcover=='search'): #search for cover try: ready_cover = self.get_cover_image() except: if(self.write_thumb): #raise OSError('Failed to extract cover!') self.no_cover = True try: if sys.frozen or sys.importers: butler_dir = os.path.dirname(sys.executable) except AttributeError: butler_dir = os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe()))) path_to_cover = butler_dir + "\\default_banner.jpeg" ready_cover = Image.open(path_to_cover) if self.cover_size =='pw': ready_cover = ready_cover.resize((217, 330), Image.ANTIALIAS) else: ready_cover = ready_cover.resize((330, 470), Image.ANTIALIAS) ready_cover = ready_cover.convert('L') self.txt2defaultcover(self.title, self.author, self.seqnumber, ready_cover, self.position) else: #extract the cover from the book try: # ready_cover = self.get_cover_image() extractcover_34.extractThumbnail(self.path, "tmpdir.$$$"); shutil.rmtree("tmpdir.$$$") coverfile = 'images.$$$' + '\\' + self.infilename +'.cover' + '.jpeg' ready_cover = Image.open(coverfile) if self.cover_size =='pw': ready_cover = ready_cover.resize((217, 330), Image.ANTIALIAS) else: ready_cover = ready_cover.resize((330, 470), Image.ANTIALIAS) ready_cover = ready_cover.convert('L') self.txt2img(self.title, self.seqnumber, ready_cover, self.position) except: if(self.write_thumb): # shutil.rmtree("images.$$$") #raise OSError('Failed to extract cover!') self.no_cover = True try: if sys.frozen or sys.importers: butler_dir = os.path.dirname(sys.executable) except AttributeError: butler_dir = os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe()))) path_to_cover = butler_dir + "\\default_banner.jpeg" ready_cover = Image.open(path_to_cover) if self.cover_size =='pw': ready_cover = ready_cover.resize((217, 330), Image.ANTIALIAS) else: ready_cover = ready_cover.resize((330, 470), Image.ANTIALIAS) ready_cover = ready_cover.convert('L') self.txt2defaultcover(self.title, self.author, self.seqnumber, ready_cover, self.position) if(self.write_thumb): if cloud=='no': ready_cover.save('thumbnail_' + self.asin + '_EBOK_portrait.jpg', 'JPEG') else: # get ASIN from file section = KindleUnpack.Sectionizer(self.path) mhlst = [KindleUnpack.MobiHeader(section, 0)] mh = mhlst[0] metadata = mh.getmetadata() assa = metadata.get('ASIN') assassin = assa[0].decode("utf-8") if assassin==None: assassin='None' ready_cover.save('thumbnail_' + assassin + '_EBOK_portrait.jpg', 'JPEG') if getcover !='search' and cover == '' and self.no_cover == False: shutil.rmtree("images.$$$") if cloud=='no': #save processed file saved = 0 # ready_file.seek(0) target = open(self.infilename + '.processed' + self.infileext, 'wb') while True: chunk = ready_file.read(32768) if not chunk: break target.write(chunk) saved += len(chunk) self.progressbar['value'] = int((saved/source_size)*100)