Come posso copiare al meglio un numero elevato di piccoli file su scp?


59

Ho una directory che ha diversi gigabyte e diverse migliaia di piccoli file. Voglio copiarlo sulla rete con scp più di una volta. Il tempo della CPU sui computer di origine e di destinazione è economico, ma l'overhead di rete aggiunto copiando ogni file singolarmente è enorme. Lo farei tar / gzip e lo spedirei, ma la macchina sorgente è a corto di disco.

C'è un modo per me di convogliare l'output di tar -czf <output> <directory>scp? In caso contrario, esiste un'altra soluzione semplice? La mia macchina sorgente è antica (SunOS), quindi preferirei non installarla su di essa.

Risposte:


104

Puoi eseguire il pipe di tar attraverso una sessione ssh:

$ tar czf - <files> | ssh user@host "cd /wherever && tar xvzf -"

3
+1 soluzione di catrame. Se hai più larghezza di banda e meno CPU puoi rimuovere il flag di compressione (anche se gzip è piuttosto leggero).
dietbuddha,

2
E puoi rilasciare il flag di compressione e invece attivarlo in SSH ( ssh -Co Compression yesin ~/.ssh/config).
Sam Hocevar,

3
Non ho mai pensato di usare tar in questo modo. Bene, ecco perché vengo qui!
Mr. Shickadance,

2
Questo comando potrebbe essere leggermente ridotto:$ tar cz <files> | ssh user@host "cd /wherever; tar xvz"
carlito,

2
@Greg il trattino è una convenzione nel software compatibile POSIX che significa STDIN o STDOUT a seconda del contesto. Il primo trattino significa "letto da / dev / stdin" e il secondo - che è effettivamente eseguito sull'host remoto - significa "/ dev / stdin". Il pipe e lo ssh collegano questi due processi. Vedi unix.stackexchange.com/questions/16357/… per saperne di più.
Richard Metzler,

22

Il catrame con compressione bzip2 dovrebbe prelevare tanto carico dalla rete e dalla cpu.

$ tar -C /path/to/src/dir -jcf - ./ | ssh user@server 'tar -C /path/to/dest/dir -jxf -'

Non utilizzare -vperché l'output dello schermo potrebbe rallentare il processo. Ma se vuoi un output dettagliato usalo sul lato locale di tar ( -jcvf), non sulla parte remota.

Se copi ripetutamente sullo stesso percorso di destinazione, come l'aggiornamento di una copia di backup, la scelta migliore è rsync con compressione.

$ rsync -az -e ssh /path/to/src/dir/ user@server:/path/to/dest/dir/

Si noti che entrambi i percorsi src e dest terminano con un /. Ancora una volta, non usando -ve -Pcontrassegni apposta, aggiungili se hai bisogno di un output dettagliato.


16

usa rsync, usa SSH.

Uso:

rsync -aPz /source/path destination.server:remote/path

Gli switch rsync si preoccupano della compressione e delle informazioni sull'I-Node. -Pmostra l'avanzamento di ogni file.

È possibile utilizzare scp -C, che consente la compressione, ma se possibile, utilizzare rsync.


Sfortunatamente, rsync non è disponibile sul computer di origine, né sshd.
nmichaels,

1
sshd non è necessario per quelle operazioni sul computer client.
polemon

3

Puoi eseguire tarsu entrambe le estremità usando ssh. scpfa parte della sshfamiglia del bene, quindi probabilmente ce l'hai da entrambe le parti.

 8:03AM 12 % tar cf - some_directory | ssh dest_host "tar xf -"

Potrebbe esserci un modo per far funzionare gzip o bzip2 nella pipeline per ridurre anche il traffico di rete.


3

La risposta di @pdo è buona, ma si può aumentare la velocità con un buffer e una buona compressione e aggiungere una barra di avanzamento.

Spesso la rete è il collo di bottiglia e la velocità varia nel tempo. Pertanto, aiuta a bufferizzare i dati prima di inviarli sulla rete. Questo può essere fatto con pv.

