Pergunta

Eu criei um programa que itera sobre um monte de arquivos e invoca para alguns deles:

scp <file> user@host:<remotefile>

No entanto, no meu caso, pode haver milhares de arquivos pequenos que precisam transferidos e scp está abrindo uma nova conexão ssh para cada um deles, que tem bastante alguma sobrecarga.

Eu queria saber se não há solução onde guardo um processo em execução que mantém a conexão e posso enviá-lo "pedidos" para copiar arquivos individuais.

Idealmente, eu estou procurando uma combinação de algum programa emissor e receptor, de modo que eu possa começar um processo único (1) no início:

ssh user@host receiverprogram

E para cada arquivo, invoco um comando (2):

senderprogram <file> <remotefile>

e canalizar a saída de (2) para a entrada de (1), e isso faria com que o arquivo a ser transferido. No final, eu só posso enviar processo (1) algum sinal para terminar.

programas

De preferência o emissor eo receptor são programas de código aberto C para Unix. Eles podem se comunicar usando uma tomada em vez de um tubo, ou qualquer outra solução criativa.

No entanto, é um importante constrangimento que cada arquivo é transferido no momento eu iterar sobre ele: não é aceitável para coletar uma lista de arquivos e, em seguida, invocar uma instância do scp a transferência de todos os arquivos de uma só vez no final. Além disso, tenho acesso shell única simples para o recebimento de acolhimento.

Update: eu encontrei uma solução para o problema da conexão sobrecarga usando os recursos de multiplexação de ssh, ver a minha própria resposta abaixo. No entanto, eu estou começando uma recompensa porque estou curioso para saber se existe um programa emissor / receptor como eu descrevo aqui. Parece que deve existir algo que pode ser usado, por exemplo, xmodem / ymodem / zmodem?

Foi útil?

Solução

Desta forma, iria funcionar, e para outras coisas, esta abordagem geral é mais ou menos certo.

(
iterate over file list
  for each matching file
   echo filename
) | cpio -H newc -o | ssh remotehost cd location \&\& | cpio -H newc -imud

Outras dicas

Eu encontrei uma solução de outro ângulo. Desde versão 3.9 , suportes OpenSSH sessão de multiplexação : uma única conexão pode levar várias sessões de login ou de transferência de arquivos. Isso evita o custo set-up por conexão.

Para o caso da questão, posso primeiro abrir uma conexão com configura um mestre de controle (-M) com um soquete (-S) em um local específico. Eu não preciso de uma sessão (-N).

ssh user@host -M -S /tmp/%r@%h:%p -N

Em seguida, posso invocar scp para cada arquivo e instruí-lo a usar o mesmo socket:

scp -o 'ControlPath /tmp/%r@%h:%p' <file> user@host:<remotefile>

Este comando começa a copiar quase instantaneamente!

Você também pode usar o soquete de controle para conexões SSH normais, que irá, em seguida, abra imediatamente:

ssh user@host -S /tmp/%r@%h:%p

Se a tomada de controle não está mais disponível (por exemplo, porque você matou o mestre), este cai de volta para uma conexão normal. Mais informações estão disponíveis em este artigo .

Pode funcionar para uso sftp em vez de scp, e para colocá-lo em modo de lote. Faça o arquivo de comando de lote de um tubo ou de soquete e alimentos para animais de domínio comandos UNIX a ele como você quer que eles executados.

Segurança sobre isso pode ser um pouco complicado no cliente final.

Você já tentou sshfs ? Você pode:

sshfs remote_user@remote_host:/remote_dir /mnt/local_dir

Onde

  • /remote_dir foi o diretório que deseja enviar arquivos para o sistema que você está SSHing em
  • /mnt/local_dir foi o local de montagem de localização

Com esta configuração você pode apenas cp um arquivo no local_dir e seria enviada através sftp para remote_host em sua remote_dir

Note que não há uma única conexão, por isso há pouco na maneira de sobrecarga

Você pode precisar usar o -o ServerAliveInterval=15 bandeira de manter uma conexão indefinida

Você precisa ter fuse instalado localmente e um servidor SSH apoio (e configurado para) sftp

Pode ser que você está procurando para isso: ZSSH

zssh (Zmodem SSH) é um programa de transferência de arquivos interativamente a uma máquina remota enquanto estiver usando o shell seguro (ssh). Destina-se a ser uma alternativa conveniente para scp, permitindo a transferência de arquivos sem ter que abrir outra sessão e re-autenticar a si mesmo.

Use rsync por SSH se você pode recolher todos os arquivos para enviar em um único diretório (ou hierarquia de diretórios).

Se você não tem todos os arquivos em um único lugar, por favor, dar mais algumas informações sobre o que você quer alcançar e por que você não pode embalar todos os arquivos em um arquivo e enviá que mais. Por que é tão vital que cada arquivo é enviado imediatamente? Seria OK se o arquivo foi enviado com um pequeno atraso (como quando 4K no valor de dados acumulou)?

É um problema pouco agradável. Eu não estou ciente de uma solução pré-embalados, mas você poderia fazer muito com shell scripts simples. Eu tentaria isso no receptor:

#!/bin/ksh
# this is receiverprogram

