it-swarm-eu.dev

Jak kopírovat soubor na vzdálený server v Pythonu pomocí SCP nebo SSH?

Mám textový soubor na svém lokálním počítači, který je generován každodenním skriptem Python spuštěným v cronu. 

Chtěl bych přidat trochu kódu, aby byl tento soubor bezpečně odeslán na můj server přes SSH.

85
Alok

Pokud chcete jednoduchý přístup, mělo by to fungovat.

Nejdříve budete chtít ".close ()" soubor, abyste věděli, že je vypuštěn na disk z Pythonu.

import os
os.system("scp FILE [email protected]:PATH")
#e.g. os.system("scp foo.bar [email protected]:/path/to/foo.bar")

Musíte vytvořit (na zdrojovém počítači) a nainstalovat (na cílovém počítači) ssh klíč předem, aby se scp automaticky autentizoval s vaším veřejným ssh klíčem (jinými slovy, aby váš skript nežádal o heslo) . 

příklad ssh-keygen

39
pdq

Chcete-li to provést v Pythonu (tj. Ne zalomením scp přes subprocess.Popen nebo podobně) s Paramiko library, udělali byste něco takového:

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

(Pravděpodobně byste se chtěli zabývat neznámými hostiteli, chybami, vytvářením nezbytných adresářů atd.).

129
Tony Meyer

K problému lze přistupovat několika způsoby:

  1. Zabalte programy příkazového řádku
  2. použijte knihovnu Python, která poskytuje možnosti SSH (např. - Paramiko nebo Twisted Conch )

Každý přístup má své vlastní vtipy. Budete muset nastavit SSH klíče, aby umožnily přihlášení bez hesla, pokud balíte systémové příkazy jako "ssh", "scp" nebo "rsync". Heslo můžete vložit do skriptu pomocí Paramiko nebo nějaké jiné knihovny, ale můžete zjistit, že nedostatek dokumentace je frustrující, zvláště pokud nejste obeznámeni se základy spojení SSH (např. Výměna klíčů, agenti atd.). Pravděpodobně je samozřejmé, že SSH klíče jsou téměř vždy lepší nápad než hesla pro tento druh věcí.

POZNÁMKA: je těžké porazit rsync, pokud máte v plánu přenášet soubory přes SSH, zejména pokud je alternativou prostý starý scp.

Použil jsem Paramiko s očima k nahrazení systémových hovorů, ale ocitl jsem se zpět na zabalené příkazy kvůli jejich snadnému použití a okamžité znalosti. Můžete být jiný. Před nějakým časem jsem Conchovi jednou před časem předal, ale to se mi nelíbilo.

Pokud se rozhodnete pro cestu systémového volání, Python nabízí řadu možností, jako je os.system nebo moduly příkazů/podprocesů. Použil bych modul podprocesu, pokud používáte verzi 2.4+.

10
Michael

Dosáhli stejného problému, ale místo "hackování" nebo emulace příkazového řádku:

Nalezli jste tuto odpověď zde .

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')
6
Maviles

fabric lze použít k nahrání souborů 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()
3
jfs

Můžete použít vassal balíček, který je přesně určen pro to.

Vše, co potřebujete, je nainstalovat vassal a dělat

from vassal.terminal import Terminal
Shell = Terminal(["scp [email protected]:/home/foo.txt foo_local.txt"])
Shell.run()

Uloží vám také autentizační pověření a nemusíte je znovu a znovu psát.

1
Shawn
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')
0
michael

velmi jednoduchý přístup je následující: 

import os
os.system('sshpass -p "password" scp [email protected]:/path/to/file ./')

žádná knihovna python není vyžadována (pouze os) a funguje

0

Zkuste to, pokud nechcete používat certifikáty SSL:

import subprocess

try:
    # Set scp and ssh data.
    connUser = 'john'
    connHost = 'my.Host.com'
    connPath = '/home/john/'
    connPrivateKey = '/home/user/myKey.pem'

    # Use scp to send file from local to Host.
    scp = subprocess.Popen(['scp', '-i', connPrivateKey, 'myFile.txt', '{}@{}:{}'.format(connUser, connHost, connPath)])

except CalledProcessError:
    print('ERROR: Connection to Host failed!')
0
JavDomGom

Použil jsem sshfs pro připojení vzdáleného adresáře přes ssh a shutil pro kopírování souborů:

$ mkdir ~/sshmount
$ sshfs [email protected]:/path/to/remote/dst ~/sshmount

Pak v pythonu:

import shutil
shutil.copy('a.txt', '~/sshmount')

Tato metoda má tu výhodu, že můžete generovat data, pokud generujete data namísto lokálního ukládání do mezipaměti a odesílání jednoho velkého souboru.

0
Jonno_FTW

Volání příkazu scp přes podproces neumožňuje přijímat zprávu o průběhu uvnitř skriptu. pexpect lze použít k extrahování informací:

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

Viz kopírovací soubor python v lokální síti (linux -> linux)

0
jfs