Pergunta

Estou tentando ler um arquivo de um servidor usando SSH do Python. Estou usando o Paramiko para conectar. Eu posso me conectar ao servidor e executar um comando como cat filename e recupere os dados do servidor, mas alguns arquivos que estou tentando ler são de cerca de 1 GB ou mais em tamanho.

Como posso ler o arquivo na linha de servidor por linha usando o python?

Informações adicionais: o que é fazer regularmente é executar um cat filename comandando e armazene o resultado em uma variável e resolva isso. Mas como o arquivo aqui é bastante grande, estou procurando uma maneira de ler uma linha de arquivo por linha fora do servidor.

Editar: posso ler um monte de dados e dividi -los em linhas, mas o problema é que os dados recebidos no buffer nem sempre incluem as linhas completas. Por exemplo, se o buffer tiver 300 linhas, a última linha poderá ser apenas metade da linha no servidor e a próxima metade será buscada na próxima chamada para o servidor. Eu quero linhas completas

EDIT 2: Qual comando posso usar para imprimir linhas em um arquivo em um determinado intervalo. Como imprimir primeiros 100 linhas, depois os próximos 100 e assim por diante? Dessa forma, o buffer sempre conterá linhas completas.

Foi útil?

Solução

Paramiko's SFTPClient classe Permite obter um objeto semelhante a um arquivo para ler dados de um arquivo remoto de maneira pitônica.

Supondo que você tenha um aberto SSHClient:

sftp_client = ssh_client.open_sftp()
remote_file = sftp_client.open('remote_filename')
try:
    for line in remote_file:
        # process line
finally:
    remote_file.close()

Outras dicas

Aqui está uma extensão para @Matt Good's Resposta:

from contextlib     import closing
from fabric.network import connect

with closing(connect(user, host, port)) as ssh, \
     closing(ssh.open_sftp()) as sftp, \
     closing(sftp.open('remote_filename')) as file:
    for line in file:
        process(line)
#!/usr/bin/env python
import paramiko
import select
client = paramiko.SSHClient()
client.load_system_host_keys()
client.connect('yourhost.com')
transport = client.get_transport()
channel = transport.open_session()
channel.exec_command("cat /path/to/your/file")
while True:
  rl, wl, xl = select.select([channel],[],[],0.0)
  if len(rl) > 0:
      # Must be stdout
      print channel.recv(1024)

O que você quer dizer com "linha por linha" - existem muitos buffers de dados entre os hosts de rede, e nenhum deles é orientado para a linha.

Para que você possa ler um monte de dados e dividi -los em linhas no final próximo.

ssh otherhost cat somefile | python process_standard_input.py | do_process_locally

Ou você pode ter um processo lendo um monte de dados no extremo mais distante, dividi -lo e formate -o linha por linha e enviá -los para você.

scp process_standard_input.py otherhost
ssh otherhost python process_standard_input.py somefile |  do_process_locally

A única diferença com a qual eu me importaria é com que maneira reduz o volume de dados em um tubo de rede limitado. Na sua situação, pode ou não importar.

Não há nada de errado em geral em usar cat sobre um tubo SSH para mover gigabytes de dados.

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