python获取所有与套接字打开的文件描述符

2 投票
3 回答
4997 浏览
提问于 2025-04-18 06:50

我在一个基于Unix的操作系统上使用Flask和Flask自带的网络服务器。我是这样运行它的:

APP.run(host='', port=8000, threaded=True, debug=False)

在我的代码中,我会重启一些服务,比如:

  for service in ACTIVE_SERVICES:
        command = "/etc/init.d/%s restart" % service
        # stdout and stderr are string which output of command
        stdout, stderr = Popen(command, stdout=PIPE, stderr=PIPE,shell=True).communicate()

当我停止Flask应用时,我重启的其他服务会开始监听8000端口。这是因为Flask打开的文件描述符被子进程继承了。为了防止这个问题,我想获取所有的套接字文件描述符。我该怎么做呢?

3 个回答

0

这是针对python3.8的完整解决方案

def _run_on_start(a_string):
    import socket, fcntl
    for sock in filter(lambda x: type(x) == socket.socket, gc.get_objects()):
        fd = sock.fileno()
        old_flags = fcntl.fcntl(fd, fcntl.F_GETFD)
        fcntl.fcntl(fd, fcntl.F_SETFD, old_flags | fcntl.FD_CLOEXEC)
@app.before_first_request(_run_on_start)
1

在这种情况下,调用 Popen 时应该设置 close_fds = True。

3

要解决这个问题,可以使用gc模块来获取所有创建的对象。在创建并绑定套接字之后,你可以运行这段代码来获取所有的套接字对象;

for sock in filter(lambda x: type(x) == socket._socketobject, gc.get_objects()):
    fd = sock.fileno()
    old_flags = fcntl.fcntl(fd, fcntl.F_GETFD)
    fcntl.fcntl(fd, fcntl.F_SETFD, old_flags | fcntl.FD_CLOEXEC)

这段代码可以防止套接字的文件描述符被继承。

撰写回答