Como posso copiar da melhor maneira um grande número de arquivos pequenos pelo scp?

59

Eu tenho um diretório que possui vários gigabytes e vários milhares de arquivos pequenos. Quero copiá-lo pela rede com scp mais de uma vez. O tempo de CPU nas máquinas de origem e destino é barato, mas a sobrecarga de rede adicionada pela cópia de cada arquivo individualmente é enorme. Gostaria de tar / gzip-lo e enviá-lo, mas a máquina de origem está com pouco disco.

Existe uma maneira de canalizar a saída tar -czf <output> <directory>para o scp? Caso contrário, existe outra solução fácil? Minha máquina de origem é antiga (SunOS), então prefiro não instalar coisas nela.

nmichaels
fonte

Respostas:

104

Você pode canalizar o tar em uma sessão ssh:

$ tar czf - <files> | ssh user@host "cd /wherever && tar xvzf -"
pdo
fonte
3
Solução de tubo de alcatrão +1. Se você tiver mais largura de banda e menos CPU, poderá remover o sinalizador de compactação (embora o gzip seja bastante leve).
dietbuddha
2
E você pode soltar o sinalizador de compactação e ativá-lo no SSH ( ssh -Cou Compression yesno ~/.ssh/config).
Sam Hocevar
3
Nunca pensei em usar alcatrão assim. Bem, é por isso que eu venho aqui!
Sr. Shickadance
2
Este comando pode ser feito um pouco mais curto:$ tar cz <files> | ssh user@host "cd /wherever; tar xvz"
carlito
2
@Greg the dash é uma convenção no software compatível com POSIX, que significa STDIN ou STDOUT, dependendo do contexto. O primeiro traço significa 'ler de / dev / stdin' e o segundo - que é realmente executado no host remoto - significa '/ dev / stdin'. O pipe e o ssh conectam esses dois processos. Consulte unix.stackexchange.com/questions/16357/… para saber mais.
Richard Metzler
22

O alcatrão com compactação bzip2 deve sobrecarregar a rede e a CPU.

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

Não usar -vporque a saída da tela pode retardar o processo. Mas se você quiser uma saída detalhada, use-a no lado local de tar ( -jcvf), não na parte remota.

Se você copiar repetidamente no mesmo caminho de destino, como atualizar uma cópia de backup, sua melhor opção é rsync com compactação.

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

Observe que os caminhos src e dest terminam com um /. Novamente, não usando -ve -Psinalizadores de propósito, adicione-os se precisar de uma saída detalhada.

forcefsck
fonte
16

use rsync, ele usa SSH.

Uso:

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

Os comutadores rsync se preocupam com informações de compactação e I-Node. -Pexibe o progresso de cada arquivo.

Você pode usar scp -C, o que permite a compactação, mas se possível, use rsync.

polemon
fonte
Infelizmente, o rsync não está disponível na máquina de origem e nem o sshd.
Nmichaels
1
O sshd não é necessário para essas operações na máquina cliente.
Polemon
3

Você pode executar tarnas duas extremidades usando ssh. scpfaz parte da sshfamília da bondade, então você provavelmente a tem nos dois lados.

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

Pode haver uma maneira de trabalhar com gzip ou bzip2 no pipeline para diminuir também o tráfego da rede.

Bruce Ediger
fonte
3

A resposta do @ pdo é boa, mas é possível aumentar a velocidade com um buffer e uma boa compactação e adicionar uma barra de progresso.

Muitas vezes, a rede é o gargalo e a velocidade varia com o tempo. Portanto, ajuda a armazenar em buffer os dados antes de enviá-los pela rede. Isso pode ser feito com pv.

