Jak skopiować plik Na zdalny serwer w Pythonie za pomocą SCP lub SSH?
Mam plik tekstowy na mojej lokalnej maszynie, który jest generowany przez codzienny skrypt Pythona uruchamiany w cron.
Chciałbym dodać trochę kodu, aby ten plik został bezpiecznie wysłany na mój serwer przez SSH.
11 answers
Jeśli chcesz prostego podejścia, to powinno zadziałać.
Będziesz chciał ".close()" najpierw plik, aby wiedzieć, że jest spłukany na dysk z Pythona.
import os
os.system("scp FILE USER@SERVER:PATH")
#e.g. os.system("scp foo.bar [email protected]:/path/to/foo.bar")
Musisz wygenerować (na maszynie źródłowej) i zainstalować (na maszynie docelowej) klucz ssh, aby scp automatycznie został uwierzytelniony Twoim publicznym kluczem ssh (innymi słowy, aby skrypt nie pytał o hasło).
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-09-16 01:01:43
Aby to zrobić w Pythonie (tzn. nie zawijać scp przez podproces.Popen lub podobne) z biblioteką Paramiko , zrobiłbyś coś takiego:
import os
import paramiko
ssh = paramiko.SSHClient()
ssh.load_host_keys(os.path.expanduser(os.path.join("~", ".ssh", "known_hosts")))
ssh.connect(server, username=username, password=password)
sftp = ssh.open_sftp()
sftp.put(localpath, remotepath)
sftp.close()
ssh.close()
(prawdopodobnie chciałbyś poradzić sobie z nieznanymi hostami, błędami, tworzeniem wszelkich niezbędnych katalogów i tak dalej).
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-09-08 09:03:19
Prawdopodobnie użyłbyś modułu podprocesowego . Coś takiego:
import subprocess
p = subprocess.Popen(["scp", myfile, destination])
sts = os.waitpid(p.pid, 0)
Gdzie {[1] } jest prawdopodobnie formą user@remotehost:remotepath
. Dzięki
@ Charles Duffy za zwrócenie uwagi na słabość mojej oryginalnej odpowiedzi, która użyła pojedynczego argumentu łańcuchowego do określenia operacji scp shell=True
- która nie radzi sobie z białymi spacjami w ścieżkach.
Dokumentacja modułu zawiera przykłady sprawdzania błędów, które można wykonać w połączeniu z tą operacją.
Zapewnić że ustawiłeś odpowiednie poświadczenia, abyś mógł wykonać bez nadzoru, bez hasła scp pomiędzy maszynami . Istnieje już pytanie o stackoverflow.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 11:33:32
Istnieje kilka różnych sposobów podejścia do problemu:
- Zawijanie programów wiersza poleceń
- Użyj Biblioteki Pythona, która udostępnia możliwości SSH (np. - Paramiko lub Twisted Conch )
Każde podejście ma swoje dziwactwa. Musisz skonfigurować klawisze SSH, aby włączyć logowanie bez hasła, jeśli owijasz Polecenia systemowe ,takie jak" ssh"," scp "lub" rsync."Możesz osadzić hasło w skrypcie za pomocą Paramiko lub innej biblioteki, ale możesz znajdź brak dokumentacji frustrujące, zwłaszcza jeśli nie są zaznajomieni z podstawami połączenia SSH (np-wymiany kluczy, agentów, itp). Prawdopodobnie jest oczywiste, że klucze SSH są prawie zawsze lepszym pomysłem niż hasła do tego rodzaju rzeczy.
Notatka: trudno jest pokonać rsync, jeśli planujesz przesyłać pliki przez SSH, zwłaszcza jeśli alternatywą jest zwykły stary scp.
Używałem Paramiko z zamiarem zastąpienia wywołań systemowych, ale znalazłem się narysowany powrót do poleceń owiniętych ze względu na ich łatwość obsługi i natychmiastową znajomość. Możesz być inna. Dałem Conch raz-over jakiś czas temu, ale to nie przypadło mi do gustu.
Jeśli wybierzesz ścieżkę wywołania systemowego, Python oferuje szereg opcji, takich jak system operacyjny.system lub Moduły poleceń/podprocesów. Wybrałbym moduł podprocesowy, Jeśli używam wersji 2.4+.
Wystąpił ten sam problem, ale zamiast "hakowania" lub emulowania linii poleceń:
Znalazłem tę odpowiedź tutaj .
from paramiko import SSHClient
from scp import SCPClient
ssh = SSHClient()
ssh.load_system_host_keys()
ssh.connect('example.com')
with SCPClient(ssh.get_transport()) as scp:
scp.put('test.txt', 'test2.txt')
scp.get('test2.txt')
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-01-16 12:04:43
fabric
może być używany do przesyłania plików vis ssh:
#!/usr/bin/env python
from fabric.api import execute, put
from fabric.network import disconnect_all
if __name__=="__main__":
import sys
# specify hostname to connect to and the remote/local paths
srcdir, remote_dirname, hostname = sys.argv[1:]
try:
s = execute(put, srcdir, remote_dirname, host=hostname)
print(repr(s))
finally:
disconnect_all()
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-07-03 19:46:04
Wywołanie polecenia scp
przez podproces nie pozwala na otrzymywanie raportu postępu wewnątrz skryptu. pexpect
może być użyty do wyodrębnienia tej informacji:
import pipes
import re
import pexpect # $ pip install pexpect
def progress(locals):
# extract percents
print(int(re.search(br'(\d+)%$', locals['child'].after).group(1)))
command = "scp %s %s" % tuple(map(pipes.quote, [srcfile, destination]))
pexpect.run(command, events={r'\d+%': progress})
Zobacz plik kopiowania Pythona w sieci lokalnej (linux -> linux)
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:34:59
from paramiko import SSHClient
from scp import SCPClient
import os
ssh = SSHClient()
ssh.load_host_keys(os.path.expanduser(os.path.join("~", ".ssh", "known_hosts")))
ssh.connect(server, username='username', password='password')
with SCPClient(ssh.get_transport()) as scp:
scp.put('test.txt', 'test2.txt')
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-07-12 01:51:37
Bardzo proste podejście jest następujące:
import os
sshpass -p "password" scp user@host:/path/to/file ./
Żadna biblioteka Pythona nie jest wymagana (tylko os) i działa
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-01-04 15:40:07
Użyłem sshfs do zamontowania zdalnego katalogu przez ssh, a shutil do skopiowania plików:
$ mkdir ~/sshmount
$ sshfs user@remotehost:/path/to/remote/dst ~/sshmount
Następnie w Pythonie:
import shutil
shutil.copy('a.txt', '~/sshmount')
Ta metoda ma tę zaletę, że możesz przesyłać strumieniowo dane, jeśli generujesz dane, a nie buforujesz lokalnie i wysyłasz jeden duży plik.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-02-06 02:58:25
Trochę hacky, ale to powinno zadziałać:)
import os
filePath = "/foo/bar/baz.py"
serverPath = "/blah/boo/boom.py"
os.system("scp "+filePath+" [email protected]:"+serverPath)
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-09-16 00:56:31