当前位置: 首页 > news >正文

Linux: bash起后台进程引发的僵尸进程

1. 前言

限于作者能力水平,本文可能存在谬误,因此而给读者带来的损失,作者不做任何承诺。

2. 案例

原来的故事是 这样 的,感兴趣的读者可以直接前往。我从中截取了一段重现故事中问题的代码(对原代码做了小小调整):

#include <unistd.h>
#include <stdio.h>
#include <sys/wait.h>#define SLEEP_SCRIPT_PATH "/home/bill/Study/qemu-lab/app/issue/1/sleep.sh&"int main(void)
{int pid;if ((pid = fork()) == 0) {printf("children: %d\n", getpid());/* /bin/bash -c /home/bill/Study/qemu-lab/app/issue/1/sleep.sh& */execle("/bin/bash", "/bin/bash", "-c", SLEEP_SCRIPT_PATH, (char *)0, NULL);}printf("parent: %d\n", getpid());//printf("waitfing for children... ");//wait(NULL);//printf("done.\n");while (1)sleep(1);return 0;
}

sleep.sh 的内容如下:

#!/bin/bashsleep 3

编译并运行:

$ make zombie_issue$ strace -f -t -e execve ./zombie_issue 
16:28:33 execve("./zombie_issue", ["./zombie_issue"], [/* 69 vars */]) = 0
parent: 11128
strace: Process 11129 attached
children: 11129
[pid 11129] 16:28:33 execve("/bin/bash", ["/bin/bash", "-c", "/home/bill/Study/qemu-lab/app/is"...], NULL) = 0
strace: Process 11130 attached
[pid 11130] 16:28:33 execve("/home/bill/Study/qemu-lab/app/issue/1/sleep.sh", ["/home/bill/Study/qemu-lab/app/is"...], [/* 3 vars */] <unfinished ...>
[pid 11129] 16:28:33 +++ exited with 0 +++
[pid 11128] 16:28:33 --- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=11129, si_uid=1000, si_status=0, si_utime=0, si_stime=0} ---
[pid 11130] 16:28:33 <... execve resumed> ) = 0
strace: Process 11131 attached
[pid 11131] 16:28:33 execve("/bin/sleep", ["sleep", "3"], [/* 3 vars */]) = 0
[pid 11131] 16:28:36 --- SIGWINCH {si_signo=SIGWINCH, si_code=SI_KERNEL} ---
[pid 11128] 16:28:36 --- SIGWINCH {si_signo=SIGWINCH, si_code=SI_KERNEL} ---
[pid 11130] 16:28:36 --- SIGWINCH {si_signo=SIGWINCH, si_code=SI_KERNEL} ---
[pid 11131] 16:28:36 +++ exited with 0 +++
[pid 11130] 16:28:36 --- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=11131, si_uid=1000, si_status=0, si_utime=0, si_stime=0} ---
[pid 11130] 16:28:36 +++ exited with 0 +++
16:28:37 --- SIGWINCH {si_signo=SIGWINCH, si_code=SI_KERNEL} ---$ ps -ef -o pid,ppid,commPID   PPID COMMAND9539   2774 bash11133   9539  \_ ps9439   2774 bash11126   9439  \_ strace11128  11126      \_ zombie_issue11129  11128          \_ bash <defunct>

看看,进程 11129 进程变僵尸了:<defunct> 标注表示进程变僵尸了。用 top 可以观察到变 Z 了:

top - 16:51:36 up  5:39,  1 user,  load average: 0.09, 0.04, 0.01
Tasks:   1 total,   0 running,   0 sleeping,   0 stopped,   1 zombie
%Cpu(s):  0.5 us,  2.1 sy,  0.0 ni, 97.4 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 st
KiB Mem :  4015908 total,   844272 free,   928832 used,  2242804 buff/cache
KiB Swap:        0 total,        0 free,        0 used.  2735724 avail Mem PID USER      PR  NI    VIRT    RES    SHR S  %CPU %MEM     TIME+ COMMAND                                                                  11129 bill      20   0       0      0      0 Z   0.0  0.0   0:00.02 bash

开始分析问题之前,我们先来了解 bash 是怎么处理 & 操作符 的:

If a command is terminated by the control operator &, the shell executes the 
command in the background in a subshell. The shell does not wait for the command 
to finish, and the return status is 0. 

