2011-10-27 11 views
0

darのリモートバックアップサーバーを設定しようとしています。along these linesです。可能であれば、私はパイソンを使ってすべてのパイピングをしたいと思っていますが、そのことについてseparate questionに尋ねました。悪意のあるサーバーのpythonサブプロセスデッドロック

subprocess.Popen(cmd, shell=True)でnetcatを使用して、darサイトの例のように差分バックアップを作成することに成功しました。 2つのだけ問題があります:

  1. 私は、バックグラウンドでサーバーを実行すると、それが失敗した動的このよう
  2. ポート番号を割り当てる方法を知りません。どうして?

更新:これは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 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 

クライアントはハングアップ、およびI:

$ 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 

はここで、クライアント上で何が起こるかですキーボード割り込みでそれを殺さなければなりません。

+0

なぜPythonを関与させる必要がありますか? 'dar - | nc'と 'nc -l | darははるかに簡単です。 –

+0

@gringo、それはより簡単ですが、すべてのバックアップを手動で呼び出す必要はありません。 Cronは十分にスマートではありません。 bashでバックアップサーバをコーディングするのはかなり苦しいでしょう。だから、あなたは何を提案していますか? –

+0

cronの何が問題なのですか?私はソケットのためにncとpythonの両方を使用するという点は見ていません。実践的なアプローチのためには+1 –

答えて

1
  1. 利用Popen.communicate()の代わりPopen.wait()

    python documentation for wait()状態:

    警告:子プロセスがブロックは、より多くのデータを受け入れるようにOSパイプバッファを待っているような標準出力や標準エラー出力パイプに十分な出力を生成した場合これがデッドロックします。それを避けるには、()を使用してください。

  2. Darとそれに関連する実行可能ファイルshould get a -Qが対話的に実行されていない場合。 catdar_xformdar_slavedar

  3. 複数のプロセスをsyncronizingすると、最初の「最も弱いリンク」にcommunicate()を呼び出すようにしてください。これは質問で正しく行われましたが、それは注目に値することです。

  4. 共有リソースをクリーンアップします。クライアントプロセスは、dar_xformがまだ読み取っているソケットを開いたままにしています。 darの後に最初のソケットでデータを送信しようとすると、そのソケットを閉じることなく友人が終了し、デッドロックが発生します。

Here is a working exampleshell=Trueまたはnetcatを使用しない。これの利点は、セカンダリポートを動的に割り当てることができるため、複数のバックアップクライアントを同時に処理できることです。

1

私は自分の損失を減らし、やり直すだろう。この解決策の試みは非常に複雑でクラージーです。地域の多くの既製のソリューションがあります:あなたは、ハードコアやすいルート、rsyncの+のsshを取りたい場合は

Fwbackupsがいいですね。

+0

+1。私は残念なことに、このような技術的な挑戦が私を困惑させているとき、眠れない。私はバキュラとアマンダを考えましたが、自分のものを転がすのと同じくらい長く私を理解するのに時間がかかりそうです。魅力的だったrsyncの問題は、darと同じくらい頻繁に正しいことをやっていないし、darを使って私のバックアップを暗号化してアマゾンs3に簡単に貼り付けることができるということです。 –

関連する問題