def new_terminal(self, ip_address="", **kwargs): """Make a new terminal, return a :class:`PtyWithClients` instance.""" options = self.term_settings.copy() options['shell_command'] = self.shell_command options.update(kwargs) env = self.make_term_env(**options) if ip_address == "": argv = options['shell_command'] pty = PtyProcessUnicode.spawn(argv, env=env, cwd=options.get('cwd', None)) else: argv = 'ssh admin@%s' % (ip_address) pty = pexpect.spawn(argv, env=env, cwd=options.get('cwd', None)) ssh_newkey = 'Are you sure you want to continue connecting' i = pty.expect([pexpect.TIMEOUT, ssh_newkey, 'password: '******'yes') pty.expect('password: '******'password: '******'Connect to server timeout') return None pty.sendline('admin') return PtyWithClients(pty)
def open(self): """Open ThreadedTerminal connection & start thread pulling data from it.""" ret = super(ThreadedTerminal, self).open() if not self._terminal: self._terminal = PtyProcessUnicode.spawn( self._cmd, dimensions=self.dimensions) # need to not replace not unicode data instead of raise exception self._terminal.decoder = codecs.getincrementaldecoder('utf-8')( errors='replace') done = Event() self.pulling_thread = TillDoneThread(target=self.pull_data, done_event=done, kwargs={'pulling_done': done}) self.pulling_thread.start() retry = 0 is_operable = False while (retry < 10) and (not is_operable): is_operable = self._shell_operable.wait(timeout=1) if not is_operable: self.logger.warning( "Terminal open but not fully operable yet.\nREAD_BUFFER: '{}'" .format(self.read_buffer.encode("UTF-8", "replace"))) self._terminal.write('\n') retry += 1 return ret
def new_terminal(self, **kwargs): options = self.term_settings.copy() options['shell_command'] = self.shell_command options.update(kwargs) argv = options['shell_command'] env = self.make_term_env(**options) pty = PtyProcessUnicode.spawn(argv, env=env, cwd=options.get('cwd', None)) return PtyWithClients(pty)
def new_terminal(self, **kwargs): """Make a new terminal, return a :class:`PtyWithClients` instance.""" options = self.term_settings.copy() options['shell_command'] = self.shell_command options.update(kwargs) argv = options['shell_command'] env = self.make_term_env(**options) pty = PtyProcessUnicode.spawn(argv, env=env, cwd=options.get('cwd', None)) return PtyWithClients(pty)
def open(self): """Open ThreadedTerminal connection & start thread pulling data from it.""" if not self._terminal: self._terminal = PtyProcessUnicode.spawn( self._cmd, dimensions=self.dimensions) done = Event() self.pulling_thread = TillDoneThread(target=self.pull_data, done_event=done, kwargs={'pulling_done': done}) self.pulling_thread.start() self._shell_operable.wait(timeout=2)
def __init__(self, argv, env=[], cwd=None): self.clients = [] # If you start the process and then construct this object from it, # output generated by the process prior to the object's creation # is lost. Hence the change from 0.8.3. # Buffer output until a client connects; then let the client # drain the buffer. # We keep the same read_buffer as before self.read_buffer = deque([], maxlen=10) self.preopen_buffer = deque([]) self.ptyproc = PtyProcessUnicode.spawn(argv, env=env, cwd=cwd)
def _import_torrent(torrent): proc = PtyProcessUnicode.spawn([ "beet", "import", "--noresume", _calculate_import_path(torrent), ]) PROCESSES[torrent.id] = proc _read_and_send_pty_out(proc, torrent) exit_status = _right_exit_status(proc.exitstatus) return exit_status
def __init__(self, argv, env=[], cwd=None): self.clients = [] # Use read_buffer to store historical messages for reconnection self.read_buffer = deque([], maxlen=1000) kwargs = dict(argv=argv, env=env, cwd=cwd) if preexec_fn is not None: kwargs["preexec_fn"] = preexec_fn self.ptyproc = PtyProcessUnicode.spawn(**kwargs) # The output might not be strictly UTF-8 encoded, so # we replace the inner decoder of PtyProcessUnicode # to allow non-strict decode. self.ptyproc.decoder = codecs.getincrementaldecoder('utf-8')(errors='replace')
def kill_spawned_process(self): """ Kill spawned process inside container. If process of `docker exec` was killed, the spawned process inside container is still running. So we should kill spawned process before kill `docker exec`. """ p = PtyProcessUnicode.spawn(['docker', 'exec', self.container_id, '/bin/sh', '-c', 'kill -1 $(cat /tmp/sh.pid.{})'.format(self.uuid)]) # wait till complete execution of command while p.isalive(): sleep(1) p.close()
def new_one(self, **kwargs): """Make a new terminal, return a :class:`PtyWithClients` instance.""" options = {} options['shell_command'] = self.shell_command options.update(kwargs) argv = options['shell_command'] env = self.make_term_env(**options) self.proc = PtyProcessUnicode.spawn(argv, env=env, cwd=options.get('cwd', None)) return self
def kill_spawned_process(self): """ Kill spawned process inside container. If process of `docker exec` was killed, the spawned process inside container is still running. So we should kill spawned process before kill `docker exec`. """ p = PtyProcessUnicode.spawn([ 'docker', 'exec', self.container_id, '/bin/sh', '-c', 'kill -1 $(cat /tmp/sh.pid.{})'.format(self.uuid) ]) # wait till complete execution of command while p.isalive(): sleep(1) p.close()
def test_spawn_unicode_sh(self): env = os.environ.copy() env['FOO'] = 'rebar' p = PtyProcessUnicode.spawn(['sh'], env=env) p.read() p.write(u'echo $FOO\n') time.sleep(0.1) response = p.read() assert u'rebar' in response p.sendeof() p.read() with self.assertRaises(EOFError): p.read()
def test_spawn_unicode_sh(self): env = os.environ.copy() env['FOO'] = 'rebar' p = PtyProcessUnicode.spawn(['sh'], env=env) p.read() p.write(u'echo $FOO\n') time.sleep(0.1) response = p.read() assert u'rebar' in response p.sendeof() p.readline() with self.assertRaises(EOFError): p.read()
def _interactive_repl_unicode(self, echo): """Test Call and response with echo ON/OFF.""" # given, bc = PtyProcessUnicode.spawn(['bc'], echo=echo) given_input = u'2+2+2+2+2+2+2+2+2+2+2+2+2+2+2+2+2+2+2+2\n' expected_output = u'40' # gnu-bc will display a long FSF banner on startup, # whereas bsd-bc (on FreeBSD, Solaris) display no # banner at all. To ensure we've read up to our # current prompt, read until the response of '2^16' is found. time.sleep(1) bc.write(u'2^16\n') outp = u'' while self._canread(bc.fd): outp += bc.read() assert u'65536' in outp # exercise, bc.write(given_input) while self._canread(bc.fd, timeout=2): outp += bc.read() # with echo ON, we should see our input. # # note: we cannot assert the reverse: on Solaris, FreeBSD, # and OSX, our input is echoed to output even with echo=False, # something to do with the non-gnu version of bc(1), perhaps. if echo: assert given_input.strip() in outp # we should most certainly see the result output. assert expected_output in outp # exercise sending EOF bc.sendeof() # validate EOF on read while True: try: bc.read() except EOFError: break # validate exit status, assert bc.wait() == 0
def run(self) -> int: from codecs import getreader import subprocess as sp import sys from cleo.io.io import OutputType # type: ignore[import] from ptyprocess import PtyProcessUnicode # type: ignore[import] color = self._colors[ 0] if TestRunner._prev_color is None else self._colors[ (self._colors.index(TestRunner._prev_color) + 1) % len(self._colors)] TestRunner._prev_color = color command = ['bash', '-c', self.config] prefix = f'{self.name}| ' try: cols, rows = os.get_terminal_size() except OSError: sproc = sp.Popen(command, cwd=self.cwd, stdout=sp.PIPE, stderr=sp.STDOUT) assert sproc.stdout stdout = getreader(sys.getdefaultencoding())(sproc.stdout) for line in iter(stdout.readline, ''): line = line.rstrip() if self.line_prefixing: self.io.write(f'<fg={color}>{prefix}</fg>') self.io.write(line + '\n', type=OutputType.NORMAL) sproc.wait() assert sproc.returncode is not None return sproc.returncode else: proc = PtyProcessUnicode.spawn(command, dimensions=(rows, cols - len(prefix)), cwd=self.cwd) while not proc.eof(): try: line = proc.readline().rstrip() except EOFError: break if self.line_prefixing: self.io.write(f'<fg={color}>{prefix}</fg>') self.io.write(line + '\n', type=OutputType.NORMAL) proc.wait() assert proc.exitstatus is not None return proc.exitstatus
def __init__(self, argv, cwd=None, env=None, name='tty', dimensions=(24, 80)): ptyproc = PtyProcessUnicode.spawn(argv, env=env, cwd=cwd) self.ptyproc = ptyproc self.name = name self.read_watch = FdWatcher(self) # tracker for XtermSocketHandler connected to this terminal self.clients = [] # Store the last few things read, so when a new client connects, # it can show e.g. the most recent prompt, rather than absolutely # nothing. self.read_buffer = deque([], maxlen=15)
def __init__(self, argv, env=[], cwd=None): self.clients = [] # If you start the process and then construct this object from it, # output generated by the process prior to the object's creation # is lost. Hence the change from 0.8.3. # Buffer output until a client connects; then let the client # drain the buffer. # We keep the same read_buffer as before self.read_buffer = deque([], maxlen=10) self.preopen_buffer = deque([]) kwargs = dict(argv=argv, env=env, cwd=cwd) if preexec_fn is not None: kwargs["preexec_fn"] = preexec_fn self.ptyproc = PtyProcessUnicode.spawn(**kwargs) # The output might not be strictly UTF-8 encoded, so # we replace the inner decoder of PtyProcessUnicode # to allow non-strict decode. self.ptyproc.decoder = codecs.getincrementaldecoder('utf-8')(errors='replace')
async def run_in_terminal(msg, send, context): root = context.shared.project_root mode = msg['mode'] path = Path(root, *msg.get('filePath', [])).resolve() args = shlex.split(msg.get('args', '')) await stop(msg, send, context) if mode == 'script': command = ['python', shlex.quote(str(path))] + args elif mode == 'module': module = '.'.join(path.relative_to(root).parts[:-1] + (path.stem, )) command = ['python', '-m', module] + args elif mode == 'shell': command = shlex.split(msg['command']) else: raise ValueError('unsupported mode') cwd = msg.get('cwd', None) if not cwd: cwd = str(root) cwd = shlex.quote(cwd) if IS_PTY: pty = PtyProcessUnicode.spawn(command, cwd=cwd, dimensions=(msg['rows'], msg['cols'])) await send('Started', None) context.pty = pty loop = asyncio.get_event_loop() context.reader = asyncio.ensure_future( loop.run_in_executor( None, partial(reader, pty, context.main_thread_send, context))) else: pty = await asyncio.create_subprocess_shell(shlex.join(command), stdin=PIPE, stdout=PIPE, stderr=STDOUT, cwd=cwd, bufsize=0) await send('Started', None) context.pty = pty context.reader = asyncio.create_task(async_reader(pty, send)) context.reader = asyncio.create_task(wait_until_finish(pty, send))
def start_pty(self, *args): if not self.container_id: self.send_error_and_close("Error: container not found.") return try: # create a pseudo terminal of container by command: # `docker exec -ti <container_id> /bin/sh -c '[ -x /bin/bash ] && /bin/bash || /bin/sh'` # and then set the stream to non-blocking mode. pty = PtyProcessUnicode.spawn( ['docker', 'exec', '-ti', self.container_id, '/bin/sh', '-c', 'echo $$ > /tmp/sh.pid.{} && [ -x /bin/bash ] && /bin/bash || /bin/sh'.format(self.uuid)]) flags = fcntl(pty.fileobj, F_GETFL) fcntl(pty.fileobj, F_SETFL, flags | O_NONBLOCK) setattr(self, "pty", pty) TerminalSocketHandler.clients.update({self: pty}) logger.info('Connect to console of container {}'.format(self.container_id)) except Exception as e: self.send_error_and_close("Error: cannot start console: {}".format(e))
def run_pty_subprocess(cmd: List[str], capture: Capture = Capture.BOTH, stdin: Optional[str] = None) -> Tuple[int, str]: """ Run a command in a PTY subprocess. Arguments: cmd: The command to run. capture: The output to capture. stdin: String to use as standard input. Returns: The exit code and the command output. """ process = PtyProcessUnicode.spawn(cmd) pty_output: List[str] = [] if stdin is not None: process.setecho(False) process.waitnoecho() process.write(stdin) process.sendeof() # not sure why but sending only one eof is not always enough, # so we send a second one and ignore any IO error with contextlib.suppress(OSError): process.sendeof() while True: try: output_data = process.read() except EOFError: break if capture == Capture.NONE: print(output_data, end="", flush=True) # noqa: WPS421 (print) else: pty_output.append(output_data) output = "".join(pty_output).replace("\r\n", "\n") return process.wait(), output
def start_pty(self, *args): if not self.container_id: self.send_error_and_close("Error: container not found.") return try: # create a pseudo terminal of container by command: # `docker exec -ti <container_id> /bin/sh -c '[ -x /bin/bash ] && /bin/bash || /bin/sh'` # and then set the stream to non-blocking mode. pty = PtyProcessUnicode.spawn([ 'docker', 'exec', '-ti', self.container_id, '/bin/sh', '-c', 'echo $$ > /tmp/sh.pid.{} && [ -x /bin/bash ] && /bin/bash || /bin/sh' .format(self.uuid) ]) flags = fcntl(pty.fileobj, F_GETFL) fcntl(pty.fileobj, F_SETFL, flags | O_NONBLOCK) setattr(self, "pty", pty) TerminalSocketHandler.clients.update({self: pty}) logger.info('Connect to console of container {}'.format( self.container_id)) except Exception as e: self.send_error_and_close( "Error: cannot start console: {}".format(e))
def spawn(self, argv): self.set_quit_signal() self.pty = PtyProcessUnicode.spawn(argv) self._copy() self.pty.wait() return (self.pty.exitstatus, self.log)
script.write(appaware_command) # spin up in a subprocesses pid = os.fork() if pid == 0: abort_oracle_j2 = Template("su - {{ orauser }} -c 'kill -9 -1'") abort_oracle = abort_oracle_j2.render(orauser=act_orauser) def unmountthemount(SignNum, frame): os.system(abort_oracle) appliance.unmount_image(image=mountedimage) # register for the signals signal.signal(signal.SIGINT, unmountthemount) signal.signal(signal.SIGTERM, unmountthemount) while True: time.sleep(60) else: # ignore all the signals... let oracle deal with them for sig in signal.Signals: print(sig) if (sig != signal.SIGKILL): signal.signal(sig, signal.SIG_IGN) # run with a terminal script_proc = PtyProcessUnicode.spawn(["bash", "/script/run.sh"]) while True: print(script_proc.readline())
def _process(self, argv): self.set_quit_signal() self.pty = PtyProcessUnicode.spawn(argv)
from ptyprocess import PtyProcessUnicode p = PtyProcessUnicode.spawn(['python3']) x = p.read(20) print("x=", x) p.write('6+6\n') y = p.read(20) print("y=", y)