上面是摘自 bash手册 原文,翻译下它的意思:
bash 启动的命令,如果尾接 & 操作符,则 bash 启动 子shell 来运行命令,而 bash 本身不等待
(即不对命令程序发起 wait() 调用)命令的结束,直接以退出码 0 退出。
我们再来简单了解下,什么样的进程会变成 僵尸进程
一个进程退出了,其存活的父进程又不对其进行回收(没有对进程发起 wait() 调用),则该进程就会变成 僵尸进程
有了上述对 bash & 操作符僵尸进程 的基础知识,我们就可以来理一理为什么会出现僵尸进程了。
我们不关注用来调试的 strace 进程,直接从 zombie_issue 说起。结合 strace 的追踪记录,以及程序 zombie_issue 的输出信息,我们按 进程 PID 来小结一下出现的几个进程:

11128: zombie_issue 进程
11129: zombie_issue 进程 fork 的子进程,用来启动程序 /bin/bash
11130: /bin/bash 的子shell,用来启动脚本 sleep.sh
11131: 运行脚本 sleep.sh 中 sleep 3 语句的进程

上面说了,进程变僵尸,是因为无人对它进行回收。我们一步步来看,为什么 进程 11129 最后变成了僵尸:

1. 脚本 sleep.sh 中执行 sleep 3 语句的进程 11131 运行完成后,子shell进程 11130 对其进行了回收,所以它不会变僵尸;
2. 子 shell 进程 11130 等到执行 sleep 3 语句的进程 11131 退出后,它自己也退出了。此时因为启动它的父进程程序 /bin/bash 已经退出了,它变成了无人理的孤儿,那么谁来回收它呢?针对这种父进程比子进程先结束的情形,Linux内核会将子进程托孤给 始祖进程init,由 init进程 负责完成子进程的回收。于是,我们的孤儿进程 11130 也被回收了,所以它不会变僵尸;
3. 而启动程序 /bin/bash 的进程 11129 ,自从它退出后,父程序 zombie_issue 进程 11128 对它不理睬,任其曝尸荒野,何其惨也,但由于父进程 zombie_issue 又没有退出,Linux内核也不会将其托孤给 init 进程,所以只能变僵尸了。

通过上面的分析,我们知道了 进程 11129 为什么变僵尸的原因。
上面的测试代码单独拿出来,就是一个编程BUG:存活的父进程 理应对子进程发起 wait() 。如果放开对代码中的 wait() 调用的注释,就不会出现僵尸进程。
这是一个简单的问题,但放在复杂的环境下,我们确实可能犯这样的错误。其实仅仅是要模拟出现僵尸进程的情形,上面的测试代码还可以简化:

#include <unistd.h>
#include <sys/wait.h>int main(void)
{int pid;if ((pid = fork()) == 0) {execle("/bin/bash", "/bin/bash", "-c", "/bin/ls", (char *)0, NULL);}//wait(NULL);while (1)sleep(1);return 0;
}

3. 参考资料

cron 僵尸进程问题分析
man bash

相关文章:

Linux: bash起后台进程引发的僵尸进程

1. 前言 限于作者能力水平&#xff0c;本文可能存在谬误&#xff0c;因此而给读者带来的损失&#xff0c;作者不做任何承诺。 2. 案例 原来的故事是 这样 的&#xff0c;感兴趣的读者可以直接前往。我从中截取了一段重现故事中问题的代码&#xff08;对原代码做了小小调整&a…...

网络安全攻防中,Rock-ON自动化的多功能网络侦查工具,Burpsuite被动扫描流量转发

网络安全攻防中&#xff0c;Rock-ON自动化的多功能网络侦查工具&#xff0c;Burpsuite被动扫描流量转发。 #################### 免责声明&#xff1a;工具本身并无好坏&#xff0c;希望大家以遵守《网络安全法》相关法律为前提来使用该工具&#xff0c;支持研究学习&#xff…...

电子技术——共模抑制

电子技术——共模抑制 我们在之前学习过&#xff0c;无论是MOS还是BJT的差分输入对&#xff0c;共模信号并不会改变漏极电流的大小&#xff0c;因此我们说差分输入对共模信号无响应。但是实际上由于各种客观非理想因素&#xff0c;例如电流源有限阻抗等&#xff0c;此时共模是影…...

对KMP简单的理解

声明&#xff1a;下边的例子均表示下标从1开始的数组 ne数组的定义&#xff1a; next[i] 就是使子串 s[1…i] 有最长相等前后缀的前缀的最后一位的下标。ne[i]也可以表示相等子串的长度 准备执行jne[j]时&#xff0c; 表示当前s[i]!p[j1] , 如果ne[j]1 &#xff0c;那么下…...

