def connectionMade(self): sockFD = self.transport.fileno() childFDs = {0: sockFD, 1: sockFD} if self.factory.stderrFile: childFDs[2] = self.factory.stderrFile.fileno() # processes run by inetd expect blocking sockets # FIXME: maybe this should be done in process.py? are other uses of # Process possibly affected by this? fdesc.setBlocking(sockFD) if childFDs.has_key(2): fdesc.setBlocking(childFDs[2]) service = self.factory.service uid = service.user gid = service.group # don't tell Process to change our UID/GID if it's what we # already are if uid == os.getuid(): uid = None if gid == os.getgid(): gid = None process.Process(None, service.program, service.programArgs, os.environ, None, None, uid, gid, childFDs) reactor.removeReader(self.transport) reactor.removeWriter(self.transport)
def connectionMade(self): sockFD = self.transport.fileno() childFDs = {0: sockFD, 1: sockFD} if self.factory.stderrFile: childFDs[2] = self.factory.stderrFile.fileno() # processes run by inetd expect blocking sockets # FIXME: maybe this should be done in process.py? are other uses of # Process possibly affected by this? fdesc.setBlocking(sockFD) if childFDs.has_key(2): fdesc.setBlocking(childFDs[2]) service = self.factory.service uid = service.user gid = service.group # don't tell Process to change our UID/GID if it's what we # already are if uid == os.getuid(): uid = None if gid == os.getgid(): gid = None process.Process(None, service.program, service.programArgs, os.environ, None, None, uid, gid, childFDs) reactor.removeReader(self.transport) reactor.removeWriter(self.transport)
def test_setBlocking(self): """ L{fdesc.setBlocking} sets a file description to blocking. """ r, w = os.pipe() self.addCleanup(os.close, r) self.addCleanup(os.close, w) fdesc.setNonBlocking(r) fdesc.setBlocking(r) self.assertFalse(fcntl.fcntl(r, fcntl.F_GETFL) & os.O_NONBLOCK)
def test_setBlocking(self): """ L{fdesc.setBlocking} sets a file description to blocking. """ r, w = os.pipe() self.addCleanup(os.close, r) self.addCleanup(os.close, w) fdesc.setNonBlocking(r) fdesc.setBlocking(r) self.assertFalse(fcntl.fcntl(r, fcntl.F_GETFL) & os.O_NONBLOCK)
def connectionLost(self, reason): """ See abstract.FileDescriptor.connectionLost. """ # At least on macOS 10.4, exiting while stdout is non-blocking can # result in data loss. For some reason putting the file descriptor # back into blocking mode seems to resolve this issue. fdesc.setBlocking(self.fd) abstract.FileDescriptor.connectionLost(self, reason) self.proc.childConnectionLost(self.name, reason)
def connectionLost(self, reason): """ See abstract.FileDescriptor.connectionLost. """ # At least on OS X 10.4, exiting while stdout is non-blocking can # result in data loss. For some reason putting the file descriptor # back into blocking mode seems to resolve this issue. fdesc.setBlocking(self.fd) abstract.FileDescriptor.connectionLost(self, reason) self.proc.childConnectionLost(self.name, reason)
def _read_loop(self): while True: try: # I/O routing r, w, e = select.select([self.socket, sys.stdin], [], []) if self.socket in r: data = self.socket.recv(1024) if data: self._receive(data) else: # Nothing received? End of stream. break if sys.stdin in r: # Non blocking read. (Write works better in blocking mode. # Especially on OS X.) fdesc.setNonBlocking(sys.stdin) data = sys.stdin.read(1024) # We read larger chuncks (more than just one byte) in # one go. This is important for meta and arrow keys # which consist of multiple bytes. Many applications # rely on this that they'll receive them together. fdesc.setBlocking(sys.stdin) # If we're finish and 'wait_for_closing' was set. Any key # press will terminate the client. if self.wait_for_closing: break if chr(14) in data: # Ctrl-N # Tell the server to open a new window. self.socket.sendall( pickle.dumps(('open-new-window', ''))) else: self.socket.sendall(pickle.dumps(('_input', data))) except socket.error: print '\nConnection closed...' break except Exception as e: # SIGWINCH will abort select() call. Just ignore this error if e.args and e.args[0] == errno.EINTR: continue else: raise
def _read_loop(self): while True: try: # I/O routing r, w, e = select.select([ self.socket, sys.stdin ], [], []) if self.socket in r: data = self.socket.recv(1024) if data: self._receive(data) else: # Nothing received? End of stream. break if sys.stdin in r: # Non blocking read. (Write works better in blocking mode. # Especially on OS X.) fdesc.setNonBlocking(sys.stdin) data = sys.stdin.read(1024) # We read larger chuncks (more than just one byte) in # one go. This is important for meta and arrow keys # which consist of multiple bytes. Many applications # rely on this that they'll receive them together. fdesc.setBlocking(sys.stdin) # If we're finish and 'wait_for_closing' was set. Any key # press will terminate the client. if self.wait_for_closing: break if chr(14) in data: # Ctrl-N # Tell the server to open a new window. self.socket.sendall(pickle.dumps(('open-new-window', ''))) else: self.socket.sendall(pickle.dumps(('_input', data))) except socket.error: print '\nConnection closed...' break except Exception as e: # SIGWINCH will abort select() call. Just ignore this error if e.args and e.args[0] == errno.EINTR: continue else: raise
def _read_loop(self): while True: try: # I/O routing r, w, e = select.select([ self.socket, sys.stdin ], [], []) if self.socket in r: data = self.socket.recv(1024) if data: self._receive(data) else: # Nothing received? End of stream. break if sys.stdin in r: # Non blocking read. (Write works better in blocking mode. # Especially on OS X.) fdesc.setNonBlocking(sys.stdin) data = sys.stdin.read(1) fdesc.setBlocking(sys.stdin) # If we're finish and 'wait_for_closing' was set. Any key # press will terminate the client. if self.wait_for_closing: break if ord(data) == 14: # Ctrl-N # Tell the server to open a new window. self.socket.sendall(pickle.dumps(('open-new-window', ''))) else: self.socket.sendall(pickle.dumps(('_input', data))) except socket.error: print '\nConnection closed...' break except Exception as e: # SIGWINCH will abort select() call. Just ignore this error if e.args and e.args[0] == errno.EINTR: continue else: raise
def run(self, stdin=None, stdout=None, stderr=None): "Start the task, returning status via <task>.deferred callbacks when the task completes. The keyword arguments stdin, stdout, and stderr may be used to override the ones provided at initialization." if stdin is None: stdin = getattr(self, 'stdin', None) if stdout is None: stdout = getattr(self, 'stdout', None) if stderr is None: stderr = getattr(self, 'stderr', None) fd = stdin prev = None for task in self.args: if prev: self.run_sub(prev, stdin=fd) fd = prev.proc.pipes.pop(1) fdesc.setBlocking(fd) fd.stopReading() fd = fd.fileno() prev = task if prev: self.run_sub(prev, stdin=fd, stdout=stdout, stderr=stderr) else: self.deferred.callback(None)
def _posix_shell(self, chan, raw=True, initial_input=None): """ Create a loop which redirects sys.stdin/stdout into this channel. The loop ends when channel.recv() returns 0. Code inspired by the Paramiko interactive demo. """ result = [] password_sent = False # Set terminal in raw mode if raw: context = raw_mode(self.pty.stdin) else: context = contextlib.nested() assert self.pty.set_ssh_channel_size with context: # Make channel non blocking. chan.settimeout(0.0) # When initial input has been given, send this first if initial_input: time.sleep( 0.2 ) # Wait a very short while for the channel to be initialized, before sending. chan.send(initial_input) reading_from_stdin = True # Read/write loop while True: # Don't wait for any input when an exit status code has been # set already. (But still wait for the output to finish.) if chan.status_event.isSet(): reading_from_stdin = False # When the channel is closed, and there's nothing to read # anymore. We can return what we got from Paramiko. (Not # sure why this happens. Most of the time, select() still # returns and chan.recv() returns an empty string, but when # read_ready is False, select() doesn't return anymore.) if chan.closed and not chan.in_buffer.read_ready(): break channels = [self.pty.stdin, chan ] if reading_from_stdin else [chan] r, w, e = select(channels, [], [], 1) # Note the select-timeout. That is required in order to # check for the status_event every second. # Receive stream if chan in r: try: x = chan.recv(1024) # Received length 0 -> end of stream if len(x) == 0: break # Write received characters to stdout and flush while True: try: self.pty.stdout.write(x) break except IOError as e: # Sometimes, when we have a lot of output, we get here: # IOError: [Errno 11] Resource temporarily unavailable # Just waiting a little, and retrying seems to work. # See also: deployer.run.socket_client for a similar issue. time.sleep(0.2) self.pty.stdout.flush() # Also remember received output. # We want to return what's written to stdout. result.append(x) # Do we need to send the sudo password? (It's when the # magic prompt has been detected in the stream) Note # that we only monitor the last part of 'result', it's # a bit fuzzy, but works. if not password_sent and self.magic_sudo_prompt in ''.join( result[-32:]): chan.send(self.password) chan.send('\n') password_sent = True except socket.timeout: pass # Send stream (one by one character) # (use 'elif', read stdin only when there is no more output to be received.) elif self.pty.stdin in r: try: # Make stdin non-blocking. (The select call already # blocked for us, we want sys.stdin.read() to read # as many bytes as possible without blocking.) try: fdesc.setNonBlocking(self.pty.stdin) x = self.pty.stdin.read(1024) finally: # Set stdin blocking again # (Writing works better in blocking mode. # Especially OS X seems to be very sensitive if we # write lange amounts [>1000 bytes] nonblocking to # stdout. That causes a lot of IOErrors.) fdesc.setBlocking(self.pty.stdin) # We receive \n from stdin, but \r is required to # send. (Until now, the only place where the # difference became clear is in redis-cli, which # only accepts \r as confirmation.) x = x.replace('\n', '\r') except IOError as e: # What to do with IOError exceptions? # (we see what happens in the next select-call.) continue # Received length 0 # There's no more at stdin to read. if len(x) == 0: # However, we should go on processing the input # from the remote end, until the process finishes # there (because it was done or processed Ctrl-C or # Ctrl-D/EOF.) # # The end of the input stream happens when we are # using StringIO at the client side, and we're not # attached to a real pseudo terminal. (For # unit-testing, or background commands.) reading_from_stdin = False continue # Write to channel chan.send(x) # Not sure about this. Sometimes, when pasting large data # in the command line, the many concecutive read or write # commands will make Paramiko hang somehow... (This was # the case, when still using a blocking pty.stdin.read(1) # instead of a non-blocking readmany. time.sleep(0.01) return ''.join(result)
def _posix_shell(self, chan, raw=True, initial_input=None): """ Create a loop which redirects sys.stdin/stdout into this channel. The loop ends when channel.recv() returns 0. Code inspired by the Paramiko interactive demo. """ result = [] password_sent = False # Set terminal in raw mode if raw: context = raw_mode(self.pty.stdin) else: context = contextlib.nested() assert self.pty.set_ssh_channel_size with context: # Make channel non blocking. chan.settimeout(0.0) # When initial input has been given, send this first if initial_input: time.sleep(0.2) # Wait a very short while for the channel to be initialized, before sending. chan.send(initial_input) reading_from_stdin = True # Read/write loop while True: # Don't wait for any input when an exit status code has been # set already. (But still wait for the output to finish.) if chan.status_event.isSet(): reading_from_stdin = False # When the channel is closed, and there's nothing to read # anymore. We can return what we got from Paramiko. (Not # sure why this happens. Most of the time, select() still # returns and chan.recv() returns an empty string, but when # read_ready is False, select() doesn't return anymore.) if chan.closed and not chan.in_buffer.read_ready(): break channels = [self.pty.stdin, chan] if reading_from_stdin else [chan] r, w, e = select(channels, [], [], 1) # Note the select-timeout. That is required in order to # check for the status_event every second. # Receive stream if chan in r: try: x = chan.recv(1024) # Received length 0 -> end of stream if len(x) == 0: break # Write received characters to stdout and flush while True: try: self.pty.stdout.write(x) break except IOError as e: # Sometimes, when we have a lot of output, we get here: # IOError: [Errno 11] Resource temporarily unavailable # Just waiting a little, and retrying seems to work. # See also: deployer.run.socket_client for a similar issue. time.sleep(0.2) self.pty.stdout.flush() # Also remember received output. # We want to return what's written to stdout. result.append(x) # Do we need to send the sudo password? (It's when the # magic prompt has been detected in the stream) Note # that we only monitor the last part of 'result', it's # a bit fuzzy, but works. if not password_sent and self.magic_sudo_prompt in ''.join(result[-32:]): chan.send(self.password) chan.send('\n') password_sent = True except socket.timeout: pass # Send stream (one by one character) # (use 'elif', read stdin only when there is no more output to be received.) elif self.pty.stdin in r: try: # Make stdin non-blocking. (The select call already # blocked for us, we want sys.stdin.read() to read # as many bytes as possible without blocking.) try: fdesc.setNonBlocking(self.pty.stdin) x = self.pty.stdin.read(1024) finally: # Set stdin blocking again # (Writing works better in blocking mode. # Especially OS X seems to be very sensitive if we # write lange amounts [>1000 bytes] nonblocking to # stdout. That causes a lot of IOErrors.) fdesc.setBlocking(self.pty.stdin) # We receive \n from stdin, but \r is required to # send. (Until now, the only place where the # difference became clear is in redis-cli, which # only accepts \r as confirmation.) x = x.replace('\n', '\r') except IOError as e: # What to do with IOError exceptions? # (we see what happens in the next select-call.) continue # Received length 0 # There's no more at stdin to read. if len(x) == 0: # However, we should go on processing the input # from the remote end, until the process finishes # there (because it was done or processed Ctrl-C or # Ctrl-D/EOF.) # # The end of the input stream happens when we are # using StringIO at the client side, and we're not # attached to a real pseudo terminal. (For # unit-testing, or background commands.) reading_from_stdin = False continue # Write to channel chan.send(x) # Not sure about this. Sometimes, when pasting large data # in the command line, the many concecutive read or write # commands will make Paramiko hang somehow... (This was # the case, when still using a blocking pty.stdin.read(1) # instead of a non-blocking readmany. time.sleep(0.01) return ''.join(result)
def doRead(self): try: setBlocking(False,0) return fdesc.readFromFD(0, self.dataReceived) finally: fdesc.setBlocking(True,0)
def _posix_shell(self, pty, chan, raw=True, log_entry=None, initial_input=None): """ Create a loop which redirects sys.stdin/stdout into this channel. The loop ends when channel.recv() returns 0. Code inspired by the Paramiko interactive demo. """ result = [] password_sent = False # Save terminal attributes oldtty = termios.tcgetattr(pty.stdin) # Make stdin non-blocking. (The select call will already # block for us, we want sys.stdin.read() to read as many # bytes as possible without blocking.) fdesc.setNonBlocking(pty.stdin) try: # Set terminal raw if raw: tty.setraw(pty.stdin.fileno()) tty.setcbreak(pty.stdin.fileno()) chan.settimeout(0.0) # When initial input has been given, send this first if initial_input: time.sleep(0.2) # Wait a very short while for the channel to be initialized, before sending. chan.send(initial_input) # Read/write loop while True: # Don't wait for any input when an exit status code has been # set already. if chan.status_event.isSet(): break; r, w, e = select([pty.stdin, chan], [], []) # Receive stream if chan in r: try: x = chan.recv(1024) # Received length 0 -> end of stream if len(x) == 0: break # Log received characters log_entry.log_io(x) # Write received characters to stdout and flush pty.stdout.write(x) pty.stdout.flush() # Also remember received output. # We want to return what's written to stdout. result.append(x) # Do we need to send the sudo password? (It's when the # magic prompt has been detected in the stream) Note # that we only monitor the last part of 'result', it's # a bit fuzzy, but works. if not password_sent and self.magic_sudo_prompt in ''.join(result[-32:]): chan.send(self.password) chan.send('\n') password_sent = True except socket.timeout: pass # Send stream (one by one character) if pty.stdin in r: try: x = pty.stdin.read(1024) except IOError, e: # What to do with IOError exceptions? # (we see what happens in the next select-call.) continue # Received length 0 -> end of stream if len(x) == 0: break # Write to channel chan.send(x) # Not sure about this. Sometimes, when pasting large data # in the command line, the many concecutive read or write # commands will make Paramiko hang somehow... (This was # the case, when still using a blocking pty.stdin.read(1) # instead of a non-blocking readmany. time.sleep(0.01) finally: # Restore terminal termios.tcsetattr(pty.stdin, termios.TCSADRAIN, oldtty) # Set blocking again fdesc.setBlocking(pty.stdin) return ''.join(result)
def __init__(self, *a, **kw): process.ProcessReader.__init__(self, *a, **kw) fdesc.setBlocking(sys.stdin.fileno())
def __init__(self,*a,**k): super(StdIO,self).__init__(*a,**k) fdesc.setBlocking(self._writer.fd)
# unit-testing, or background commands.) reading_from_stdin = False continue # Write to channel chan.send(x) # Not sure about this. Sometimes, when pasting large data # in the command line, the many concecutive read or write # commands will make Paramiko hang somehow... (This was # the case, when still using a blocking pty.stdin.read(1) # instead of a non-blocking readmany. time.sleep(0.01) finally: # Set blocking again fdesc.setBlocking(pty.stdin) return ''.join(result) # =====[ SFTP operations ]==== def _expand_local_path(self, path): # Only tilde expansion return os.path.expanduser(path) def expand_path(self, path, context=None): raise NotImplementedError def _tempfile(self, context): """ Return temporary filename """ return self.expand_path('~/deployer-tempfile-%s-%s' % (time.time(), random.randint(0, 1000000)), context)
# Write to channel chan.send(x) # Not sure about this. Sometimes, when pasting large data # in the command line, the many concecutive read or write # commands will make Paramiko hang somehow... (This was # the case, when still using a blocking pty.stdin.read(1) # instead of a non-blocking readmany. time.sleep(0.01) finally: # Restore terminal termios.tcsetattr(pty.stdin, termios.TCSADRAIN, oldtty) # Set blocking again fdesc.setBlocking(pty.stdin) return ''.join(result) # =====[ Actions which are also available in non-sandbox mode ]==== def get_ip_address(self, interface='eth0'): """ Return internal IP address of this interface. """ # Add "cd /", to be sure that at least no error get thrown because # we're in a non existing directory right now. with self.cd('/'): with self.sandbox(False): # Some hosts give 'inet addr:', other 'enet adr:' back. #