1、问题:

通过docker exec产生的进程bash(5704)看ppid是docker-containe(5564),但是通过ptrace进程号5564没有关于clone的系统调用,就算ptrace进程号3594、3542也没有什么有意义的。所以我有一个疑问,这个bash(5704)是由谁产生的?以下通过实验来说明。

2、解决:

利用kprobes中的探测技术kretprobe(基于kprobe实现),探测sys_clone函数的返回值(此返回值为新进程的pid),同时也输出当前进程号

#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/kprobes.h>
#include <linux/ktime.h>
#include <linux/limits.h>
#include <linux/sched.h> static char func_name[NAME_MAX] = "sys_clone";
module_param_string(func, func_name, NAME_MAX, S_IRUGO);
MODULE_PARM_DESC(func, "Function to kretprobe; this module will report the"
" function's execution time"); /* per-instance private data */
struct my_data {
ktime_t entry_stamp;
}; /* Here we use the entry_hanlder to timestamp function entry */
static int entry_handler(struct kretprobe_instance *ri, struct pt_regs *regs)
{
struct my_data *data; if (!current->mm)
return ; /* Skip kernel threads */ data = (struct my_data *)ri->data;
data->entry_stamp = ktime_get();
return ;
} /*
* Return-probe handler: Log the return value and duration. Duration may turn
* out to be zero consistently, depending upon the granularity of time
* accounting on the platform.
*/
static int ret_handler(struct kretprobe_instance *ri, struct pt_regs *regs)
{
int retval = regs_return_value(regs);
struct my_data *data = (struct my_data *)ri->data;
s64 delta;
ktime_t now; now = ktime_get();
delta = ktime_to_ns(ktime_sub(now, data->entry_stamp));
printk(KERN_INFO "current task(%d) is %s, %s returned %d and took %lld ns to execute\n",
current->pid, current->comm, func_name, retval, (long long)delta);
return ;
} static struct kretprobe my_kretprobe = {
.handler = ret_handler,
.entry_handler = entry_handler,
.data_size = sizeof(struct my_data),
/* Probe up to 20 instances concurrently. */
.maxactive = ,
}; static int __init kretprobe_init(void)
{
int ret; my_kretprobe.kp.symbol_name = func_name;
ret = register_kretprobe(&my_kretprobe);
if (ret < ) {
printk(KERN_INFO "register_kretprobe failed, returned %d\n",
ret);
return -;
}
printk(KERN_INFO "Planted return probe at %s: %p\n",
my_kretprobe.kp.symbol_name, my_kretprobe.kp.addr);
return ;
} static void __exit kretprobe_exit(void)
{
unregister_kretprobe(&my_kretprobe);
printk(KERN_INFO "kretprobe at %p unregistered\n",
my_kretprobe.kp.addr); /* nmissed > 0 suggests that maxactive was set too low. */
printk(KERN_INFO "Missed probing %d instances of %s\n",
my_kretprobe.nmissed, my_kretprobe.kp.symbol_name);
} module_init(kretprobe_init)
module_exit(kretprobe_exit)
MODULE_LICENSE("GPL");

3、结果

探针输出结果如下:

current task() is docker-containe, sys_clone returned 
current task() is docker-containe, sys_clone returned
current task() is docker-containe, sys_clone returned
current task() is docker-containe, sys_clone returned
current task() is docker-containe, sys_clone returned
current task() is docker-containe, sys_clone returned
current task() is docker-containe, sys_clone returned
.......
current task() is docker-containe, sys_clone returned
current task() is docker-runc, sys_clone returned
current task() is docker-runc, sys_clone returned
current task() is docker-runc, sys_clone returned
current task() is docker-runc, sys_clone returned
current task() is docker-runc, sys_clone returned
current task() is docker-runc, sys_clone returned
current task() is runc:[:PARENT], sys_clone returned
current task() is runc:[:CHILD], sys_clone returned
current task() is runc:[:INIT], sys_clone returned

通过pstree -p看到进程树

           ├─dockerd()─┬─docker-containe()─┬─docker-containe()─┬─bash()