Hibernate不是过时了么?SpringDataJpa又是什么?和Mybatis有什么区别?

一、前言 ps: 大三下学期&#xff0c;拿到了一份实习。进入公司后发现用到的技术栈有Spring Data Jpa\Hibernate,但对于持久层框架我只接触了Mybatis\Mybatis-Plus&#xff0c;所以就来学习一下Spring Data Jpa。 1.回顾MyBatis 来自官方文档的介绍&#xff1a;MyBatis 是一款…...

数学建模拓展内容:卡方检验和Fisher精确性检验(附有SPSS使用步骤)

卡方检验和Fisher精确性检验卡方拟合度检验卡方独立性检验卡方检验的前提假设Fisher精确性检验卡方拟合度检验 卡方拟合度检验概要&#xff1a;卡方拟合度检验也被称为单因素卡方检验&#xff0c;用于检验一个分类变量的预期频率和观察到的频率之间是否存在显著差异。 卡方拟…...

【Python学习笔记之七大数据类型】

Python数据类型&#xff1a;Number数字、Boolean布尔值、String字符串、list列表、tuple元组、set集合、dictionary字典 int整数 a1 print(a,type(a))float浮点数 b1.1 print(b,type(b))complex复数 c100.5j print(c,type(c))bool布尔值:True、False,true和false并非Python…...

Android系统之onFirstRef自动调用原理

前言&#xff1a;抽丝剥茧探究onFirstRef究竟为何在初始化sp<xxx>第一个调用&#xff1f;1.onFirstRef调用位置<1>.system/core/libutils/RefBase.cpp#include <utils/RefBase.h>//1.初始化强指针 void RefBase::incStrong(const void* id) const {weakref_i…...

ipv6上网配置

一般现在的宽带都已经支持ipv6了&#xff0c;但是需要一些配置才能真正用上ipv6。记录一下配置过程。 当前测试环境为移动宽带&#xff0c;光猫下面接了一个路由器&#xff0c;家里所有的设备都挂到这个路由器下面的。 1. 光猫改桥接 光猫在使用路由模式下&#xff0c;ipv6无…...

python实现聚类技术—复杂网络社团检测 附完整代码

实验内容 某跆拳道俱乐部数据由 34 个节点组成,由于管理上的分歧,俱乐部要分解成两个社团。 该实验的任务即:要求我们在给定的复杂网络上检测出两个社团。 分析与设计 实验思路分析如下: 聚类算法通常可以描述为用相似度来衡量两个数据的远近,搜索可能的划分方案,使得目标…...

如何判断两架飞机在汇聚飞行?(如何计算两架飞机的航向夹角?)内含程序源码

ok&#xff0c;在开始一切之前&#xff0c;让我先猜一猜&#xff0c;你是不是想百度“二维平面下如何计算两个移动物体的航向夹角&#xff1f;”如果是&#xff0c;那就请继续往下看。 首先&#xff0c;我们要明确一个概念&#xff1a;航向角≠航向夹角&#xff01;&#xff0…...

Scipy稀疏矩阵bsr_array

文章目录基本原理初始化内置方法基本原理 bsr&#xff0c;即Block Sparse Row&#xff0c;bsr_array即块稀疏行矩阵&#xff0c;顾名思义就是将稀疏矩阵分割成一个个非0的子块&#xff0c;然后对这些子块进行存储。通过输入维度&#xff0c;可以创建一个空的bsr数组&#xff0…...

LeetCode笔记:Weekly Contest 332

LeetCode笔记&#xff1a;Weekly Contest 332 1. 题目一 1. 解题思路2. 代码实现 2. 题目二 1. 解题思路2. 代码实现 3. 题目三 1. 解题思路2. 代码实现 4. 题目四 1. 解题思路2. 代码实现 比赛链接&#xff1a;https://leetcode.com/contest/weekly-contest-332/ 1. 题目一…...

autox.js在vscode(win7)与雷神模拟器上的开发环境配置

目录 下载autox.js 安装autox.js&#xff1f; 在电脑上搭建autox.js开发环境 安装vscode 安装autox.js插件 雷神模拟器连接vscode 设置雷神模拟器IP 设置autox.js应用IP地址等 下载autox.js 大体来说&#xff0c;就是一个运行在Android平台上的JavaScript 运行环境 和…...

