AsyncSSH and timeout

1,055 views
Skip to first unread message

Standard User

unread,
Oct 27, 2016, 5:53:25 AM10/27/16
to asyncssh-users
Good day,
I'm trying to run multiple SSH clients, this is an example from documentation, which works fine:
http://pastebin.com/zh4zymeQ

The problem is, it is not possible to directly set connect timeout in run_client() function. However, the docs say:
asyncio calls can be wrapped in a call to asyncio.wait_for() or asyncio.wait() which takes a timeout and provides equivalent functionality.

So I tried to modify run_client() like this:
http://pastebin.com/mH7pBuuf

But it spits out a syntax error. I also tried countless variations of it, but still no luck. Could someone more knowledgeable help me to set the timeout?

Ron Frederick

unread,
Oct 27, 2016, 9:59:12 AM10/27/16
to Standard User, asyncssh-users
Python doesn’t support mixing the new “async” and the old ‘yield from” syntax. You have to go with one or the other. Other than that, you were on the right track, though. What you want is something like:

import asyncio, asyncssh

async def run_client(host, command):
    async with asyncssh.connect(host) as conn:
        return await conn.run(command)

async def run_multiple_clients():
    # Put your lists of hosts here
    hosts = ['localhost', '1.1.1.1', 'localhost', '1.1.1.1']

    tasks = (asyncio.wait_for(run_client(host, 'ls abc'), timeout=3) 
                 for host in hosts)
    results = await asyncio.gather(*tasks, return_exceptions=True)

    for i, result in enumerate(results, 1):
        if isinstance(result, asyncio.TimeoutError):
            print('Task %d timed out.' % i)
        elif isinstance(result, Exception):
            print('Task %d failed: %s' % (i, str(result)))
        elif result.exit_status != 0:
            print('Task %d exited with status %s:' % (i, result.exit_status))
            print(result.stderr, end='')
        else:
            print('Task %d succeeded:' % i)
            print(result.stdout, end='')

        print(75*'-')

asyncio.get_event_loop().run_until_complete(run_multiple_clients())
-- 
Ron Frederick



Standard User

unread,
Oct 27, 2016, 10:15:16 AM10/27/16
to asyncssh-users, manta...@gmail.com
Working fine now, many thanks, Ron!

chuvak...@gmail.com

unread,
Sep 28, 2018, 5:49:46 AM9/28/18
to asyncssh-users
The problem with this approach is that the timeout is set not only to the connection process but to complete coroutine execution. If I run some number of time-consuming commands on  a router (like gathering technical support information) the task is timed out even though the connection was successful and nothing wrong with the execution of the command.

Is there a way to specify a timeout to the connection but not the entire coroutine function?

Ron Frederick

unread,
Sep 28, 2018, 9:47:56 PM9/28/18
to chuvak...@gmail.com, asyncssh-users
Hello,

The wait_for() call can be used on any coroutine. So, if you want it to apply only to the connect call and not to the later actions, that’s an easy change:

import asyncio, asyncssh

async def run_client(host, command):
    conn = await asyncio.wait_for(asyncssh.connect(host), timeout=3)

    async with conn:
        return await conn.run(command)

async def run_multiple_clients():
    # Put your lists of hosts here
    hosts = ['localhost', '1.1.1.1', 'localhost', '1.1.1.1']

    tasks = (run_client(host, 'ls abc') for host in hosts)
    results = await asyncio.gather(*tasks, return_exceptions=True)

    for i, result in enumerate(results, 1):
        if isinstance(result, asyncio.TimeoutError):
            print('Task %d timed out.' % i)
        elif isinstance(result, Exception):
            print('Task %d failed: %s' % (i, str(result)))
        elif result.exit_status != 0:
            print('Task %d exited with status %s:' % (i, result.exit_status))
            print(result.stderr, end='')
        else:
            print('Task %d succeeded:' % i)
            print(result.stdout, end='')

        print(75*'-')

asyncio.get_event_loop().run_until_complete(run_multiple_clients())

Aleksei Chuvakov

unread,
Oct 1, 2018, 4:53:11 AM10/1/18
to ro...@timeheart.net, asyncss...@googlegroups.com
Hi!

That works just perfect! Many thanks, Ron!

__________________________

Best Regards, Alex Chuvakov

Reply all
Reply to author
Forward
0 new messages