惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Cyberwarzone
Cyberwarzone
S
Secure Thoughts
L
LINUX DO - 热门话题
C
Cyber Attacks, Cyber Crime and Cyber Security
C
CERT Recently Published Vulnerability Notes
P
Privacy & Cybersecurity Law Blog
A
Arctic Wolf
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
C
Cybersecurity and Infrastructure Security Agency CISA
大猫的无限游戏
大猫的无限游戏
U
Unit 42
Recorded Future
Recorded Future
Hacker News: Ask HN
Hacker News: Ask HN
F
Full Disclosure
Spread Privacy
Spread Privacy
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
Know Your Adversary
Know Your Adversary
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
云风的 BLOG
云风的 BLOG
Stack Overflow Blog
Stack Overflow Blog
D
Darknet – Hacking Tools, Hacker News & Cyber Security
F
Fortinet All Blogs
Martin Fowler
Martin Fowler
T
Threatpost
I
InfoQ
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
Cloudbric
Cloudbric
L
LangChain Blog
N
Netflix TechBlog - Medium
The Register - Security
The Register - Security
S
Security @ Cisco Blogs
B
Blog
T
Threat Research - Cisco Blogs
T
The Blog of Author Tim Ferriss
The GitHub Blog
The GitHub Blog
D
DataBreaches.Net
Simon Willison's Weblog
Simon Willison's Weblog
P
Proofpoint News Feed
Microsoft Security Blog
Microsoft Security Blog
Blog — PlanetScale
Blog — PlanetScale
B
Blog RSS Feed
MongoDB | Blog
MongoDB | Blog
W
WeLiveSecurity
Forbes - Security
Forbes - Security
O
OpenAI News
C
Check Point Blog
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
The Last Watchdog
The Last Watchdog
H
Help Net Security
SecWiki News
SecWiki News

逸思杂陈

家用网络 vlan 单线复用 Linux 平台 intel UHD 6xx 核显 openvino 探索 UI 区域检测的 vibe coding 复盘 mitmproxy 使用 esim 使用相关 阻止 bilibili 网页自动关注 Hexo 版本更新与技术债务 配置 Linux 作为主力操作系统 在 Linux 虚拟机中使用 PyAutoGUI 做自动化 语言的力量 联想笔记本 BIOS 跳过检测强制降级 redroid “设备未获得play保护机制认证” 问题 在 iOS 上访问安卓应用 在 VSCode 中用 Rust 刷LeetCode 跨域的那些事 HomeBrew 与无 root 权限 Linux 环境包管理 给 macOS 词典增加生词本功能 容器内进程优雅退出 Python 循环变量泄露与延迟绑定 bash 语法备忘 MySQL 自定义数据库路径
关闭子进程打开的文件描述符
Jay.Run · 2022-08-30 · via 逸思杂陈

我们在测试代码时,由于需要经常重启服务,经常会发现服务端口被占用。
一般kill掉后台进程就ok了,但是如果服务有启动一些常驻的后台程序,可能也会导致端口不能释放。

在类UNIX系统中,一切被打开的文件、端口被抽象为文件描述符(file descriptor)
从python3.4开始,文件描述符默认是non-inheritable,也就是子进程不会共享文件描述符。

问题

一般为了实现多进程、多线程的webserver,服务端口fd必须设置为继承(set_inheritable),这样才能多进程监听一个端口(配合SO_REUSEPORT)
典型的是使用flask的测试服务器的场景,这里我们写一段代码模拟。

1
2
3
4
5
6
import socket, os
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.bind(('127.0.0.1', 22222))
server.set_inheritable(True)

os.system("python -c 'import time;time.sleep(1000)' ")

我们通过lsof -p {pid}可以看到这两个进程的所有文件描述符
server进程, 可以看到服务端口的fd是4

1
2
3
4
5
6
7
8
9
10
11
COMMAND   PID  FD      TYPE             DEVICE  SIZE/OFF       NODE NAME
ptpython 6214 cwd DIR 253,0 4096 872946898 /
...
ptpython 6214 0u CHR 136,13 0t0 16 /dev/pts/13
ptpython 6214 1u CHR 136,13 0t0 16 /dev/pts/13
ptpython 6214 2u CHR 136,13 0t0 16 /dev/pts/13
ptpython 6214 3r CHR 1,9 0t0 2057 /dev/urandom
ptpython 6214 4u sock 0,7 0t0 58345077 protocol: TCP
ptpython 6214 5u a_inode 0,10 0 8627 [eventpoll]
ptpython 6214 6u unix 0x0000000000000000 0t0 58368029 socket
ptpython 6214 7u unix 0x0000000000000000 0t0 58368030 socket

sleep子进程,也拥有fd=4的文件描述符

1
2
3
4
5
6
7
COMMAND   PID  FD   TYPE DEVICE  SIZE/OFF       NODE NAME
python 18022 cwd DIR 253,0 4096 872946898 /
...
python 18022 0u CHR 136,13 0t0 16 /dev/pts/13
python 18022 1u CHR 136,13 0t0 16 /dev/pts/13
python 18022 2u CHR 136,13 0t0 16 /dev/pts/13
python 18022 4u sock 0,7 0t0 58345077 protocol: TCP

如果server进程退出时,sleep进程没有退出,fd=4对应的端口就被占用了,服务也就不能正常启动了。

解决方法

手动清理

1
2
3
4
5
6
7
8
import os
import time

os.system(f'lsof -p {os.getpid()}')
os.closerange(3, 100)
time.sleep(5)
os.system(f'lsof -p {os.getpid()}')

使用close_fds

使用subprocess库而不是os来启动子程序, 通过close_fds参数关闭多余的文件描述符

1
2
import subprocess
subprocess.call("python -c 'import time;time.sleep(1000)'", shell=True, close_fds=True)

参考