创建阿里云物联网平台

创建阿里云物联网平台 对云平台设备创建过程做记录&#xff0c;懒得再看视频 文章参考视频&#xff1a;https://www.bilibili.com/video/BV1jP4y1E7TJ?p26&vd_source50694678ae937a743c59db6b5ff46c31 阿里云&#xff1a;https://www.aliyun.com 1&#xff0e;物联网平…...

【链式二叉树】数据结构链式二叉树的(万字详解)

前言&#xff1a; 在上一篇博客中&#xff0c;我们已经详解学习了堆的基本知识&#xff0c;今天带大家进入的是二叉树的另外一种存储方式----“链式二叉树”的学习&#xff0c;主要用到的就是“递归思想”&#xff01;&#xff01; 本文目录1.链式二叉树的实现1.1前置说明1.2结…...

Koa2篇-简单介绍及使用

一.简介koa2是基于 Node.js 平台的下一代 web 开发框架, 致力于成为一个更小、更富有表现力、更健壮的 Web 框架。 可以避免异步嵌套. express中间件是异步回调,Koa2原生支持async/await二.async/awaitconst { rejects } require("assert"); const { resolve } req…...

Linux ALSA 之十一:ALSA ASOC Path 完整路径追踪

ALSA ASOC Path 完整路径追踪一、ASoc Path 简介二、ASoc Path 完整路径2.1 tinymix 设置2.2 完整路径 route一、ASoc Path 简介 如前面小节所描述&#xff0c;ASoc 中 Machine Driver 是 platform driver 和 codec driver 的粘合剂&#xff0c;audio path 离不开 FE/BE/DAI l…...

【Spring Cloud总结】1、服务提供者与服务消费者快速上手

目录 文件结构 代码 1、api 1.1实体类&#xff08;Dept &#xff09; 1.2数据库 2、provider 2.1 DeptController 2.2 DeptDao 2.3 DeptService 2.4 DeptServiceImpl 2.5 application.yml 3、consumer 3.1 ConfigBean 3.2 DeptConsumerController 测试 1.启动…...

若依项目学习之登录生成验证码