│ │ │ ├─bash()
│ │ │ ├─mysqld()─┬─{mysqld}()
│ │ │ │ ├─{mysqld}()
│ │ │ │ ├─{mysqld}()
│ │ │ │ ├─{mysqld}()
│ │ │ │ ├─{mysqld}()
│ │ │ │ ├─{mysqld}()
│ │ │ │ ├─{mysqld}()
│ │ │ │ ├─{mysqld}()
│ │ │ │ ├─{mysqld}()
│ │ │ │ ├─{mysqld}()
│ │ │ │ ├─{mysqld}()
│ │ │ │ ├─{mysqld}()
│ │ │ │ ├─{mysqld}()
│ │ │ │ ├─{mysqld}()
│ │ │ │ ├─{mysqld}()
│ │ │ │ ├─{mysqld}()
│ │ │ │ ├─{mysqld}()
│ │ │ │ ├─{mysqld}()
│ │ │ │ ├─{mysqld}()
│ │ │ │ ├─{mysqld}()
│ │ │ │ ├─{mysqld}()
│ │ │ │ ├─{mysqld}()
│ │ │ │ ├─{mysqld}()
│ │ │ │ ├─{mysqld}()
│ │ │ │ ├─{mysqld}()
│ │ │ │ ├─{mysqld}()
│ │ │ │ ├─{mysqld}()
│ │ │ │ ├─{mysqld}()
│ │ │ │ ├─{mysqld}()
│ │ │ │ ├─{mysqld}()
│ │ │ │ ├─{mysqld}()
│ │ │ │ ├─{mysqld}()
│ │ │ │ ├─{mysqld}()
│ │ │ │ ├─{mysqld}()
│ │ │ │ └─{mysqld}()
│ │ │ ├─{docker-containe}()
│ │ │ ├─{docker-containe}()
│ │ │ ├─{docker-containe}()
│ │ │ ├─{docker-containe}()
│ │ │ ├─{docker-containe}()
│ │ │ ├─{docker-containe}()
│ │ │ ├─{docker-containe}()
│ │ │ └─{docker-containe}()
│ │ ├─{docker-containe}()
│ │ ├─{docker-containe}()
│ │ ├─{docker-containe}()
│ │ ├─{docker-containe}()
│ │ ├─{docker-containe}()
│ │ ├─{docker-containe}()
│ │ ├─{docker-containe}()
│ │ ├─{docker-containe}()
│ │ ├─{docker-containe}()
│ │ ├─{docker-containe}()
│ │ └─{docker-containe}()

一个图总结,其中红线部分运行完就退出了,所以pstree -p看不到:

所以根本就不是由docker-contained-shim(5564)产生的bash进程,所以ptrace没什么结果。

一个问题:以上红框内runc退出后其子进程bash不是应该由init进程接管吗?如何变成docker-containerd-shim的子进程呢?

解答:从Linux 3.4开始,prctl增加了对PR_SET_CHILD_SUBREAPER的支持,这样就可以控制孤儿进程可以被谁接管,而不是像以前一样只能由init进程接管。

4、后续

左边是strace结果,右边是kret结果。ppid是通过status查看的,可以看到很多不是28323产生的进程,都通过prctl由它接管了

但左边28330显示是parent,而右边显示28330是child

即为:红线内是kret视角(kret一起监控clone和execve,发现parent等的确没有发生execve)

原因猜测:

先clone原进程,新进程刚要运行就会因为被标记的延迟信号(SIGSTOP)要处理,所以第一时间就陷入到strace(strace跟踪多线程与内核的交互),strace此时wait到的pid是新进程的,而name是刚才clone的父进程的。

而后该新进程正常运行,改名(可以通过prctl(PR_SET_NAME, new_name)。参考:linux下修改进程名称),所以该进程发生clone时name和strace看到的已经不同了。

以上是一种根据现象猜测的原因,具体是不是这样需要看docker的在这部分的实现,为啥改名呢?

