Como copiar um arquivo que ainda está sendo escrito em ssh?

18

Aqui está a situação:

  1. Estou fazendo upload de um arquivo grande do cliente A para um servidor usando o sftp.
  2. Eu também preciso baixar este arquivo do servidor para o cliente B por ssh.

O que eu gostaria de fazer é iniciar a transferência do servidor para o cliente B quando o upload ainda estiver acontecendo no cliente A.

Qual é o melhor método / ferramenta para fazer isso?

UPDATE :

As respostas até agora são interessantes - vou ler e testar todas elas. Pontos de bônus para respostas que não dependem de como o Cliente A está carregando o arquivo. (isto é, a única coisa que sabemos do cliente A é que o arquivo está sendo gravado em um nome de arquivo conhecido).

    
por Steven D 30.09.2010 / 20:29

7 respostas

10

Para um único arquivo em vez de usar SFTP, você poderia enviar o arquivo por ssh usando cat ou pv no lado de envio e usando tee no servidor do meio para enviar os dados para um arquivo lá e enviar uma cópia sobre o outro link ssh do outro lado do qual apenas grava os dados em um arquivo. O vodu exato exigido vou deixar como um exercício para o leitor, como eu não tenho tempo para jogar agora (desculpe). Esse método só funcionaria se o segundo destino fosse publicamente acessível via SSH, o que pode não ser o caso, conforme você o descreve como uma máquina cliente.

Outra abordagem, que é menos "executar e aguardar", mas pode ser mais fácil, usar rsync entre o servidor e o cliente B. Na primeira vez que você executar isso, poderá obter uma cópia parcial dos dados, mas você pode simplesmente voltar a executá-lo para obter mais dados depois (com uma execução final depois que a transferência do Servidor- > Servidor for concluída). Isso só funcionará se o servidor colocar os dados diretamente no nome de arquivo correto durante a transferência de SFTP (às vezes você verá os dados entrando em um arquivo temporário que é renomeado assim que o arquivo for completamente transferido - isso é feito para arquivo de atualização mais atômica, mas vai tornar a idéia rsync inutilizável). Você também pode usar rsync para a transferência de C1 em vez de scp (se você usar a opção --inplace para evitar o problema mencionado acima) - usar o rsync também lhe dará proteção contra a necessidade de reenviar tudo se o C1- > A conexão com o servidor apresenta problemas durante uma grande transferência (eu costumo usar rsync --inplace -a --progress <source> <dest> ao invés de scp / sftp quando o rsync está disponível, para este comportamento de "transferência de currículo").

Para resumir o acima, executando:

rsync --inplace -a --progress <source> user@server:/<destination_file_or_folder>

no client1 e depois em execução

rsync --inplace -a --progress user@server:/<destination_file_or_folder> <destination_on_cli2>

no client2 repetidamente até que a primeira transferência seja concluída (depois, execute mais uma vez para garantir que você tenha tudo). rsync é muito bom em transferir apenas o mínimo absoluto necessário para atualizar um local em vez de transferir todo o lote de cada vez. Para paranóia, talvez você queira adicionar a opção --checksum aos comandos rsync (o que levará muito mais tempo de CPU para arquivos grandes, mas não resultará em mais dados sendo transferidos a menos que seja necessário) e para acelerar o --compress Essa opção ajudará se os dados que você está transferindo ainda não estiverem em um formato compactado.

    
por 30.09.2010 / 22:37
5

Eu não posso tentar no momento, então isso pode falhar: Minha idéia é a seguinte: montar o diretório onde o arquivo está chegando no cliente B, por exemplo, com sshfs para / mnt / server no sistema de arquivos do cliente b. Então

tail -c +0 -f /mnt/server/thefileinquestion > ~/finalfile
    
por 30.09.2010 / 21:42
1

Acho que isso deve funcionar:

user@clientA:~$ cat file | ssh server "cat > dest"

e depois

user@clientB:~$ ssh server "tail +0 -f dest" > file

Adicione o comando pv se você quiser ver sua taxa de transferência.

    
por 30.09.2010 / 22:53
1

Você poderia usar um fifo para isso. Por simplicidade primeiro sem ssh envolvendo apenas dois xterms:

No xterm A:

$ mkfifo fif
$ cat test.tar.gz | tee copy.tar.gz > fif

No xterm B:

