2013-04-09 12 views
5

Mam wreszcie mój skrypt python pexpect pracy z wyjątkiem najważniejszej części aktualizacji daty! Mogę SSH w polu, ale moje drugie polecenie nie działa poprawnie. Waliłem głową w ścianę, próbując zrozumieć, dlaczego. Sprawdziłem wyjście żądła i powinno działać w oparciu o kodowane. Nie jestem ekspertem, jeśli chodzi o pythona lub pexpect, więc potrzebuję trochę pomocy w ustaleniu, dlaczego mój czas nie jest aktualizowany.python pexpect: SSHing następnie aktualizowanie daty

mój oryginalny kod:

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)[email protected]%(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() 

Nowy Kodeks:

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() 

Nowy Błąd Dostaję:

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(). 

ROZWIĄZANIE BŁĘDU

Rozwiązałem problem, który otrzymałem. Ze względu na znany błąd musiałem dodać następujące linie do usr/lib/python.2.6/dist-pakietów/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 
+0

aktualizacji swojej wersji pexpect np zainstalować do '~/.local' , uruchom: 'pip install --user pexpect'. Limit czasu powinien być obsługiwany przez sam pexpect. – jfs

+0

@Sebastian przez 'pip' masz na myśli' python-pip'? – WorkerBee

+1

yes, ['pip'] (http://www.pip-installer.org/). – jfs

Odpowiedz

1

ROZWIĄZANIE błędu

Wymyśliłem rozwiązanie problemu, który otrzymałem. Ze względu na znany błąd musiałem dodać następujące linie do 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 
+0

Jeśli chodzi o mnie, ta linia służy tylko do usuwania bufora ze wszystkiego, co wysyła ssh login. Następnie wysyłają pustą komendę, aby wywołać kolejny wynik polecenia. Dlatego uważam, że linia może być po prostu zapakowana w 'try-except-pass', aby zignorować przypadek, gdy nic nie zostało na wejściu. – ony

1

Należy prawdopodobnie obsługiwać pytanie o hasło sudo (+ -t opcji do ssh dostać tty) i użyć przed p.close(), aby uniknąć przedwczesnego zabicia procesu potomnego.

Oto przykład na podstawie pexpect docs:

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) 

Można również spróbować fabric:

# fabfile.py 
from fabric.api import run, sudo 

def date(): 
    run('date') 
    sudo('date') 

Zastosowanie:

$ fab -H localhost,[email protected] date 
+0

@Sebastian Próbowałem tego, co umieściłeś, ale ciągle dostaję problem z 's.login (nazwa hosta, nazwa użytkownika, hasło)'. Sprawdziłem podwójnie wartości, które przechodzę do tej funkcji i wszystko wygląda poprawnie. Próbowałem nawet uruchomić przykładowy kod z podanego linku i błędów kodu w tej samej linii. – WorkerBee

+0

@Sebastian proszę sprawdzić mój oryginalny wpis na mój nowo zaktualizowany kod – WorkerBee

+0

@WorkerBee: Opublikuj błąd, który otrzymujesz. – jfs

Powiązane problemy