Question

I am using ssh to log into a camera, scp a tarball over to it and extract files from the tarbal and then run the script. I am having problems with Pexpect, though. Pexpect times out when the tarball is being copied over. It seem's not to wait until it is done. And then it start's doing the same thing with the untar command, The code I have is below:

    ssh_newkey = 'Are you sure you want to continue connecting'          
    copy = pexpect.spawn('ssh service@10.10.10.10')
    i=copy.expect([ssh_newkey,'password:',pexpect.EOF])
    if i==0:
        copy.sendline('yes')
        i=copy.expect([ssh_newkey,'password:',pexpect.EOF])
    if i==1:        
        copy.sendline("service")
        print 'Password Accepted'
        copy.expect('service@user:')
        copy.sendline('su - root')
        i=copy.expect('Password:')
        copy.sendline('root')
        i=copy.expect('#')
        copy.sendline('cd /tmp')
        i=copy.expect("#")
        copy.sendline('scp user@20.20.20.20:/home/user/tarfile.tar.gz .')
        i=copy.expect([ssh_newkey,'password:',pexpect.EOF])
        if i==0:
            copy.sendline('yes')
            i=copy.expect([ssh_newkey,'password:',pexpect.EOF])
        else:
            pass
        copy.sendline('userpwd')
        i=copy.expect('#')
        copy.sendline('tar -zxvf tarfile.tar.gz bin/installer.sh')
        i=copy.expect("#")
        copy.sendline("setsid /tmp/bin/installer.sh /tmp/tarfile.tar.gz > /dev/null 2>&1 &")            
    elif i==2:
        print "I either got key or connection timeout"
    else:
        pass

Can anyone help find a solution for this?

Thanks

Was it helpful?

Solution

I'm not sure if this is correct, but I'd try setting the timeout to None:

copy = pexpect.spawn('ssh service@10.10.10.10', timeout=None)

According to the source code, pexpect seems to not check the timeout when it's set to None.

Anyway, the reason I'm answering this even though I'm not sure whether it solves your problem is that I wanted to recommend using paramiko instead. I had good experience using it for communication over SSH in the past.

OTHER TIPS

Is there a reason your using pexpect or even paramiko?

if you setup a public/private key then you can just use as a single example:

command = "scp user@20.20.20.20:/home/user/tarfile.tar.gz"
split_command = shlex.split(command)
subprocess.call(split_command)

Then as per the suggestion above use paramiko to send commands.

you can use the keyfile for that as well:

The following class method will give you a persistent session (although it is untested):

#!/usr/bin/python
# -*- coding: utf-8 -*-

from __future__ import print_function
import os
from paramiko import SSHClient, AutoAddPolicy, AuthenticationException, RSAKey
from subprocess import call

class CommsSuite(object):

    def __init__(self):
        self.ssh_client = SSHClient()

        #--------------------------------------

        def _session_send(command):
            """
             Use to send commands over ssh in a 'interactive_session'
             Verifies session is present
             If the interactive_session is not present then print the failed command.

             This may be updated to raise an error, 
             which would probably make more sense.

             @param command:  the command to send across as a string

             ::TODO:: consider raise exception here as failed 
                      session will most likely be fatal.

            """

            if self.session.send_ready():
                self.session.send("%s\n" % command)
            else:
                print("Session cannot send %s" % command)

        #--------------------------------------

        def _get_persistent_session(_timeout = 5):
            """
            connect to the host and establish an interactive session.

            @param _timeout: sets the timout to prevent blocking.

            """
            privatekeyfile = os.path.expanduser('~/.ssh/id_rsa')#this must point to your keyfile

            private_key = RSAKey.from_private_key_file(privatekeyfile)
            self.ssh_client.set_missing_host_key_policy(AutoAddPolicy())

            self.ssh_client.connect(hostname,
                                    username = <username>,
                                    pkey = private_key,
                                    timeout = _timeout)

            self.transport = self.ssh_client.get_transport()
            self.session = self.transport.open_session()
            self.session.exec_command("bash -s")

        _get_persistent_session()


        # build a comma seperated list of commands here as a string "[a,b,c]"
        commands = ["tar -zxvf tarfile.tar.gz bin/installer.sh", "setsid /tmp/bin/installer.sh /tmp/tarfile.tar.gz > /dev/null 2>&1"]
        # then run the list of commands
        if len(commands) > 0:
            for command in commands:
                _session_send(command)

        self.session.close()#close the session when done


CommsSuite()
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top