2013-03-01 16 views
9

Próbuję uruchomić polecenie scp (bezpieczne kopiowanie) przy użyciu subprocess.Popen. Login wymaga, aby wysłać hasło:Wysyłanie hasła przez SSH lub SCP z podprocesu.Popen

from subprocess import Popen, PIPE 

proc = Popen(['scp', "[email protected]:/foo/bar/somefile.txt", "."], stdin = PIPE) 
proc.stdin.write(b'mypassword') 
proc.stdin.flush() 

Ten natychmiast zwraca błąd:

[email protected]'s password: 
Permission denied, please try again. 

jestem pewną hasło jest prawidłowe. Łatwo to zweryfikować, ręcznie wywołując powłokę scp. Dlaczego to nie działa?

Uwaga, istnieje wiele podobnych pytań do tego, prosząc o subprocess.Popen i wysyłanie hasła do zautomatyzowanego SSH lub logowania FTP:

How can I set a users password in linux from a python script?
Use subprocess to send a password

odpowiedź (s) na te pytania don” t działa i/lub nie stosuje się, ponieważ używam Pythona 3.

+0

Nie znam tego kodu, ale próbujesz użyć parametru -p? również wymiana kluczy jako metoda walidacji? – diego2k

+0

Z -pi oznacza "-p mypassword uż[email protected]: /foo/bar/somefile.txt" nie wiem czy możesz to zrobić – diego2k

+1

@ diego2k Z tego co mi wiadomo, scp nie akceptuje przełącznika wprowadź hasło za pomocą wiersza poleceń (jego strona podręcznika nie zawiera niczego w tym rodzaju). Ogólnie nie jest dobrą praktyką dostarczanie hasła w wierszu poleceń, ponieważ zostanie to zapisane w .bash_history – entropy

Odpowiedz

6

Druga odpowiedź, którą łączysz, sugeruje użycie Pexpect (zwykle jest to właściwy sposób interakcji z programami wiersza poleceń oczekującymi danych wejściowych). Jest tam fork tego, który działa dla python3, z którego możesz korzystać.

+1

uwaga: regular [pexpect] (https://pypi.python.org/pypi/pexpect) obsługuje teraz Python 3. – jfs

9

Oto funkcja ssh z hasłem przy użyciu pexpect:

def ssh(host, cmd, user, password, timeout=30, bg_run=False):                         
    """SSH'es to a host using the supplied credentials and executes a command.                         
    Throws an exception if the command doesn't return 0.                              
    bgrun: run command in the background"""                                  

    fname = tempfile.mktemp()                                     
    fout = open(fname, 'w')                                      

    options = '-q -oStrictHostKeyChecking=no -oUserKnownHostsFile=/dev/null -oPubkeyAuthentication=no'                   
    if bg_run:                                       
     options += ' -f'                                      
    ssh_cmd = 'ssh %[email protected]%s %s "%s"' % (user, host, options, cmd)                             
    child = pexpect.spawn(ssh_cmd, timeout=timeout)                                
    child.expect(['password: '])                                                                        
    child.sendline(password)                                     
    child.logfile = fout                                      
    child.expect(pexpect.EOF)                                     
    child.close()                                        
    fout.close()                                        

    fin = open(fname, 'r')                                      
    stdout = fin.read()                                       
    fin.close()                                         

    if 0 != child.exitstatus:                                     
     raise Exception(stdout)                                     

    return stdout 

Coś podobnego powinno być możliwe przy użyciu scp.

+0

Dzięki. To mi pomogło. Rozglądam się, ale czy możesz mi powiedzieć, co oznacza ta linia? '-q -oStrictHostKeyChecking = no -oUserKnownHostsFile =/dev/null -oPubkeyAuthentication = no' – alfonso

+1

@alfonso to są opcje, które można przekazać do ssh w linii poleceń lub do '.ssh/config' bez' - o'. Pierwszy mówi ssh, aby nie narzekał, jeśli gospodarz zmienił swój klucz, ponieważ mógł zostać ponownie zainstalowany od ostatniego użycia. Drugi mówi o używaniu/dev/null zamiast .ssh/known_hosts, więc znowu przestanie narzekać, jeśli zostanie ponownie zainstalowany z ostrzeżeniem o zduplikowanym wpisie. Ostatnie dni, aby nie używać kluczy, które wymuszają wprowadzanie hasła. – sjbx

4

Pexpect posiada bibliotekę dokładnie to: pxssh

http://pexpect.readthedocs.org/en/stable/api/pxssh.html

import pxssh 
import getpass 
try: 
    s = pxssh.pxssh() 
    hostname = raw_input('hostname: ') 
    username = raw_input('username: ') 
    password = getpass.getpass('password: ') 
    s.login(hostname, username, password) 
    s.sendline('uptime') # run a command 
    s.prompt()    # match the prompt 
    print(s.before)  # print everything before the prompt. 
    s.logout() 
except pxssh.ExceptionPxssh as e: 
    print("pxssh failed on login.") 
    print(e) 
1

Chyba niektóre aplikacje interakcji z użytkownikiem za pomocą stdin i niektóre aplikacje interakcję za pomocą terminala. W takim przypadku, gdy piszemy hasło używając PIPE, piszemy do stdin. Ale aplikacja SCP odczytuje hasło z terminala. Ponieważ podprocesor nie może wchodzić w interakcje z użytkownikiem za pomocą terminala, ale może wchodzić w interakcje z wykorzystaniem standardowego wejścia, nie możemy używać modułu podprocesowego i musimy użyć pexpect do skopiowania pliku przy użyciu scp.

Zapraszam do korekt.