Эффективная передача данных консоли, tar & gzip / bzip2 без создания промежуточных файлов - PullRequest
1 голос
/ 19 августа 2011

среда Linux.Итак, у нас есть программа t_show, которая при выполнении с идентификатором записывает данные о цене для этого идентификатора на консоли.Нет другого способа получить эти данные.

Мне нужно скопировать данные о цене для идентификаторов 1-10 000 между двумя серверами, используя минимальную пропускную способность, минимальное количество соединений.На конечном сервере данные будут представлять собой отдельный файл для каждого идентификатора в формате:

<id>.dat

Примером такого решения станет долгосрочное решение:

dest:

files=`seq 1 10000`
for id in `echo $files`;
do
    ./t_show $id > $id
done
tar cf - $files | nice gzip -c  > dat.tar.gz

source:

scp user@source:dat.tar.gz ./
gunzip dat.tar.gz
tar xvf dat.tar

То есть записывать каждый вывод в свой файл, сжимать и архивировать, отправлять по сети, распаковывать.создать новый файл для каждого идентификатора.Это занимает тонны пространства и плохо масштабируется.

Можно ли записать вывод консоли напрямую в (сжатый) архив tar без создания промежуточных файлов?Какие-нибудь лучшие идеи (возможно, запись сжатых данных непосредственно через сеть, пропуская tar)?

Архив tar нужно будет извлечь, как я сказал на целевом сервере, в виде отдельного файла для каждого ID.Спасибо всем, кто нашел время, чтобы помочь.

Ответы [ 6 ]

2 голосов
/ 19 августа 2011

Вы можете просто отправить данные, отформатированные каким-либо образом, и проанализировать их на получателе.

foo.sh отправителю:

#!/bin/bash
for (( id = 0; id <= 10000; id++ ))
do
    data="$(./t_show $id)"
    size=$(wc -c <<< "$data")

    echo $id $size
    cat <<< "$data"
done

На получателе:

ssh -C user@server 'foo.sh'|while read file size; do
    dd of="$file" bs=1 count="$size"
done

ssh -C сжимает данные во время передачи

1 голос
/ 19 августа 2011

Вы можете по крайней мере tar заполнить ssh-соединение:

tar -czf - inputfiles | ssh remotecomputer "tar -xzf -"

Как заполнить архив без промежуточных файлов, однако, я не знаю.

РЕДАКТИРОВАТЬ: Хорошо, я полагаю, вы могли бы сделать это, написав файл tar вручную.Заголовок указан здесь и не кажется слишком сложным, но это не совсем мое представление об удобстве ...

0 голосов
/ 22 августа 2011

Спасибо всем

Я воспользовался советом «просто отправьте данные, отформатированные каким-либо образом, и проанализируйте их на приемнике», похоже, это единодушное мнение. Пропуск tar и использование ssh -C для простоты.

Perl-скрипт. Разбивает идентификаторы на группы по 1000. Идентификаторы являются source_id в хэш-таблице. Все данные отправляются через один ssh, разделенный «HEADER», поэтому он записывает в соответствующий файл. Это лот более эффективный:

sub copy_tickserver_files {
my $self = shift;

my $cmd = 'cd tickserver/ ; ';

my $i = 1;

while ( my ($source_id, $dest_id) = each ( %{ $self->{id_translations} } ) ) {
    $cmd .= qq{ echo HEADER $source_id ; ./t_show $source_id ; };
    $i++;
    if ( $i % 1000 == 0 ) {
        $cmd = qq{ssh -C dba\@$self->{source_env}->{tickserver} " $cmd " | };
        $self->copy_tickserver_files_subset( $cmd );
        $cmd = 'cd tickserver/ ; ';
    }
}

$cmd = qq{ssh -C dba\@$self->{source_env}->{tickserver} " $cmd " | };
$self->copy_tickserver_files_subset( $cmd );

}

sub copy_tickserver_files_subset {
my $self = shift;
my $cmd = shift;

my $output = '';
open TICKS, $cmd;
while(<TICKS>) {
    if ( m{HEADER [ ] ([0-9]+) }mxs ) {
        my $id = $1;
        $output = "$self->{tmp_dir}/$id.ts";
        close TICKSOP;
        open TICKSOP, '>', $output;
        next;
    }
    next unless $output;
    print TICKSOP "$_";
}
close TICKS;
close TICKSOP;
}
0 голосов
/ 19 августа 2011

Я бы попробовал это:

(for ID in $(seq 1 10000); do echo $ID: $(/t_show $ID); done) | ssh user@destination "ImportscriptOrProgram" 

Это выведет «1: ValueOfID1» в standardout, который передается через ssh на хост назначения, где вы можете запустить свой importScript или программу, которая читаетлинии от стандартных.

HTH

0 голосов
/ 19 августа 2011

Вы можете сделать лучше без смолы:

#!/bin/bash
for id in `seq 1 1000`
do
    ./t_show $id
done | gzip

Единственная разница в том, что вы не получите границы между разными идентификаторами.

Теперь поместите это в скрипт, скажите show_me_the_ids и сделайте из клиента

shh user@source ./show_me_the_ids | gunzip

И вот они!

Или вы можете указать флаг -C для сжатия SSH-соединения и удаления всех использованных gzip / gunzip.

Если вы действительно в этом заинтересованы, вы можете попробовать ssh -C, gzip -9 и другие программы сжатия. Лично я ставлю на lzma -9.

0 голосов
/ 19 августа 2011

Не думаю, что это работает с простым bash-скриптом.Но вы можете взглянуть на модуль Archive::TAR для Perl или других языков сценариев.

Модуль Perl имеет функцию add_data для создания «файла» на лету идобавьте его в архив для потоковой передачи по сети.

Документация находится здесь:

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...