Why is exit() or exec needed after telnetlib read_all() - python

A lot of resources, including the example in the official documentation at telnetlib suggest that at the end before you do a read_all(), you need to write exit after the command as:
tn.write("ls\n")
tn.write("exit\n")
Can someone please help me understand why is this needed ?
If I try doing it without the exit, the telnet connection hangs (or at least looks like it is hung) as the output of the command executed does not show on the terminal.
Also, another way of making it work, as I found in some resources was to use 'exec' to fire up the command and then you don't need the exit thing anymore.
Please help me understand this as well.

read_all() reads all the output until EOF. In other words, it waits until remote server closes connection and returns you all the data it has sent. If you have not previously notified the server with an "exit" command that you have no more commands for it, it will wait for them. And a deadlock occurs: you are holding open connection because you are waiting for server to tell you that it has sent everything it intended to say, and server waits for new orders from you and is ready to add more data to it's output.

Related

Python Subprocess readline hangs() after reading all input

I am trying to readlines from the tcp server that I ran in the same script. I am able to send one command and reads its output but at the end (after reading all outputs) it looks like that program hangs in readline, I have tried almost all the solutions here and here but still it hangs.
Most of these solutions propose to check if output of readline is none or not but in my case program never returns from last read and just hangs in there.
tcp server is not in my control, or say I just have to test server script therefore I can not modify it. Also, is it possible to send commands to runing server using python without using subprocess? any better alternative?
def subprocess_cmd(command):
process=subprocess.Popen(command,stdin=subprocess.PIPE,stderr=subprocess.STDOUT,stdout=subprocess.PIPE, shell=True)
for cmd in ['python3 -u tcp_server.py 123 port1']:
subprocess_cmd(cmd)
process.stdin.write('command like print_list')
process.stdin.flush()
while True:
line=process.stdout.readline()
if line == '':
break
readline hangs because your TCP connection is still open and readline expects more data to come in. You must close the connection from server side to notify readline that there is nothing more to read. Usually it is done by closing socket on client side notifying the server that there will not be any more requests to it. When server finishes processing all your commands it closes socket too. And this is the signal for you that you have received all the data that server sent to you.
Or, alternatively, if you don't want to close the connection, you must invent delimiters which will mark end of response. So the client will stop calling readline when such delimiter is read.

Python telnetlib ending session

If I am using Python telnetlib, is there a way to close the telnet session if that device does not support nothing to terminate telnet session, so no ctrl+something or quit or anything like that.
I need this so that I could use read.all
Network sockets let you shutdown write and/or read channels to let the other side know that you have finished that part of the conversation. For a telnet server, shutting down the write channel is an exit. It should finish sending whatever is in the send pipeline and then close the connection completely. That close is an EOF and read_all should return. So, assuming you've already got a connection called tn
tn.get_socket().shutdown(socket.SHUT_WR)
data = tn.read_all()
tn.close()

can't get commands on remote host after fixed amount of send commands

I have a program with 2 threads. Every thread sends different commands to remote host and redirect output to file. Threads use different remote hosts. I've created a connection with pxssh and trying to send commands to remote hosts with 'sendline':
s = pxssh.pxssh()
try:
s.login (ip, user, pswd)
except:
logging.error("login: error")
return
logging.debug("login: success")
s.sendline("ls / >> tmpfile.log")
s.prompt()
I can send fixed number of commands (about 500 commands on every host) and after that 'sendline' stops working. Connection is ok, but I can't get commands on remote hosts. It looks like some resources run out... what can it be?
Reposting as an answer, since it solved the issue:
Are you reading in between each write? If the host is producing output and you're not reading it, sooner or later a buffer will fill up and it will block until there's room to write some more. Make sure that before each write, you read any data that's available in the terminal, even if you don't want to do anything with it.
If you really don't care about the output at all, you could create a thread that constantly reads in a loop, so that your main thread can skip reading altogether. If your code needs to do anything with any part of the output, though, don't do this.

Why does this twisted server interact wrongly with a process?

The server is at https://github.com/EmeraldHaze/Socketd/blob/master/Serv.py ; the process is at https://github.com/EmeraldHaze/QFTSOM/blob/master/main.py
A client too test this is at http://www.kongregate.com/games/EmeraldHaze/this-is-why-we-have-maps ; port forwarding and whatnot is set up correctly.
The point is that someone connecting too the server sends something like {"IP":"123.456.789.012"}, then a process is made for him, then the IO streams of the process and the user are connected. The reality is that the process outputs something, the user sees it, the user gives some input, the server gets it (and logs it), then nothing happens. Any ideas why? The buffers should be flushed.
Uh, I solved this. It was becouse sys.stdin.readline() stops blocking when it gets a \n, but either twisted or the client strip them off, meaning it will block indefinitly despite getting input.

twisted handle_quit() the way to disconnect?

so I'm implementing a log server with twisted (python-loggingserver) and I added simple authentication to the server. If the authentication fails, I wanna close the connection to the client. The class in the log server code already has a function called handle_quit(). Is that the right way to close the connection? Here's a code snippet:
if password != log_password:
self._logger.warning("Authentication failed. Connection closed.")
self.handle_quit()
If the handle_quit message you're referring to is this one, then that should work fine. The only thing the method does is self.transport.loseConnection(), which closes the connection. You could also just do self.transport.loseConnection() yourself, which will accomplish the same thing (since it is, of course, the same thing). I would select between these two options by thinking about whether failed authentication should just close the connection or if it should always be treated the same way a quit command is treated. In the current code this makes no difference, but you might imagine the quit command having extra processing at some future point (cleaning up some resources or something).

Categories

Resources