什么是将同一文件一次压缩和tar到多个服务器的更有效方法?现在我有:
for SERVER in $SERVERS; do
tar czpf - my/directory | ssh $SERVER tar xzpf - &
done && wait
它完成了工作,并行运行循环是一种改进,但是有大约20台服务器在我的终端上进行了大量的冗余压缩。有没有办法只计算一次tarball,然后将相同的输出复制到循环中的每个ssh命令中?
答案 0 :(得分: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点明确说明。制作答案社区维基
答案 1 :(得分:2)
您可以使用tee
执行某项操作,并使用FIFO或(在更高级的shell上,例如bash
)使用>(command)
构造。
这可能有两种可能的方式:
tee >(ssh host1 tar xzpf -) >(ssh host2 tar xzpf -)
之类的命令结束。如何在Bash中这样做对我来说并不完全清楚;要么你可以使用数组,但我不确定,或者你必须使用eval
。您可以从一个名为FIFO的“初始”开始,其中tar
数据通过管道输入。然后,在每次迭代中,您mkfifo next_pipe; tee <previous_pipe >(ssh ...) > next_pipe
在每次迭代中创建一个命名FIFO。最后,为了启动while,complidated管道,您必须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脚本,它可以完成所有tee
内容,并通过管道工作,而不是通过命名的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 ...