python pexpect: SSHing then updating the date
Question: I have finally have my python pexpect script working except for the most
important part updating the date! I am able to SSH in the box but my second
command does not execute properly. I have been banging my head on the wall
trying to figure out why. I have checked the output of the sting and it should
be working based on whats coded. I am not a expert when it comes to python or
pexpect so I am in need of a bit of help figuring out why my time is not
updating.

**my original code** :

    
    
    list = ["089"]
    sn = 0
    
    ssh_new_conn = 'Are you sure you want to continue connecting'
    
    class ThreadClass(threading.Thread):
    def __init__(self, index):
    super(ThreadClass, self).__init__()
    self.index = index
    def run(self):
    
    sn = storelist[self.index]
    
    
    #easterndate = (currenttime + datetime.timedelta(0, 3600))
    #easterndate = easterndate
    
    est = timezone('US/Eastern')
    cst = timezone('US/Central')
    #currenttime = (datetime.now())
    currenttime = cst.localize(datetime.now())
    #easterndate = (currenttime + timedelta(0, 3600))
    #easterndate = easterndate.strftime("%a %b %d %H:%M:%S %Z %Y")
    easterndate = currenttime.astimezone(est).strftime("%a %b %d %H:%M:%S %Z %Y")
    command1 = "/usr/bin/ssh %(username)s@%(hostname)s" % locals()
    command2 = " sudo date -s\"%(easterndate)s\"" % locals()
    command3 = " sudo date -s\"%(currenttime)s\"" % locals()
    now = datetime.now()
    
    #central
    if sn == "073" or sn == "066" or sn == "016": #or sn == "022":
        p = pexpect.spawn((command1 + command3), timeout=360)
    
    
    #eastern
    else:
        print(command1 + command2)
        p = pexpect.spawn((command1 + command2), timeout=360)
    
    
    # Handles the 3 possible connection outcomes:
    # a) Ssh to the remote host for the first time, triggering 'Are you sure you want to continue connecting'
    # b) ask you for password
    # c) No password is needed at all, because you already have the key.
    i = p.expect([ssh_new_conn,'[pP]assword:',pexpect.EOF])
    print ' Initial pexpect command output: ', i
    if i == 0:
        # send 'yes'
        p.sendline('yes')
        i = p.expect(['[pP]assword:',pexpect.EOF])
        print 'sent yes. pexpect command output', i
        if i == 0:
            # send the password
            print "logging into box %(sn)s" % locals()
            p.sendline(password)
            print "login successful"
            print "Setting the time..."
    
    elif i == 1:
        # send the password
        print "logging into box %(sn)s" % locals()
        p.sendline(password)
        print "login successful"
        print "Setting the time..."
        p.close()
    
    elif i == 2:
        print "pexpect faced key or connection timeout"
        pass
    
    print p.before
    
    for i in range(len(list)):
      t = ThreadClass(i)
      t.start()
    

**New Code** :

    
    
    class ThreadClass(threading.Thread):
    def __init__(self, index):
       super(ThreadClass, self).__init__()
       self.index = index
    def run(self):
    
        try:
            sn = storelist[self.index]
            username = raw_input('username: ')
            password = raw_input('password: ')
            hostname = "[hostname]"
            est = timezone('US/Eastern')
            cst = timezone('US/Central')
            #currenttime = (datetime.now())
            currenttime = cst.localize(datetime.now())
            #easterndate = (currenttime + timedelta(0, 3600))
            #easterndate = easterndate.strftime("%a %b %d %H:%M:%S %Z %Y")
            easterndate = currenttime.astimezone(est).strftime("%a %b %d %H:%M:%S %Z %Y")
            ssh = pxssh.pxssh()
    
            print(hostname + " " + username + " " + password)
            ssh.login(hostname, username, password)
    
            if sn == "073" or sn == "066" or sn == "016": #or sn == "022":
                ssh.sendline ('date')       # run a command
                ssh.prompt()                # match the prompt
                print(s.before)           # print everything before the prompt.
                ssh.sendline ('sudo date -s\"%(currenttime)s\"' % locals())  # run a command
                ssh.expect('(?i)password.*:')  # match password prompt for sudo
                ssh.sendline(password)
                ssh.prompt()
                print(s.before)
                ssh.logout()
            else:
                ssh.sendline ('date')       # run a command
                ssh.prompt()                # match the prompt
                print(s.before)           # print everything before the prompt.
                ssh.sendline ('sudo date -s\"%(easterndate)s\"' % locals())  # run a command
                ssh.expect('(?i)password.*:')  # match password prompt for sudo
                ssh.sendline(password)
                ssh.prompt()
                print(s.before)
                ssh.logout()
    
        except pxssh.ExceptionPxssh as e:
            print(e)
    
    
    for i in range(len(storelist)):
      t = ThreadClass(i)
      t.start()
    

**New Error I am getting** :

    
    
    Traceback (most recent call last):
      File "./sshtest.py", line 8, in <module>
        s.login (hostname, username, password)
      File "/usr/lib/python2.6/dist-packages/pxssh.py", line 243, in login
        if not self.synch_original_prompt():
      File "/usr/lib/python2.6/dist-packages/pxssh.py", line 134, in synch_original_prompt
        self.read_nonblocking(size=10000,timeout=1) # GAS: Clear out the cache before getting the prompt
      File "/usr/lib/python2.6/dist-packages/pexpect.py", line 824, in read_nonblocking
        raise TIMEOUT ('Timeout exceeded in read_nonblocking().')
    pexpect.TIMEOUT: Timeout exceeded in read_nonblocking().
    

**SOLUTION TO ERROR**

I figured out the solution to the error I was getting. Due to a known bug I
had to add the following lines to usr/lib/python.2.6/dist-packages/pxssh.py:

    
    
    self.sendline()       #line 134
    time.sleep(0.5)       #line 135
    self.read_nonblocking(size=10000,timeout=1) # GAS: Clear out the cache before getting the prompt
    


Answer: You should probably handle the sudo password prompt (+ `-t` ssh option to get
a tty) and use `p.expect(EOF)` before `p.close()` to avoid killing the child
process prematurely.

Here's an example based on [pexpect
docs](http://pexpect.sourceforge.net/pxssh.html):

    
    
    import pxssh
    try:
        s = pxssh.pxssh()
        s.login (hostname, username, password)
        s.sendline ('date')       # run a command
        s.prompt()                # match the prompt
        print(s.before)           # print everything before the prompt.
        s.sendline ('sudo date')  # run a command
        s.expect('(?i)password.*:')  # match password prompt for sudo
        s.sendline(password)
        s.prompt()
        print(s.before)
        s.logout()
    except pxssh.ExceptionPxssh as e:
        print(e)
    

You could also try [`fabric`](http://fabfile.org):

    
    
    # fabfile.py
    from fabric.api import run, sudo
    
    def date():
        run('date')
        sudo('date')
    

Usage:

    
    
    $ fab -H localhost,user@host date
    

