2011-10-27 1 views
0

dar의 원격 백업 서버를 설정하려고합니다 (along these lines). 가능하다면 파이썬으로 모든 파이핑을 정말하고 싶습니다만, 그에 대해서는 separate question에 물어 보았습니다.악의적 인 서버에서 파이썬 하위 프로세스 교착 상태가 발생했습니다.

subprocess.Popen(cmd, shell=True)에서 netcat을 사용하여 dar 사이트의 예제와 같이 차등 백업을 만드는 데 성공했습니다. 유일한 두 가지 문제는 다음과 같습니다

  1. 내가 백그라운드에서 서버를 실행하면 동적으로이 방법
  2. 를 포트 번호를 할당하는 방법을 몰라 실패합니다. 왜?

업데이트 : 이것은 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() 

가 여기 서버에 무슨 일 :

여기
$ python clientserver.py serve & 
[1] 4651 
$ listening 
entering handler 
got: xform 
nc -dl 41201 | dar_slave archives/remotehost | nc -l 41202 
nc -dl 41200 | dar_xform -s 10k - archives/diffbackup 
sending port number 
waiting 

[1]+ Stopped     python clientserver.py serve 

클라이언트에서 발생하는 상황 : 여기

내 코드의

$ 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 

클라이언트는 또한 응답, 그리고 키보드 인터럽트로 그것을 죽여야 만합니다.

+0

왜 파이썬이 필요합니까? 'dar - | nc'와'nc -l | dar'는 훨씬 더 단순 해 보인다. –

+0

@gringo, it _sems_ simpler,하지만 수동으로 모든 백업을 호출하고 싶지는 않습니다. 크론은 충분히 똑똑하지 않습니다. bash에서 백업 서버를 코딩하는 것은 꽤 어려울 것입니다. 정확히 무엇을 제안하고 있습니까? –

+0

cron의 문제점은 무엇입니까? 소켓에 nc와 python을 모두 사용하지 않는 이유는 무엇입니까? –

답변

1
  1. Popen.wait() 대신 Popen.communicate()을 사용하십시오.

    python documentation for wait() 상태 :

    경고 : 자식 프로세스는 OS 파이프 버퍼 대기 차단이 많은 데이터를 수신되도록 표준 출력 또는 열려진 파이프 충분한 출력을 생성하는 경우이 교착한다. 이것을 피하려면 communicate()를 사용하십시오.

  2. Dar 및 관련 실행 파일 should get a -Q 대화 형으로 실행되지 않는 경우.

  3. 여러 프로세스를 syncronizing 때, 먼저 '약한 고리'에 communicate()를 호출해야합니다

  4. : dar_slave dar_xformcat 전에 dar. 이것은 질문에서 올바르게 수행되었지만 주목할 가치가 있습니다.

  5. 공유 리소스를 정리하십시오. 클라이언트 프로세스는 dar_xform이 여전히 읽는 소켓을 열려 있습니다. dar 이후에 초기 소켓 에 데이터를 보내려고하면 소켓을 닫지 않고 친구가 완료되므로 교착 상태가 발생합니다.

Here is a working example하는 shell=True 또는 netcat을 사용하지 않습니다. 이 기능의 장점은 보조 포트를 동적으로 할당 할 수 있으므로 여러 백업 클라이언트를 동시에 지원할 수 있다는 것입니다.

1

나는 내 손실을 줄이고 다시 시작합니다. 이 솔루션의 시도는 매우 복잡하고 불안정합니다. 많은 기성 솔루션은 지역에 있습니다 : 하드 코어 쉬운 경로, rsync를 + ssh 접속을 할 경우

Fwbackups이 좋은 소리.

+0

실용적인 접근법 +1. 불행히도 이런 기술적 인 문제가 나를 혼란스럽게 할 때 잠을 잘 수 없습니다. 나는 bacula와 amanda를 고려했다. 그러나 나는 그것이 자기 자신을 구르는 것처럼 그것이 나를 이해하는 데 거의 오랜 시간이 걸릴 것이라고 생각했다. 또한 rsync의 문제점은 dar와 거의 같은 일을 거의하지 않는다는 것입니다. dar를 사용하면 백업을 암호화하고 amazon s3에 쉽게 붙일 수 있습니다. –

관련 문제