我正在尝试为dar设置远程备份服务器along these lines。如果可能的话,我真的很想用python完成所有的管道工作,但是我问过a separate question。在
在subprocess.Popen(cmd, shell=True)
中使用netcat,我成功地进行了差异备份,如dar站点上的示例所示。唯一的两个问题是:
更新:这似乎与netcat无关;即使没有netcat也会挂起。在
我的代码是:
from socket import socket, AF_INET, SOCK_STREAM
import os, sys
import SocketServer
import subprocess
class DarHandler(SocketServer.BaseRequestHandler):
def handle(self):
print('entering handler')
data = self.request.recv(1024).strip()
print('got: ' + data)
if data == 'xform':
cmd1 = 'nc -dl 41201 | dar_slave archives/remotehost | nc -l 41202'
print(cmd1)
cmd2 = 'nc -dl 41200 | dar_xform -s 10k - archives/diffbackup'
print(cmd2)
proc1 = subprocess.Popen(cmd1, shell=True)
proc2 = subprocess.Popen(cmd2, shell=True)
print('sending port number')
self.request.send('41200')
print('waiting')
result = str(proc1.wait())
print('nc-dar_slave-nc returned ' + result)
result = str(proc2.wait())
print('nc-dar_xform returned ' + result)
else:
result = 'bad request'
self.request.send(result)
print('send result, exiting handler')
myaddress = ('localhost', 18010)
def server():
server = SocketServer.TCPServer(myaddress, DarHandler)
print('listening')
server.serve_forever()
def client():
sock = socket(AF_INET, SOCK_STREAM)
print('connecting')
sock.connect(('localhost', 18010))
print('connected, sending request')
sock.send('xform')
print('waiting for response')
port = sock.recv(1024)
print('got: ' + port)
try:
os.unlink('toslave')
except:
pass
os.mkfifo('toslave')
cmd1 = 'nc -w3 localhost 41201 < toslave'
cmd2 = 'nc -w3 localhost 41202 | dar -B config/test.dcf -A - -o toslave -c - | nc -w3 localhost ' + port
print(cmd2)
proc1 = subprocess.Popen(cmd1, shell=True)
proc2 = subprocess.Popen(cmd2, shell=True)
print('waiting')
result2 = proc2.wait()
result1 = proc1.wait()
print('nc<fifo returned: ' + str(result1))
print('nc-dar-nc returned: ' + str(result2))
result = sock.recv(1024)
print('received: ' + result)
sock.close()
print('socket closed, exiting')
if __name__ == "__main__":
if sys.argv[1].startswith('serv'):
server()
else:
client()
以下是服务器上发生的情况:
^{pr2}$客户机上的情况如下:
$ python clientserver.py client
connecting
connected, sending request
waiting for response
got: 41200
nc -w3 localhost 41202 | dar -B config/test.dcf -A - -o toslave -c - | nc -w3 localhost 41200
waiting
FATAL error, aborting operation
Corrupted data read on pipe
nc<fifo returned: 1
nc-dar-nc returned: 1
客户端也挂起了,我不得不用键盘中断来终止它。在
使用
Popen.communicate()
代替Popen.wait()
。在python documentation for wait()声明:
警告:如果子进程生成足够的输出到stdout或stderr管道,从而阻塞等待操作系统管道缓冲区接受更多数据,则会导致死锁。使用communicate()来避免这种情况。
Dar及其相关的可执行文件should get a -Q,如果它们不是以交互方式运行的。
当同步多个进程时,请确保首先调用“最弱链接”上的
communicate()
:dar_slave
在dar_xform
之前,dar
在cat
之前。这个问题做得对,但值得注意。清理共享资源。客户机进程正在打开daruxform仍在读取的套接字。尝试在dar和friends完成后在初始套接字上发送/接收数据而不关闭该套接字将导致死锁。
不使用
shell=True
或netcat的Here is a working example。这样做的一个优点是可以动态分配辅助端口,因此可以设想同时为多个备份客户机提供服务。在我会减少损失重新开始。这个解决方案的尝试是非常复杂和混乱的。该领域有许多现成的解决方案:
如果你想走一条简单的路线,用rsync+ssh作为硬盘,Fwbackups听起来不错。在
相关问题 更多 >
编程相关推荐