Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

while size > 0 nevers exits #70

Closed
SomeProgrammerGuy opened this issue Mar 15, 2019 · 5 comments
Closed

while size > 0 nevers exits #70

SomeProgrammerGuy opened this issue Mar 15, 2019 · 5 comments

Comments

@SomeProgrammerGuy
Copy link

SomeProgrammerGuy commented Mar 15, 2019

Im trying to follow the online examples and if I run the following the loop never exits.

If I remove the while loop all is good. If the read() call is waiting then whats the point of the while.

Similar code works fine same server with paramiko using "while not channel.recv_ready() :" etc.

Is this a bug or by design

Code:

import sys
import socket

from ssh2.session import Session

SSH_SERVER_IP ="IPADDRESS"

def main():

    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    sock.connect((SSH_SERVER_IP, 22))

    session = Session()
    session.handshake(sock)
    session.userauth_password("USERNAME", "PASSWORD")

    channel = session.open_session()

    channel.shell();

    # All I want to do here is display returned banner.

    size, data = channel.read()
    while size > 0:
        print(data.decode())         # <<<< Displays banner fine.
        size, data = channel.read()  # <<<< Sticks here on debug and never exits

    channel.close()

    print("Exit status: %s" % channel.get_exit_status())

if __name__ == '__main__':
    sys.exit(main())

Bug reports

Expected behaviour: Exit the while loop

Actual behaviour: Didn't Exit

@qzlisb
Copy link

qzlisb commented Mar 16, 2019

Because the first read is finished and the second read is always blocked, it's better to check if it's done again, such as checking the prompt.

@qzlisb
Copy link

qzlisb commented Mar 16, 2019

Or you can set session to non-block, but can't be sure to receive all data

@pkittenis
Copy link
Member

Hi there,

Thanks for the interest. This is not an issue with the library.

channel.read on an interactive shell (channel.shell) will block indefinitely if there is no output to be read - this is SSH protocol behaviour. The shell is waiting for input. As it is interactive and does not send EOF, there is no indicator no more output will be sent.

The channel should be closed before trying to read again if no more commands will be sent to it. Alternatively use channel.execute and channel.wait_eof to determine that no more output will be sent.

If all the output needed has already been received, why is the client code trying to read more data without doing anything on the channel? There will obviously be no output from it unless something is executed first.

There is functionality in the libssh2 API to check if output is available - see session.block_directions.

See example for use of close, eof and wait_eof.

@SomeProgrammerGuy
Copy link
Author

SomeProgrammerGuy commented Mar 18, 2019

Cheers. That clears things up. I did it this way following an online example that is obviously wrong.

I'm also trying to build in some simple error checking for an automated unsupervised script.

i.e.

  1. Get returned data
  2. Is any data returned and is it complete<< as I had it this will never be reached.
  3. Check returned data is correct before sending commands. (if not exit etc)

Do again for next lot of data etc

Otherwise no returned data (as some issue occurred or its wrong) the script is stuck in an infinite loop (unless there's a timeout)

An infinite loop is never a good thing without some sort of exit plan.

The example you have posted is also doing this:

# Print output
size, data = channel.read()
while size > 0:
    print(data)
    size, data = channel.read()

@pkittenis
Copy link
Member

The example is using wait_eof and close before reading as described above. read returns 0 after these when all output has been consumed.

The example as present in the repo is correct for what it does, as above.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants