Как бороться с убитым Python BaseHTTPServer, но порт все еще занят?

Я использую Python BaseHTTPServer, он может обрабатывать методы do_GET,do_POST, в методе do_POST, я выполняю оболочку linux, используя os.system, когда я убиваю скрипт python, но порт прослушивания все еще занят, поэтому я не могу запустить скрипт снова, netstat -antp|grep 80 показывает, что bash/tail занят портом 80

import sys
import os
import traceback
import time
import logging.handlers
import logging
from threading import *
from datetime import datetime
import urllib2
reload(sys)
sys.setdefaultencoding('utf-8')

class WebRequestHandler(BaseHTTPServer.BaseHTTPRequestHandler):
    server_version = 'python httpserver'
    sys_version = 'b'
    backup_dir = None
    def do_HEAD(s):
        s.send_response(200)
        s.send_header("Content-type", "text/html")
        s.end_headers()
    def do_GET(self):
        if self.path == '/foo':
            self.send_response(200)               
            os.system('nohup tail -f a.log &')

        else:
            self.send_error(404)
if __name__ == "__main__":
    try:
        server = BaseHTTPServer.HTTPServer(('',80), WebRequestHandler)    
        server.serve_forever()
    except KeyboardInterrupt:
        server.socket.close()

1 ответ

Решение

Дескрипторы файлов по умолчанию наследуются дочерними процессами, поэтому прослушивание сокета на порту 80 наследуется командой, которую вы запустили с помощью вызова system().

Чтобы избежать этого, вы должны установить флаг FD_CLOEXEC на слушающем сокете. Это может быть сделано путем добавления (и использования) определенного класса HTTPServer.

class WebServer(BaseHTTPServer.HTTPServer):
    def __init__(self, *args, **kwargs):
        BaseHTTPServer.HTTPServer.__init__(self, *args, **kwargs)
        # Set FD_CLOEXEC flag
        flags = fcntl.fcntl(self.socket.fileno(), fcntl.F_GETFD)
        flags |= fcntl.FD_CLOEXEC
        fcntl.fcntl(self.socket.fileno(), fcntl.F_SETFD, flags)

Связанные с:

Другие вопросы по тегам