while true
do
  typeset -i length
  read filename  # read filename sent by sender below
  read size      # read size of file sent
  read -N $size contents  # read all the bytes of the file
  print -n "$contents" > "$filename"
done

No lado do remetente eu iria criar um pipe nomeado e ler a partir do tubo, por exemplo.,

mkfifo $HOME/my-connection
ssh remotehost receiver-script < $HOME/my-connection

Depois de enviar um arquivo que eu tentaria este script

#!/bin/ksh
# this is senderprogram

FIFO=$HOME/my-connection

localname="$1"
remotename="$2"
print "$remotename" > $FIFO
size=$(stat -c %s "$localname")
print "$size" > $FIFO
cat "$localname" > $FIFO

Se o tamanho do arquivo é grande que você provavelmente não querer lê-lo de uma só vez, assim que algo na ordem de

BUFSIZ=8192

rm -f "$filename"
while ((size >= BUFSIZ)); do
  read -N $BUFSIZE buffer
  print -n "$buffer" >> "$filename"
  size=$((size - BUFSIZ))
done
read -N $size buffer
print -n "$contents" >> "$filename"

Eventualmente você deseja estender o script para que possa passar através de comandos chmod e chgrp. Desde que você confia o código de envio, é provavelmente mais fácil de estruturar a coisa para que o receptor simplesmente chama eval shell em cada linha, em seguida, enviar o material como

print filename='"'"$remotename"'"' > $FIFO
print "read_and_copy_bytes " '$filename' "$size" > $FIFO

e, em seguida, definir uma read_and_copy_bytes função local. Obtendo o direito de citar é um urso, mas caso contrário, deve ser simples.

É claro, nada disso foi testado! Mas eu espero que lhe dê algumas idéias úteis.

Parece um trabalho para tar? Tubo de sua saída para ssh, e, por outro tubo de lado a parte de trás saída ssh ao alcatrão.

Eu acho que o desktop GNOME usa uma única conexão SSH ao acessar uma parte através de SFTP (SSH). Eu estou supondo que este é o que está acontecendo, porque eu vejo um único processo SSH quando eu acessar um compartilhamento remoto desta forma. Então, se isso é verdade, você deve ser capaz de usar o mesmo programa para esta finalidade.

A nova versão do GNOME usado GVFS através GIO , a fim de executar todas tipo de I / O por meio de acessos diferentes. O pacote Ubuntu gvfs-bin fornece vários utilitários de linha de comando que permitem manipular os backends a partir da linha de comando.

Primeiro você vai precisar para montar sua pasta SSH:

gvfs de montagem sftp: // usuário @ host /

E, em seguida, você pode usar as gvfs-copiar para copiar seus arquivos. Eu acho que todas as transferências de arquivos será realizada através de um único processo de SSH. Você ainda pode usar ps para ver qual processo está sendo usado.

Se você se sentir mais aventureiro, pode mesmo escrever o seu próprio programa em C ou em alguma outra linguagem de alto nível que fornece uma API para GIO.

Uma opção é Conch é uma implementação do cliente SSH e servidor escrito em Python utilizando o < a href = "http://twistedmatrix.com/trac/" rel = "nofollow noreferrer"> Twsited quadro. Você poderia usá-lo para escrever uma ferramenta que aceita solicitações via algum outro protocolo (HTTP ou de domínio Unix soquetes, FTP, SSH ou qualquer outro) e transferências de arquivos gatilhos mais de uma conexão SSH longa duração. Na verdade, eu tenho vários programas em produção que utilizam esta técnica para evitar várias configurações de conexão SSH.

Houve um muito semelhante questão aqui um par de semanas atrás. A propôs a abertura de um túnel, quando ssh'ing para a máquina remota e usar o túnel para transferências scp.

curlftpfs pode ser uma solução válida para você.

Parece que ele só monta pasta de um computador externo ao computador via SFTP. Uma vez feito isso, você deve ser capaz de usar seus comandos regulares cp e tudo será feito de forma segura.

Infelizmente eu não era capaz de testá-lo eu mesmo, mas deixe-me saber se ele funciona para você!

Editar 1: eu tenho sido capaz de baixar e testá-lo. Como eu temia que exige que o cliente tenha um servidor FTP. No entanto , eu descobri um outro programa que tem exatamente o mesmo conceito que o que você está procurando. sshfs permite que você se conectar ao seu computador cliente sem necessidade de qualquer servidor especial. Depois de ter montado uma das suas pastas, você pode usar seus comandos normais cp para mover arquivos que você precisa mais. Assim que estiver pronto, ele deve então ser uma questão sorriso de umount /path/to/mounted/folder. Deixe-me saber como isso funciona!

rsync -avlzp user@remotemachine:/path/to/files /path/to/this/folder

Isto irá usar o SSH para transferir arquivos, de uma forma não-lenta

Mantenha-o simples, escrever um script pouco que faz algo assim.

  1. tar os arquivos
  2. enviar o arquivo tar
  3. untar do outro lado

Algo parecido com isto:

  1. tar -cvzf test.tgz arquivos ....
  2. scp test.tgz user@other.site.com:.
  3. ssh user@other.site.com tar -xzvf test.tgz

/ Johan

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top