Python踩坑之旅其一杀不死的Shell子进程
1.1 踩坑案例
踩坑的程序是个常驻的Agent类管理进程, 包括但不限于如下类型的任务在执行:
- a. 多线程的网络通信包处理
- 和控制Master节点交互
- 有固定Listen端口
- b. 定期作业任务, 通过subprocess.Pipe执行shell命令
- c. etc
发现坑的过程很有意思:
- a.重启Agent发现Port被占用了
- => 立刻想到可能进程没被杀死, 是不是停止脚本出问题
- => 排除发现不是, Agent进程确实死亡了
- => 通过
netstat -tanop|grep port_number发现端口确实有人占用
- => 调试环境, 直接杀掉占用进程了之, 错失首次发现问题的机会
- => 立刻想到可能进程没被杀死, 是不是停止脚本出问题
- b.问题在一段时间后重现, 重启后Port还是被占用
- 定位问题出现在一个叫做xxxxxx.sh的脚本, 该脚本占用了Agent使用的端口
- => 奇了怪了, 一个xxx.sh脚本使用这个奇葩Port干啥(大于60000的Port, 有兴趣的砖友可以想下为什么Agent默认使用6W+的端口)
- => review该脚本并没有进行端口监听的代码
- 定位问题出现在一个叫做xxxxxx.sh的脚本, 该脚本占用了Agent使用的端口
- 一拍脑袋, c.进程共享了父进程资源了
- => 溯源该脚本,发现确实是Agent启动的任务中的脚本之一
- => 问题基本定位, 该脚本属于Agent调用的脚本
- => 该Agent继承了Agent原来的资源FD, 也就是这个port
- => 虽然该脚本由于超时被动触发了terminate机制, 但terminate并没有干掉这个子进程
- => 该脚本进程的父进程(ppid) 被重置为了1
- d.问题****出在脚本进程超时kill逻辑
1.2 填坑解法
通过代码review, 找到shell具体执行的库代码如下:
self._subpro = subprocess.Popen(
cmd, shell=True, stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
preexec_fn=_signal_handle
)
# 重点是shell=True !
把上述代码改为:
self._subpro = subprocess.Popen(
cmd.split(), stdout=subprocess.PIPE,
stderr=subprocess.PIPE, preexec_fn=_signal_handle
)
# 重点是去掉了shell=True
1.3 坑位分析
Agent会在一个新创建的threading线程中执行这段代码, 如果线程执行时间超时(xx seconds), 会调用 self._subpro.terminate()终止该脚本.
表面正常:
- 启用新线程执行该脚本
- 如果出现问题,执行超时防止hang住其他任务执行调用terminate杀死进程
深层问题:
- Python 2.7.x中subprocess.Pipe 如果shell=True, 会默认把相关的pid设置为shell(sh/bash/etc)本身(执行命令的shell父进程), 并非执行cmd任务的那个进程
- 子进程由于会复制父进程的opened FD表, 导致即使被杀死, 依然保留了拥有这个Listened Port FD
这样虽然杀死了shell进程(未必死亡, 可能进入defunct状态), 但实际的执行进程确活着. 于是1.1中的坑就被结实的踩上了.
1.4 坑后扩展
1.4.1 扩展知识
本节扩展知识包括二个部分:
- Linux系统中, 子进程一般会继承父进程的哪些信息
- Agent这种常驻进程选择>60000端口的意义
扩展知识留到下篇末尾讲述, 感兴趣的可以自行搜索
1.4.1 技术关键字
- Linux系统进程
- Linux随机端口选择
- 程序多线程执行
- Shell执行
1.5 填坑总结
子进程会继承父进程的资源信息
如果只kill某进程的父进程, 集成了父进程资源的子进程会继续占用父进程的资源不释放, 包括但不限于
- listened port
- opened fd
- etc
Python Popen使用上, shell的bool状态决定了进程kill的逻辑, 需要根据场景选择使用方式
建议大家也看一下这篇文章的姊妹篇, 此篇是子孙进程无法 kill/杀死的终极解法 [Python 踩坑之旅进程篇其三pgid是个什么鬼 (子进程\子孙进程无法kill 退出的解法)] (https://www.cnblogs.com/mythmgn/p/10945941.html)
Python踩坑之旅其一杀不死的Shell子进程的更多相关文章
- Python 踩坑之旅进程篇其三pgid是个什么鬼 (子进程\子孙进程无法kill 退出的解法)
目录 1.1 踩坑案例 1.2 填坑解法 1.3 坑位分析 1.4.1 技术关键字 下期坑位预告 代码示例支持 平台: Centos 6.3 Python: 2.7.14 Github: https: ...
- [代码修订版] Python 踩坑之旅 [进程篇其四] 踩透 uid euid suid gid egid sgid的坑坑洼洼
目录 1.1 踩坑案例 1.2 填坑解法 1.3 坑位分析 1.4 技术关键字 1.5 坑后思考 下期坑位预告 代码示例支持 平台: Centos 6.3 Python: 2.7.14 代码示例: 公 ...
- Python 踩坑之旅进程篇其四一次性踩透 uid euid suid gid egid sgid的坑坑洼洼
目录 1.1 踩坑案例 1.2 填坑解法 1.3 坑位分析 1.4 技术关键字 1.5 坑后思考 下期坑位预告 代码示例支持 平台: Centos 6.3 Python: 2.7.14 代码示例: 菜 ...
- [代码修订版] Python 踩坑之旅进程篇其五打不开的文件
目录 1.1 踩坑案例 1.2 填坑和分析 1.2.1 从程序优化入手 1.2.2 从资源软硬限入手 1.4.1 技术关键字 下期坑位预告 代码示例支持 平台: Centos 6.3 Python: ...
- Python 踩坑之旅文件系统篇其一文件夹也是个文件
目录 1.1 案例 1.2 分析 1.3 扩展 1.4 技术关键字 下期预告 代码示例支持 平台: Mac OS Python: 2.7.10 代码示例: - wx: 菜单 - Python踩坑指南代 ...
- Python踩坑之旅其二裸用os.system的原罪
目录 1.1 踩坑案例 1.2 填坑解法 1.3 坑位分析 1.4.1 技术关键字 1.5 填坑总结 2. 前坑回顾 2.1 Linux中, 子进程拷贝父进程哪些信息 2.2 Agent常驻进程选择& ...
- EasyTrader踩坑之旅总结
easytrader是用python写的可以调用主要券商完成自动化炒股的一个软件 ,但我用的是同花顺,在研究过程中,发现同花顺暂时调不通.后来搜索发现thstrade的源码作者说是easytrad ...
- 我的微信小程序入门踩坑之旅
前言 更好的阅读体验请:我的微信小程序入门踩坑之旅 小程序出来也有一段日子了,刚出来时也留意了一下.不过赶上生病,加上公司里也有别的事,主要是自己犯懒,就一直没做.这星期一,赶紧趁着这股热乎劲,也不是 ...
- vue+ vue-router + webpack 踩坑之旅
说是踩坑之旅 其实是最近在思考一些问题 然后想实现方案的时候,就慢慢的查到这些方案 老司机可以忽略下面的内容了 1)起因 考虑到数据分离的问题 因为server是express搭的 自然少 ...
随机推荐
- 数据库高手(DBA专家 ,SSIS,replacation ,tourble shooting)
http://www.cnblogs.com/qanholas/category/266780.html 随笔分类 - mssql SQL Server 2008 Datetime Cast 成 Da ...
- hive-0.12.0-cdh5.1.0安装
先前条件: 要先安装好MYSQL 下载:hive-0.12.0-cdh5.1.0.tar.gz,并解压到安装目录 1. 添加环境变量 修改/etc/profile文件. #vi /etc/profil ...
- 很随意的让你了解 - 最小生成树之Prim算法
首先分成两个容器. 第一个容器就是装有生成树里面的顶点,第二个容器就是装有没有放入这个第一个容器中的顶点. 首先默认往第一个容器里面装一个顶点.然后..计算出第二个容器里所有顶点和这个顶点的距离.没有 ...
- 《精通Spring4.X企业应用开发实战》读后感第七章(AOP基础知识、jdk动态代理,CGLib动态代理)
- Struts学习第一课 使用Filter作为控制器的MVC应用
MVC设计模式概览 实现MVC(Model,View,Controller)模式的应用程序由3大部分构成: -模型:封装应用程序的数据和业务逻辑(POJO,Plain Old Java Object) ...
- doxygen+ graphviz 开源工具生成源码调用树的wiki
当拿到一含有大量代码的工程怎么看?!这时一个好的代码分析工具非常有用,网上有很多开源工具,但资料都参差不齐,偶然发现doxygen+ graphviz这两工具非常棒,使用工具直接生成函数调用链图,帮助 ...
- 开发过程中--使用base64解决传输字符串加密问题!
反正上周在解决开发公司小工具时,需要将用户输入的字符串加密处理传输,那就直接贴上代码吧,希望能帮上你们: strToArrayBufferToBase64(str) { let pos = 0, le ...
- [CentOS7] minimal安装后 出现 没有ifconfig 无法ping 无法yum could not retrieve mirrorlist http://mirrorlist.centos.org/
刚以minimal方式安装完CentOS,打算看下ip,结果ifconfig没找到(后来得知可以用ip addr查看本机ip) 于是yum grouplist, 结果出现could not retri ...
- WampServer的安装
首先安装好Microsoft Visual C++ 然后再安装WampServer 安装过程很简单 错误解决 运行后为黄色图标(成功运行应该为绿色图标) 解决办法: 1.80端口是否被占用 你的80端 ...
- 基于ECharts的股票行情分时、K线、MACD、DIF、DEA图表 (绝无仅有)
先上效果图 源码和使用说明已经开源至GitHub,欢迎各位能提出宝贵的意见噢 https://github.com/2557606319/H5-Kline