若依项目学习之登录生成验证码 使用DefaultKaptcha生成验证码 /*** 验证码配置* * author ruoyi*/ Configuration public class CaptchaConfig {/*** 生成字符类型的验证码**/Bean(name "captchaProducer")public DefaultKaptcha getKaptchaBean(){DefaultKaptcha…...

计算机网络5:数据在两台计算机之间是怎样传输的?

数据在两台计算机之间的传输总的来说包括了封装和解封两个过程 封装&#xff08;5层协议&#xff09; 以传送一张图片为例 **应用层&#xff1a;**将jpg格式的图片数据转化成计算机可以识别的0101的二进制的比特流 **传输层&#xff1a;**将应用层传输下来的数据进行分段&…...

就现在!为元宇宙和Web3对互联网的改造做准备!

欢迎来到Hubbleverse &#x1f30d; 关注我们 关注宇宙新鲜事 &#x1f4cc; 预计阅读时长&#xff1a;8分钟 本文仅代表作者个人观点&#xff0c;不代表平台意见&#xff0c;不构成投资建议。 如今&#xff0c;互联网是各种不同的网站、应用程序和平台的集合。由于彼此分离…...

【mysql数据库】

目录SQL数据库分页聚合函数表跟表之间的关联关系SQL中怎么将行转成列SQL注入将一张表的部分数据更新到另一张表WHERE和HAVING的区别索引索引分类如何创建及保存MySQL的索引&#xff1f;怎么判断要不要加索引&#xff1f;索引设计原理只要创建了索引&#xff0c;就一定会走索引吗…...

【测试开发】web 自动化测试 --- selenium4

目录1. 什么是自动化为什么要做自动化2. 为什么选择selenium作为我使用的web自动化工具3. 什么是驱动&#xff1f;驱动的工作原理是什么5. 第一个自动化程序演示6. selenium基本语法6.1 定位元素的方法6.2 操作页面元素6.3 等待6.4 信息打印获取当前页面句柄&#xff0c;窗口切…...

Elasticsearch7.8.0版本进阶——路由计算

目录一、路由计算1.1、路由计算的前提理解1.2、路由计算的概述1.3、路由计算的概述一、路由计算 1.1、路由计算的前提理解 当索引一个文档的时候&#xff0c;文档会被存储到一个主分片中。Elasticsearch 如何知道一个文档应该存放到哪个分片中呢&#xff1f;当我们创建文档时…...

c#反射-获取属性和字段的值

演示类 示例类具有一个私有实例字段&#xff0c;一个实例属性&#xff0c;一个实例字段&#xff0c;一个静态私有属性。 class Fight {private int hp;public int Hp{get > hp; set{if (value > 0){ hp value; }else if (-value > Def){ hp value - Def; }}}publi…...

前后端分离-小项目-1前端布局

技术栈前后端分离开发&#xff0c;前端主体框架Vue3后端基础框架Spring-Boot1.前端技术栈&#xff1a;Vue3AxiosElementPlus2.后端技术栈&#xff1a;Spring BootMyBatis Plus3.数据库-MySQL4.项目的依赖管理-Maven5.分页-MyBatis Plus的分页插件环境搭建安装Node.js LTSnode.j…...

基于jsp的网络电子相册的设计与实现

技术&#xff1a;Java、JSP等摘要&#xff1a;随着科学技术的不断进步&#xff0c;云技术以及大数据的不断完善&#xff0c;越来越多的网络忠实用户告别了冲洗相片的时代&#xff0c;他们更喜欢将相片上传至网络&#xff0c;这样就省去了携带和查找的麻烦&#xff0c;随时随地只…...

Python快速上手系列--类--详解篇

本章是自动化测试的真正开始&#xff0c;因为在后续的过程中&#xff0c;你会接触到unittest框架&#xff0c;pytest框架&#xff0c;而不仅仅只是写一个函数selenium脚本这么简单了。1、创建类1.1、了解类我们首先了解一下&#xff0c;为什么要使用类&#xff0c;类可以拿来干…...

Dubbo基本原理和用法讲解

Dubbo基本原理和用法讲解 序言&#xff1a;学习一项新技术&#xff0c;一般从是什么、为什么、怎么用三个方面进行学习。本篇文章也不例外&#xff0c;笔者将从Dubbo是什么&#xff1f;、为什么会产生Dubbo技术&#xff1f;、如何在项目中使用Dubbo技术。最后&#xff0c;笔者…...

网站建设的步骤/今日头条官网

如果要给C11颁一个“最令人困惑新词”奖&#xff0c;constexpr十有八九会折桂。当用于对象上面&#xff0c;它本质上就是const的加强形式&#xff0c;但是当它用于函数上&#xff0c;意思就大不相同了。有必要消除困惑&#xff0c;因为你绝对会用它的&#xff0c;特别是当你发现…...

wordpress大学主题下载地址/六年级上册数学优化设计答案

#!/bin/sh cd /data001/smallrig/data/basics java -Xms512m -Xmx512m -Xss256k -XX:PermSize64m -XX:MaxPermSize256m -jar smallrig-basics-1.0.0.jar >/dev/null 2>&1 & exit...

wordpress 内容 管理/网站策划是做什么的

节点健康检测意义在K8S集群运行的过程中&#xff0c;节点常常会因为运行时组件的问题、内核死锁、资源不足等各种各样的原因不可用。Kubelet默认对节点的PIDPressure、MemoryPressure、DiskPressure等资源状态进行了监控&#xff0c;但是当Kubelet上报这些状态的时候&#xff0…...

网站外部链接合理建设/关键词优化系统

IDM下载器安卓版是国外热门的多线程下载工具&#xff0c;一款非常优秀的下载神器&#xff0c;支持多媒体下载、自动捕获链接、自动识别文件名、静默下载、批量下载、计划下载任务、站点抓取、队列与网盘支持等 IDM下载速度据说比普通下载器快500%&#xff0c;基本能达到带宽的…...

广东省阳江网络问政平台/安徽关键词seo

前面几章早已讲到了科技公司与金融力量之间的关系&#xff0c;而当这个金融力量发生动乱的时候&#xff0c;这些科技公司又会发生什么&#xff1f;科技像是我们这个社会的大脑&#xff0c;而金融则是血液。发生金融危机时&#xff0c;就像人的血液出了问题&#xff0c;自然会对…...

wordpress 登陆链接/如何进入网站

缘起 随着互联网企业的不断发展&#xff0c;产品项目中的模块越来越多&#xff0c;用户体验要求也越来越高&#xff0c;想实现小步快跑、快速迭代的目的越来越难&#xff0c;还有65535&#xff0c;应用之间的互相调用等等问题&#xff0c;插件化技术应用而生。如果没有插件化技…...