You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python3 HTTP Server作为Systemd服务运行时出现Broken Pipe错误

解决Python http.server作为Systemd服务时的BrokenPipeError问题

问题原因

BrokenPipeError本质是客户端(比如视频播放器)在服务器还未发送完数据时主动断开了连接,Python内置的http.server没有默认处理这类异常,因此会抛出错误。对于HLS视频服务来说,这种情况十分常见——用户暂停播放、切换视频或关闭页面,都会导致连接提前中断。

解决方案

1. 在请求处理中捕获BrokenPipeError

修改你的CORSRequestHandler类,重写相关方法捕获异常,避免单个请求的错误影响整个服务:

#!/usr/bin/env python3
from http.server import HTTPServer, SimpleHTTPRequestHandler
import sys
import shutil


class CORSRequestHandler(SimpleHTTPRequestHandler):
    
    def end_headers(self):
        self.send_header('Access-Control-Allow-Origin', '*')
        self.send_header('Access-Control-Allow-Methods', '*')
        self.send_header('Access-Control-Allow-Headers', '*')
        self.send_header('Cache-Control', 'no-store, no-cache, must-revalidate')
        return super(CORSRequestHandler, self).end_headers()

    def do_OPTIONS(self):
        self.send_response(200)
        self.end_headers()

    def do_GET(self):
        try:
            super().do_GET()
        except BrokenPipeError:
            self.log_message("客户端 {} 提前断开连接".format(self.client_address[0]))
        except Exception as e:
            self.log_error("处理请求时出错: %s", str(e))

    def copyfile(self, source, outputfile):
        try:
            shutil.copyfileobj(source, outputfile)
        except BrokenPipeError:
            pass


host = sys.argv[1] if len(sys.argv) > 2 else '0.0.0.0'
port = int(sys.argv[len(sys.argv)-1]) if len(sys.argv) > 1 else 9999

print("Listening on {}:{}".format(host, port))
httpd = HTTPServer((host, port), CORSRequestHandler)
httpd.serve_forever()

2. 优化Systemd服务配置

调整配置提升安全性和稳定性,避免用root用户运行服务:

[Unit]
Description=HLS视频HTTP服务
After=network.target

[Service]
# 使用普通用户运行,降低权限风险
User=media
WorkingDirectory=/home/media
# 明确指定监听地址和端口,避免参数歧义
ExecStart=/usr/bin/python3 /home/media/httpserver.py 0.0.0.0 9999
# 仅在服务异常退出时重启,正常退出不触发重启
Restart=on-failure
# 设置重启间隔,防止频繁重启
RestartSec=5
# 将日志输出到systemd journal,方便排查问题
StandardOutput=journal+console
StandardError=journal+console

[Install]
WantedBy=multi-user.target

3. 生产环境替代方案:使用更稳定的HTTP服务器

Python内置http.server仅适合开发测试,生产环境建议用更可靠的服务器,比如aiohttp:

#!/usr/bin/env python3
from aiohttp import web
import sys

async def handle_static(request):
    path = request.match_info.get('path', '')
    return web.FileResponse(f'/home/media/{path}' if path else '/home/media/index.html')

async def options_handler(request):
    return web.Response(headers={
        'Access-Control-Allow-Origin': '*',
        'Access-Control-Allow-Methods': '*',
        'Access-Control-Allow-Headers': '*'
    })

def main():
    app = web.Application()
    app.add_routes([web.get('/{path:.*}', handle_static)])
    app.add_routes([web.options('/{path:.*}', options_handler)])
    
    @app.middleware
    async def cors_middleware(request, handler):
        response = await handler(request)
        response.headers['Access-Control-Allow-Origin'] = '*'
        response.headers['Cache-Control'] = 'no-store, no-cache, must-revalidate'
        return response
    
    host = sys.argv[1] if len(sys.argv) > 2 else '0.0.0.0'
    port = int(sys.argv[-1]) if len(sys.argv) > 1 else 9999
    web.run_app(app, host=host, port=port)

if __name__ == '__main__':
    main()

安装依赖:pip install aiohttp,然后更新Systemd的ExecStart为/usr/bin/python3 /home/media/aiohttp_server.py即可。

验证修改

  1. 重载Systemd配置并重启服务:
sudo systemctl daemon-reload
sudo systemctl restart your-service-name
  1. 实时查看日志确认问题是否解决:
journalctl -u your-service-name -f

内容的提问来源于stack exchange,提问作者PETERSON MUNENE

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.23 07:24:53