docker exec进程是由谁产生的的更多相关文章

  1. docker attach 和 docker exec

    docker attach docker attach -- Attach to a running container. 常用选项: --sig-proxy=true:Proxy all recei ...

  2. 使用docker exec命令

    这个命令使用exit命令后,不会退出后台,一般使用这个命令,使用方法如下   docker exec -it db3 /bin/sh 或者 docker exec -it d48b21a7e439 / ...

  3. Docker exec与Docker attach

    转载博客地址:http://blog.csdn.net/halcyonbaby 新浪微博:@寻觅神迹 内容系本人学习.研究和总结,如有雷同,实属荣幸! ================== Docke ...

  4. docker run VS docker exec 的区别

    “docker run”和“docker exec”都是 Docker 容器中用于执行的命令.然而,在不同的情况下,它们的使用有着本质上的区别. “docker run”命令 “docker run” ...

  5. 使用docker exec 就可以进入container,例如:docker exec -it <container_id> /bin/bash

    使用docker exec 就可以进入container,例如:docker exec -it <container_id> /bin/bash

  6. paas架构之docker——容器进程管理

    1.docker进程管理 docker的进程管理命令ps的用法基本和ubuntu系统的用法一致 1.1. 查看docker进程 sudo docker ps –a 1.2. 附着到容器上 Sudo d ...

  7. docker exec 运行命令

    docker:/root/sbin# docker exec -it 17aaf60ee3a1 /sbin/ifconfig -a eth1 Link encap:Ethernet HWaddr 22 ...

  8. docker 学习笔记20:docker守护进程的配置与启动

    安装好docker后,需要启动docker守护进程.有多种启动方式. 一.服务的方式 因为docker守护进程被安装成服务.所以,可以通过服务的方式启停docker守护进程,包括查看状态. sudo ...

  9. docker exec 系统找不到指定的路径。

    相关问题和答案 >docker exec -it a1 echo "hello..." > /var/www/html/index.html 系统找不到指定的路径. & ...

随机推荐

  1. Tcpdump MySQL Query

    在MySQL线上环境我们一般只打开了binary log,slow log,有时我们需要查看general log呢?因为该log记录所有的请求,打开该日志肯定给磁盘造成很大压力,IO能力有所下降,所 ...

  2. Sql server 2016 Always On 搭建Windows集群配置

    .安装WSFC群集组件 1)打开服务器管理器,选择“功能”,在右边窗口中点击“添加功能”. 2)在添加功能向导中,勾选“故障转移群集”,点击“下一步”. 3)在“确认安装选择”页面中,点击“安装”,进 ...

  3. 对Python源码加密及反编译前后对比

    关于python的加密 目前软件开发商对 Python 加密时可能会有两种形式,一种是对python转成的exe进行 保护,另一种是直接对.py或者.pyc文件进行保护,下面将列举两种形式的保护流程. ...

  4. nginx --反向代理配置文件

    配置文件如下图   server { listen 8080; server_name 0.0.0.0;//这里可以配置相应域名 root /www/facei; index index.html i ...

  5. C++了解free和delete

    (转自:http://www.cnblogs.com/mrye/archive/2012/09/01/2667079.html) void MyMethod1() {     using namesp ...

  6. golang gui library 库

    andlabs/ui已经重写,稳定性增强,但是组件很少,只提供了几种基础的控件,慎用.gxui死了,别用.linuxdeepin转QT了,所以…… windows系统最好的选择是walk. 首先,写w ...

  7. vue 获取屏幕宽高 width height

    /**  * 获取屏幕宽高  */ Vue.prototype.getViewportSize = function(){   return {     width: window.innerWidt ...

  8. sql server相关

    sql server nolock 在sqlserver 中with(nolock)详解   所有Select加 With (NoLock)解决阻塞死锁 在查询语句中使用 NOLOCK 和 READP ...

  9. Hibernate框架的第四天

    ## Hibernate框架的第四天 ## ---------- **回顾:Hibernate框架的第三天** 1. 一对多关联关系映射 * JavaBean的编写 * 编写映射的配置文件 * 使用级 ...

  10. Jenkins. 安装过程中出现一个错误: No such plugin: cloudbees-folder

    安装过程中出现一个错误: No such plugin: cloudbees-folder 安装插件,有时候会报类似的错误:An error occurred during installation: ...