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该脚本并没有进行端口监听的代码
  • 一拍脑袋, 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 填坑总结

  1. 子进程会继承父进程的资源信息

  2. 如果只kill某进程的父进程, 集成了父进程资源的子进程会继续占用父进程的资源不释放, 包括但不限于

    • listened port
    • opened fd
    • etc
  3. Python Popen使用上, shell的bool状态决定了进程kill的逻辑, 需要根据场景选择使用方式

建议大家也看一下这篇文章的姊妹篇, 此篇是子孙进程无法 kill/杀死的终极解法 [Python 踩坑之旅进程篇其三pgid是个什么鬼 (子进程\子孙进程无法kill 退出的解法)] (https://www.cnblogs.com/mythmgn/p/10945941.html)

Python踩坑之旅其一杀不死的Shell子进程的更多相关文章

  1. Python 踩坑之旅进程篇其三pgid是个什么鬼 (子进程\子孙进程无法kill 退出的解法)

    目录 1.1 踩坑案例 1.2 填坑解法 1.3 坑位分析 1.4.1 技术关键字 下期坑位预告 代码示例支持 平台: Centos 6.3 Python: 2.7.14 Github: https: ...

  2. [代码修订版] Python 踩坑之旅 [进程篇其四] 踩透 uid euid suid gid egid sgid的坑坑洼洼

    目录 1.1 踩坑案例 1.2 填坑解法 1.3 坑位分析 1.4 技术关键字 1.5 坑后思考 下期坑位预告 代码示例支持 平台: Centos 6.3 Python: 2.7.14 代码示例: 公 ...

  3. Python 踩坑之旅进程篇其四一次性踩透 uid euid suid gid egid sgid的坑坑洼洼

    目录 1.1 踩坑案例 1.2 填坑解法 1.3 坑位分析 1.4 技术关键字 1.5 坑后思考 下期坑位预告 代码示例支持 平台: Centos 6.3 Python: 2.7.14 代码示例: 菜 ...

  4. [代码修订版] Python 踩坑之旅进程篇其五打不开的文件

    目录 1.1 踩坑案例 1.2 填坑和分析 1.2.1 从程序优化入手 1.2.2 从资源软硬限入手 1.4.1 技术关键字 下期坑位预告 代码示例支持 平台: Centos 6.3 Python: ...

  5. Python 踩坑之旅文件系统篇其一文件夹也是个文件

    目录 1.1 案例 1.2 分析 1.3 扩展 1.4 技术关键字 下期预告 代码示例支持 平台: Mac OS Python: 2.7.10 代码示例: - wx: 菜单 - Python踩坑指南代 ...

  6. Python踩坑之旅其二裸用os.system的原罪

    目录 1.1 踩坑案例 1.2 填坑解法 1.3 坑位分析 1.4.1 技术关键字 1.5 填坑总结 2. 前坑回顾 2.1 Linux中, 子进程拷贝父进程哪些信息 2.2 Agent常驻进程选择& ...

  7. EasyTrader踩坑之旅总结

    ​ easytrader是用python写的可以调用主要券商完成自动化炒股的一个软件 ,但我用的是同花顺,在研究过程中,发现同花顺暂时调不通.后来搜索发现thstrade的源码作者说是easytrad ...

  8. 我的微信小程序入门踩坑之旅

    前言 更好的阅读体验请:我的微信小程序入门踩坑之旅 小程序出来也有一段日子了,刚出来时也留意了一下.不过赶上生病,加上公司里也有别的事,主要是自己犯懒,就一直没做.这星期一,赶紧趁着这股热乎劲,也不是 ...

  9. vue+ vue-router + webpack 踩坑之旅

    说是踩坑之旅 其实是最近在思考一些问题 然后想实现方案的时候,就慢慢的查到这些方案   老司机可以忽略下面的内容了 1)起因  考虑到数据分离的问题  因为server是express搭的   自然少 ...

随机推荐

  1. WPF Canvas

    Canvas为容器控件,用于定位. 1.基本应用 <Border HorizontalAlignment="Left" VerticalAlignment="Top ...

  2. 获取剪切板上DataFormats.Dib格式的文件

    if (formats.Contains(System.Windows.Forms.DataFormats.Dib)) { using (var img = System.Windows.Forms. ...

  3. GEO(Gene Expression Omnibus):高通量基因表达数据库

    Gene Expression Omnibus(GEO)是一个公共存储库,可以存档和自由分发由科学界提交的全套微阵列,新一代测序和其他形式的高通量功能基因组数据. 除数据存储外,还提供一系列基于Web ...

  4. 使用JSP输出九九乘法表

    在html网页中编写Java代码是,需要使用<%%>来编写,<%=%>表示取等号后面的值,如<%="hello"%>就会输出hello. < ...

  5. git branch简单使用

    1,branch的建立及使用git clone user@192.168.0.136:/media/projiect/omap4/nexttab/kernel kernel/android3.0/  ...

  6. Net Core 下载图片

    直接上代码 string url = https://www.cnblogs.com/images/logo_small.gif; //获取网站当前根目录 string sWebRootFolder ...

  7. [CentOS7] at, bash, cron, anacron

    声明:本文主要总结自:鸟哥的Linux私房菜-第十五章.例行性工作排程(crontab),如有侵权,请通知博主 at => /var/spool/at /etc/at.allow, /etc/a ...

  8. 最短路——弗洛伊德算法(floyd)

    模板: #include <bits/stdc++.h> using namespace std; ][]; int n,m,x,z,y; <<; int main() { c ...

  9. 2017-10-4 清北刷题冲刺班a.m

    P101zhx a [问题描述]你是能看到第一题的 friends 呢.——hjaHja 拥有一套时光穿梭技术,能把字符串以超越光速的速度传播,但是唯一的问题是可能会 GG.在传输的过程中,可能有四种 ...

  10. python-django框架中使用七牛云

    1:注册七牛云账号 https://www.qiniu.com/ js文件 链接:https://pan.baidu.com/s/1BW1svHqEsXrrTNtRobKkpg  提取码:ixta 2 ...