【问题标题】:python subprocess deadlock in demonized server恶魔化服务器中的python子进程死锁
【发布时间】:2011-12-16 20:57:21
【问题描述】:

我正在尝试为 dar along these lines 设置远程备份服务器。如果可能的话,我真的很想用 python 做所有的管道,但我已经问过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

客户端也挂了,我必须通过键盘中断来终止它。

【问题讨论】:

  • 为什么需要涉及python? dar - | ncnc -l | dar 似乎要简单得多。
  • @gringo,它似乎更简单,但我不想手动调用我的所有备份。 Cron 不够聪明。用 bash 编写备份服务器会非常痛苦。那你到底在暗示什么?
  • cron 有什么问题?我看不出同时使用 nc 和 python 作为套接字的意义,为什么不使用其中一个呢?

标签: python deadlock subprocess


【解决方案1】:
  1. 使用Popen.communicate() 代替Popen.wait()

    python documentation for wait() 声明:

    警告:如果子进程向 stdout 或 stderr 管道生成足够多的输出,从而阻塞等待 OS 管道缓冲区接受更多数据,这将导致死锁。使用communicate() 来避免这种情况。

  2. Dar 及其相关的可执行文件 should get a -Q 如果它们没有以交互方式运行。

  3. 同步多个进程时,请确保首先在“最弱链接”上调用communicate()dar_slavedar_xform 之前和darcat 之前。这在问题中正确完成,但值得注意。

  4. 清理共享资源。客户端进程保持打开 dar_xform 仍在读取的套接字。尝试在初始套接字上发送/接收数据 dar 和朋友完成后而不关闭该套接字将因此导致死锁。

Here is a working example 不使用 shell=True 或 netcat。这样做的一个好处是我可以动态分配辅助端口,因此可以同时为多个备份客户端提供服务。

【讨论】:

    【解决方案2】:

    我会减少损失并重新开始。这种解决方案尝试非常复杂且笨拙。该领域有许多现成的解决方案:

    如果你想走简单的路线,Fwbackups 听起来不错,rsync+ssh 用于硬核。

    【讨论】:

    • +1 务实的方法。不幸的是,当这样的技术挑战让我感到困惑时,我无法入睡。我考虑过 bacula 和 amanda,但我认为理解它们所花费的时间几乎与自己学习它们所花费的时间一样长。 rsync 的问题也很诱人,它不像 dar 那样经常做正确的事,而且使用 dar 我可以加密我的备份并轻松地将它们粘贴到 amazon s3 上。
    猜你喜欢
    • 1970-01-01
    • 2012-03-03
    • 1970-01-01
    • 1970-01-01
    • 2012-11-24
    • 2018-03-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多