$ cat fif > dest.tar.gz
$ cmp test.tar.gz dest.tar.gz
$ echo $?
0
$ cmp test.tar.gz copy.tar.gz
$ echo $?
0

Com o ssh, deve ser algo nesse sentido - talvez você tenha que desabilitar o caractere de escape em ssh (-e none):

cliente A:

 $ ssh server mkfifo fif
 $ cat src.tar.gz | ssh "tee fif > copy.tar.gz"

cliente B:

 $ ssh server cat fif > dest.tar.gz
    
por 30.09.2010 / 23:18
1

Eu tenho uma situação que precisa de uma solução como o pôster original solicitado. Estou gravando um jogo de hóquei no meu computador em um local e gostaria de assisti-lo na minha TV em outro local. O link entre os dois locais permite que a cópia seja de aproximadamente 1.3Mb / se o vídeo de gravação é de aproximadamente 1.5Mb / s. Então, eu quero copiar o arquivo quando ele começar a gravar. Desta forma, o meu jogo de 3 horas irá copiar em cerca de 3,5 horas. Então, eu copio quando começa a gravar e posso começar a assistir 30 minutos depois de começar. Então eu posso assistir sem interrupções, quase em tempo real. Isto é, desde que eu consiga copiá-lo enquanto escreve o novo arquivo. O problema com ferramentas como rsync e scp é que elas olham para o tamanho do arquivo quando você inicia a cópia e, depois de copiar essa quantidade de dados, ele é encerrado; mesmo que o arquivo tenha crescido mais que o dobro durante essa cópia. E, se, eu estou usando apenas rsync em um loop para copiá-lo uma vez que ele pára, quando o próximo rsync termina ele reconstrói o arquivo de destino e que mata meu player de vídeo e eu tenho que reiniciar assistindo e avançar para onde eu estava no programa, quando de repente ele matou. Eu queria uma solução melhor e não consegui encontrar uma, então eu juntei isso:

dd if=2031_20160514030000.mpg |
pv --size 4653819304 |
ssh -C -c arcfour,blowfish-cbc -p 5555 myserver.com 'dd of=/media/TV/2031_20160514030000.mpg'

Então, o que isso faz?

Primeiro, eu uso o dd para copiar o arquivo à medida que ele cresce. Como o arquivo cresce mais rápido do que o dd pode enviá-lo pela rede, o dd nunca alcança o final do arquivo. Em seguida, eu canalizo para "viewer pipe (pv)" e dou uma estimativa de quão grande o arquivo será baseado em quão grandes são esses arquivos. Isso não é necessário, mas gosto de ver um medidor de progresso. Então, canalizo o fluxo para minha conexão ssh. A conexão ssh usa -C para compactação (para reduzir a largura de banda da rede e tentar acelerá-la), -c arcfour,blowfish-cbc para a criptografia mais barata (novamente para acelerar um pouco), o -p é para a porta do meu firewall Estou usando no destino, e o ssh finalmente executa o comando dd no destino para recriar o arquivo conforme ele é recebido. Fico feliz em dizer que esta solução funciona muito bem. Eu posso assistir ao jogo de hóquei enquanto o arquivo está sendo criado e copiado com apenas um pequeno atraso. Espero que isso ajude outras pessoas à procura de uma configuração semelhante. Não encontrei nada que funcionasse tão bem, apesar de ter encontrado muitas pessoas descrevendo perguntas como a que está aqui e o que eu queria, então pensei em compartilhar isso na esperança de que isso ajude alguém mais um dia.

    
por 15.05.2016 / 05:24
0

Não tenho certeza se o método tail -f funciona (embora provavelmente o faça se o arquivo for texto). A razão é que eu não sei como tail -f, e sftp transferem e confiam em meta-informação.

Se o sftp transferir primeiro a meta-informação e o tail -f contar com a meta-informação para informar que não existe mais nenhum arquivo, então o tail poderá ter o fim com EOFs ou nulls.

Se você não se importa com o caminho do upload, ou seja, o Computador 1 faz upload para o computador 2 faz upload para o computador 3, você pode tentar usar top bittorent em vez de sftp. Parece que é para isso que foi projetado.

    
por 01.10.2010 / 01:04
0

Você pode tentar ler o arquivo desde o início, mas precisa ter certeza de que pode escrevê-lo com a mesma velocidade, pelo menos.

    
por 22.07.2016 / 20:26