Inoltre, di solito si può aumentare la velocità con un algoritmo di compressione adeguato. Gzip (come usato sopra) è un algoritmo di compressione veloce, ma in generale zstandard ( zstd) (e per rapporti di compressione elevati LZMA / LZMA2 ( xz) comprimerà meglio e sarà più veloce allo stesso tempo. I nuovi xz e zstd hanno già il supporto multi core integrato Per usare gzip con più core è possibile utilizzare pigz.

Ecco un esempio per inviare dati con una barra di avanzamento, buffering e compressione zstandard su una rete:

tar cf - . | pv -perabs $(du -sk . | cut -f 1)K | zstd -14 --long=31 -T0 | pv -qCB 512M | ssh user@host "cd /wherever && pv -qCB 512M | zstd -cd -T0 --long=31 | tar xf -"

Il primo pvè mostrare l'avanzamento ( p ), il tempo stimato ( e ), la velocità di trasferimento ( r ), la velocità media ( a ), i byte totali trasferiti ( b ). La dimensione totale è stimato con due aggiunto l'opzione di dimensione ( s ). L'avanzamento viene misurato prima della compressione e del buffering, quindi non è molto preciso, ma comunque utile.

zstdviene utilizzato con l'impostazione di compressione 14 . Questo numero può essere ridotto o aumentato a seconda della velocità della rete e della CPU, quindi zstd è un po 'più veloce della velocità della rete. Con quattro core su una CPU Haswell 3.2 GHz 14 offre una velocità di circa 120 MB / s. Nell'esempio, viene utilizzata la modalità lunga 31 (utilizza una finestra da 2 GB, richiede molta RAM, ma è molto buona, ad esempio per comprimere i dump del database). Le opzioni T0 impostano la quantità di thread sul numero di core. Bisogna essere consapevoli del fatto che insieme alla modalità lunga queste impostazioni utilizzano molta memoria.

Un problema con zstd è che la maggior parte dei sistemi operativi non viene fornita con la versione> = 1.3.4. Questa versione è necessaria per un corretto supporto multi core e lungo. Se non disponibile, può essere compilato e installato da https://github.com/facebook/zstd con solo make -j4 && sudo make install. Invece di zstd, si può anche usare xz o pigz. xz è lento ma si comprime molto bene (buono su connessioni lente), pigz / gzip è veloce ma non si comprime molto bene. pvviene quindi riutilizzato, ma per il buffering ( qper quiet, Cper la modalità no splice [sempre necessaria per il buffering] e Bper impostare la dimensione del buffer).

Nell'esempio viene utilizzato anche un buffer sul lato ricevitore. Questo spesso non è necessario (poiché la velocità di decompressione e di scrittura sul disco rigido è per lo più superiore alla velocità della rete), ma di solito non danneggia neanche.


2

Se hai gzip su entrambe le estremità: sourcehost$ cd sourcedir && tar cf - . | gzip -c - | ssh user@destinationhost "cd destinationdir && gzip -c -d | tar xf -"

Se non hai gzip sul computer di origine, assicurati di aver decompresso sulla destinazione: sourcehost$ cd sourcedir && tar cf - . | compress | ssh user@destinationhost "cd destdir && uncompress | tar xf -"

Questo sarebbe più veloce di prima comprimerlo, quindi inviarlo, quindi decomprimerlo e non richiede spazio su disco aggiuntivo su entrambi i lati. Ho sorseggiato la bandiera di compressione (z) su tar, perché probabilmente non ce l'hai sul lato antico.


2

Oppure puoi farlo al contrario, se necessario. Cioè tirare il tarball sulla rete piuttosto che spingerlo come è stato suggerito. Questo non risolve la parte ripetitiva della tua domanda e rsync è la cosa migliore per farlo, ma probabilmente ci sono tar switch per aiutarti.

Quindi sulla macchina locale:

ssh remote 'tar zcf - /etc/resolv.conf' | tar zxf -

Meglio trovarsi prima nella directory giusta o devi usare l'opzione -C sul comando untaring alla fine.

Basta menzionarlo nel caso fosse necessario. È per me come nella mia situazione il mio server locale è dietro nat, quindi prenderei qualche rete inutilmente per poterlo fare nel modo precedentemente menzionato.

HTH


1

Oppure monta il filesystem remoto tramite sshfs

sshfs user@remotehost:/path/on/remote /path/on/local

1

Sebbene non sia il più elegante, soprattutto perché non sta copiando un singolo file zip o tar e doppiamente, in quanto non aiuta a ridurre la necessità della rete, la mia unica scelta è stata quella di utilizzare scp -r:

-r

      Copia ricorsivamente intere directory. Si noti che scp segue i collegamenti simbolici riscontrati nella traversata dell'albero.
Fonte: scp (1)

Stavo riscontrando problemi con l'esaurimento dello spazio su disco con un file tar zippato da 30 GB. Pensavo che gunzip potesse farlo in linea, cioè rimuovendo l'originale mentre veniva decompresso (e potrei aver perso un risultato di Google) ma non sono riuscito a trovare nulla.

Infine, poiché ero stanco di provare più volte in attesa che un nuovo file TAR o ZIP finisse di eseguire il taring o zippare, ho finalmente fatto:

  1. Dal server / PC / laptop originale, vai alla directory in cui si trovano le tue cartelle con numerosi file / cartelle.
  2. scp -r source_folder_name yourname@yourservername:destination_folder_name

Quindi prendi un po 'di birra, caffè o popcorn e aspetta. La cosa buona è che scp tenterà nuovamente se la connessione di rete "si blocca". Spero solo che non scenda completamente.


OK, questo richiede chiaramente meno tempo rispetto alla digitazione di mille scpcomandi. Ma la domanda si pone sul "sovraccarico della rete". La tua soluzione utilizza la rete in misura minore rispetto alla copia di ciascun file singolarmente? La tua soluzione è superiore in qualche modo ai sette che sono già stati pubblicati?
G-Man dice "Ripristina Monica" il

Snap, mio ​​male - mi è sfuggita totalmente la parte aerea della rete - grazie per averlo sottolineato @ G-Man. Ho aggiornato la risposta, sento ancora che potrebbe essere utile se qualcuno inciampa su un problema simile come ho avuto e quando mi sono imbattuto in questa domanda.
JGlass
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.