2015-03-05 2 views
1

Что представляет собой более эффективный способ сжимать и деактивировать одни и те же файлы сразу на нескольких серверах? Сейчас у меня есть:tar -z файлы на несколько серверов одновременно?

for SERVER in $SERVERS; do 
    tar czpf - my/directory | ssh $SERVER tar xzpf - & 
done && wait 

Она получает работу, и запустить цикл параллельно является улучшением, но с ~ 20 серверов, много избыточных проносясь на моем конце. Есть ли способ вычислить tarball только один раз, а затем дублировать этот же вывод в каждой команде ssh в цикле?

+3

Почему бы не использовать временный файл для хранения tarball? – user4098326

+0

сжатие папки снова и снова для каждого сервера, очевидно, является наихудшим решением. – hek2mgl

+0

@ hek2mgl Право.Но запуск цикла в параллель, по крайней мере, лучше, чем нет. – Chris

ответ

2

Вы можете сделать что-то с tee и либо FIFO, либо (на более продвинутых оболочках, таких как bash) используйте конструкцию >(command).

Это может работать в 2 способами:

  1. Вы можете создать свою командную строку в цикле, так что в итоге вы с помощью команды tee >(ssh host1 tar xzpf -) >(ssh host2 tar xzpf -). Как это сделать в Bash не совсем ясно для меня; либо вы можете использовать массив, но я не уверен), или вам придется использовать eval.
  2. Вы можете начать с «начального» имени FIFO, в который поступают данные tar. Затем на каждой итерации вы делаете mkfifo next_pipe; tee <previous_pipe >(ssh ...) > next_pipe для создания именованного FIFO на каждой итерации. В конце вам понадобится cat последний трубопровод до /dev/null, чтобы начать то, что урезано.

    Что-то вроде

    mkfifo 0 
    tar czpf - my/directory > 0 
    i=0 
    for SERVER in $SERVERS; do 
        i=$((i+1)) 
        mkfifo $i 
        tee <$((i-1)) >(ssh $SERVER tar xzpf) >$i & 
    end 
    

, а затем ждать, пока все процессы, чтобы закончить. А потом очистите свой каталог!

Это сказало, что я лично, вероятно, напишу сценарий Python, который сделает все это, и работает через каналы, а не через имена FIFO. Это, в частности, облегчает боль, чтобы очистить в конце.

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

Но если это так, вот первый снимок программы Python, которая выполняет эту работу. Это рекламный снимок, который полностью непроверен, но показывает идею.

#/usr/bin/env python 
import sys 
import subprocess 
cmd1 = sys.argv[1] 
cmd2 = sys.argv[2] 
hosts = sys.argv[3:] 
sp1 = subprocess.Popen(cmd1, shell=True, stdout=subprocess.PIPE) 
spn = [] 
for host in hosts: 
    sp = subprocess.Popen(['ssh', host, cmd1], stdin=subprocess.PIPE) 
    spn.append(sp) 
while True: 
    block = sp1.stdout.read(4096) 
    if not block: break 
    for sp in spn: 
     sp.stdin.write(block) 
c = sp1.wait() 
for sp in spn: 
    c2 = sp.wait() 
    if not c: c = c2 
sys.exit(c) 

Может быть вызвана с

./program 'tar czpf - my/directory -' 'tar xzpf' host1 host2 host3 ... 
+1

Как бы вы использовали тройник, чтобы связать свой вывод с несколькими итерациями цикла? – Chris

3

это не будет DRY, но процесс замены и tee могут сделать это:

tar czpf - my/directory | tee \ 
    >(ssh server1 tar xzpf -) \ 
    >(ssh server2 tar xzpf -) \ 
    >(ssh server3 tar xzpf -) \ 
    >(ssh server4 tar xzpf -) \ 
    ...      \ 
    >(ssh server20 tar xzpf -) \ 
    >/dev/null 

Перенаправление на /dev/null в конце предотвращает печатая содержимое архива на терминале.

...

Я вижу это момент просто glglgl # 1 изложены в явном виде. Сделано ответ сообщество wiki

+1

Это сообщество wiki: вы должны иметь возможность редактировать его –

Смежные вопросы