Além disso, geralmente é possível aumentar a velocidade com um algoritmo de compactação adequado. O gzip (como usado acima) é um algoritmo de compactação rápido, mas em geral o zstandard ( zstd) (e para altas taxas de compactação, o LZMA / LZMA2 ( xz) compacta melhor e fica mais rápido ao mesmo tempo. Os novos xz e zstd têm suporte para vários núcleos Para usar o gzip com múltiplos núcleos, o pigz pode ser usado.

Aqui está um exemplo para enviar dados com uma barra de progresso, buffer e compactação zstandard em uma rede:

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 -"

O primeiro pvé mostrar o progresso ( p ), tempo estimado ( e ), taxa de transferência ( r ), taxa média ( a ), total de bytes transferidos ( b ). O tamanho total é estimada com due adicionou-se a opção (tamanho s ). O progresso é medido antes da compactação e do buffer, portanto, não é muito preciso, mas ainda é útil.

zstdé usado com a configuração de compactação 14 . Esse número pode ser reduzido ou aumentado dependendo da velocidade da rede e da CPU, portanto o zstd é um pouco mais rápido que a velocidade da rede. Com quatro núcleos em uma CPU Haswell de 3,2 GHz 14, a velocidade é de cerca de 120 MB / s. No exemplo, o modo longo 31 (usa uma janela de 2 GB, precisa de muita RAM, mas é muito bom, por exemplo, para compactar despejos de banco de dados). As opções T0 configuram a quantidade de encadeamentos para o número de núcleos. Deve-se estar ciente de que, juntamente com o modo longo, essas configurações usam muita memória.

Um problema com o zstd é que a maioria dos sistemas operacionais não é fornecida com a versão> = 1.3.4. Esta versão é necessária para o suporte multi core e longo adequado. Se não estiver disponível, ele pode ser compilado e instalado em https://github.com/facebook/zstd com apenas make -j4 && sudo make install. Em vez de zstd, também é possível usar xz ou pigz. xz é lento, mas compacta muito bem (bom em conexões lentas), pigz / gzip é rápido, mas compacta não tão bem. pvé usado novamente, mas para o buffer ( qpara silencioso, Cpara o modo sem emenda [sempre necessário para o buffer] e Bpara definir o tamanho do buffer).

No exemplo, um buffer também é usado no lado do receptor. Isso geralmente é desnecessário (porque a velocidade de descompactação e gravação no disco rígido é mais alta que a velocidade da rede), mas geralmente não causa danos.

Fabian Heller
fonte
2

Se você possui o gzip nas duas extremidades: sourcehost$ cd sourcedir && tar cf - . | gzip -c - | ssh user@destinationhost "cd destinationdir && gzip -c -d | tar xf -"

Se você não possui o gzip na máquina de origem, descompacte no destino: sourcehost$ cd sourcedir && tar cf - . | compress | ssh user@destinationhost "cd destdir && uncompress | tar xf -"

Isso seria mais rápido do que primeiro fechar o zíper, depois enviar e descompactar, e não requer espaço em disco extra em nenhum dos lados. Eu sikpped a bandeira de compressão (z) no alcatrão, porque você provavelmente não tem no lado antigo.

MattBianco
fonte
2

Ou você pode fazer o contrário, se precisar. Isso é puxar o tarball pela rede em vez de empurrá-lo como foi sugerido. Isso não resolve a parte repetida da sua pergunta e o rsync é melhor para isso, mas provavelmente há opções de tar para ajudar.

Então, na máquina local:

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

É melhor estar no diretório certo primeiro ou você deve usar a opção -C no comando desarmar no final.

Apenas mencionando isso, caso isso seja necessário. É para mim, pois, na minha situação, meu servidor local está atrás de nat, portanto, levaria alguma rede futurizando a ponto de ser capaz de fazê-lo da maneira mencionada anteriormente.

HTH

DaveQB
fonte
1

Ou monte o sistema de arquivos remoto via sshfs

sshfs user@remotehost:/path/on/remote /path/on/local
ivanivan
fonte
1

Embora não seja o mais elegante, especialmente porque não está copiando um único arquivo zip ou tar e duplamente, para não ajudar a reduzir a carga de rede, minha única opção era usar scp -r:

-r

      Copie recursivamente diretórios inteiros. Observe que scp segue os links simbólicos encontrados no percurso da árvore.
Fonte: scp (1)

Eu estava tendo problemas com a falta de espaço em disco com um arquivo tar compactado de 30 GB. Eu pensei que o gunzip poderia fazê-lo em linha, ou seja, removendo o original, pois estava sendo descompactado (e posso ter perdido um resultado do Google), mas não consegui encontrar nada.

Por fim, como estava cansado de tentar várias vezes esperar que um novo arquivo TAR ou ZIP terminasse de tar ou zipar, finalmente fiz:

  1. No servidor / PC / laptop original, navegue até o diretório em que está sua pasta com vários arquivos / pastas.
  2. scp -r source_folder_name yourname@yourservername:destination_folder_name

Depois, pegue um pouco de cerveja, café ou pipoca e espere. O bom é que o scp tentará novamente se a conexão de rede "travar". Só espero que não desça completamente.

JGlass
fonte
OK, isso claramente leva menos tempo do que digitar mil scpcomandos. Mas a pergunta é sobre "sobrecarga de rede". Sua solução usa a rede menos do que copiar cada arquivo individualmente? Sua solução é superior às sete que já foram publicadas?
G-Man diz 'Reinstate Monica'
Snap, meu mal - eu perdi totalmente a parte aérea da rede - obrigado por apontar isso para o @ G-Man. Atualizei a resposta, ainda acho que pode ser útil se alguém se deparar com um problema semelhante ao meu e quando me deparei com essa pergunta.
JGlass