从零自制docker-15-【实现 mydocker run -d 支持后台运行容器】

news2024/11/17 15:34:50

文章目录

  • 实现目的
  • 莫名奇妙的问题
  • 对之前upper层出现root补充
  • 对run某些命令出现找不到文件或目录的原因
  • 代码
  • 效果

实现目的

docker run -d时容器在后台运行,而不会进入命令行交互形式

  1. 首先是需要添加-d选项
  2. 然后设置当添加-d选项时候主进程不会等待子进程,而是直接结束
func Contain_run(cmd string,it bool,resource_config *cgroups.Resource,volume string) {
	command,writepipe,rooturl:=new_contain_process(it,volume)
	log.Infof("cmd %s it %t",cmd,it)
	
	if err:=command.Start();err!=nil{
		log.Error(err)
	}
	log.Infof("cmd %s",cmd)
	cmdstring:=strings.Split(cmd, " ")
	log.Infof("split cmd %v",cmdstring)

	llkdockercgroups:=cgroups.Cgroups{
		Cgroups_Name: "llkdockercgroups",
		Resour:resource_config,
		Sub:cgroups.Subsystemins,
	}
	log.Info(llkdockercgroups.Resour)

	cgroups_path:=cgroups.Get_cgroups_path("cgroup",llkdockercgroups.Cgroups_Name)
	log.Info("in run.go get cgroups_path")
	llkdockercgroups.Move(command.Process.Pid,cgroups_path)

	llkdockercgroups.Set(cgroups_path)
	//defer llkdockercgroups.Remove(cgroups_path) //-d后台运行的话不能删除cgroup

	write_to_pipe(cmdstring,writepipe)
	if it{ //-it实现交互,那么当前终端就不能关闭退出,还需留给子进程使用
		command.Wait()
		// 从容器内的命令行中的退出才会wait结束
		end_volume(rooturl,volume)
		end_overlays(rooturl)
	}
	
	log.Infof("exit  !!!")

}
  1. 最后注意主进程不能删除该进程建立的cgroup,否则会出现下述问题,这个是删除cgroup出现的问题,原因是这个cgroup还包含一些正在运行的进程,那些进程没有结束就删除cgroup会删除失败
    在这里插入图片描述

解决方法:就是在-it的模式下最后删除,但后台运行的不会

if it{ //-it实现交互,那么当前终端就不能关闭退出,还需留给子进程使用
		command.Wait()
		// 从容器内的命令行中的退出才会wait结束
		end_volume(rooturl,volume)
		end_overlays(rooturl)
		llkdockercgroups.Remove(cgroups_path) //-d后台运行的话不能删除cgroup
	}

这个是后台运行docker的
在这里插入图片描述
而最后通过-it运行的结果如下
在这里插入图片描述

莫名奇妙的问题

发现调试的时候,使用log.Infof等其他类似的,最后终端上没有显示全,但通ps -ef|grep -e PPID -e top查看发现其又确实在在运行

例如下面这个9550进程是后台运行的top进程
在这里插入图片描述
但在终端上显示时有时不全,有时也会显示全
在这里插入图片描述
这里我是开了子进程的和当前终端的标准输入输出和错误都一样的,不然看不到相关调试信息

func new_contain_process(it bool,volume string)  (*exec.Cmd,*os.File,string){	
	
	readpipe,writepipe,err:=os.Pipe()
	if err!=nil{
		log.Fatal(err)
	}
	command:=exec.Command("/proc/self/exe","init")
	command.SysProcAttr=&syscall.SysProcAttr{
		Cloneflags: syscall.CLONE_NEWUTS | syscall.CLONE_NEWPID | syscall.CLONE_NEWNS |
			syscall.CLONE_NEWNET | syscall.CLONE_NEWIPC,
	}
	 //主进程和子进程共用一个终端
		command.Stdin=os.Stdin
		command.Stdout=os.Stdout
		command.Stderr=os.Stderr
	
	log.Info(command)
	log.Infof("sucess create a contain process")
	command.ExtraFiles=[]*os.File{readpipe}
	mntURL := "./merged"
	rootURL := "./"
	command.Dir = mntURL
	prepare_overlays(rootURL) 
	prepare_volume(rootURL,volume)

	log.Info(readpipe)
	return command,writepipe,rootURL
	
}

对之前upper层出现root补充

之前一直是对上一个写的docker复制然后在复制的上面写新的,发现busybox和刚从busybox解压得到缺少了很多东西,然后又重新解压生成了busybox将其使用。然后之前在后面发现upper中出现root是调用相关命令就会出现root,但当时没有啥修改的文件,这次全的busybox发现出现了下面的这个,那么确实就是因为调用命令引起的日志记录的变化导致的
在这里插入图片描述

对run某些命令出现找不到文件或目录的原因

当时是容器在挂载前就找相关命令,找到的这个是宿主机上的,但我们要的是在pivoroot后的根目录下的相关命令的路径,所以后面运行这个宿主机上的路径会显示路径找不到,因为此时是以容器的根目录为相对参考


func Contain_init(){
	
	
	cmd:=readpipe()
	log.Infof("init %s",cmd)
	
	log.Infof("cmd[0] %s",cmd[0]=="/bin/sh")
	log.Infof("cmd len %d",len(cmd))
	log.Infof("cmd %s",cmd[0])
	/*
	path,err:=exec.LookPath(cmd[0])//挂载前得到相关命令的路径会出现找不到
	if err!=nil{
		log.Fatal(err)
	}
	argv:=[]string{}
    for i:=1;i<len(cmd);i++{
		argv=append(argv,cmd[i-1])
	}*/

	log.Infof("prepare for mount ")

	mount()
	path,err:=exec.LookPath(cmd[0]) //挂载后再得到相关命令的路径等
	if err!=nil{
		log.Fatal(err)
	}
	argv:=[]string{}
    for i:=1;i<len(cmd);i++{
		argv=append(argv,cmd[i-1])
	}


	log.Infof("prepare for exec cmd ")
	log.Info(path)
	log.Info(argv)
	log.Info(os.Environ())

	if err:=syscall.Exec(path,argv,os.Environ());err!=nil{
		log.Infof("exec error")
		log.Info(err)
	}
	
}

代码

https://github.com/FULLK/llkdocker/tree/main/run_d_docker

效果

最终我启动了sudo ./run_docker run -d top多次,在cgroup.procs中可以看到(一部分是之前sudo ./run_docker run -it /bin/sh加入的,因为我最后关闭了主进程最后自动删除cgroup的函数),最终可以看到top进程在后台运行
`
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1721253.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

ollama入门系列教程简介与目录

教程简介 Ollama教程系列是为那些希望深入了解并掌握Ollama框架的开发者设计的。通过这一系列的教程,用户将学习如何从基础设置到高级功能的各个方面,有效地在Ollama平台上开发和部署大型语言模型。本系列包括如何将模型导入Ollama框架、利用与OpenAI兼容的API、以及如何使用…

关于ida如何进行远程linux调试(详解)

首先我们需要安装工具软件VMware虚拟机和finalshell&#xff0c;并在虚拟机中安装centos 7系统&#xff0c;还要将finalshell连接到该系统中&#xff0c;具体操作可以去b站搜黑马Linux学习&#xff0c;学完该课程的p5&#xff0c;p6&#xff0c;p8即可&#xff0c;我接下来讲的…

CentOS7.9部署安装OpenGauss 5.0.2企业版

1、更新系统: yum update -y 2、更改主机名&#xff1a; hostnamectl set-hostname opendb01 3、关闭透明页&#xff1a; echo never > /sys/kernel/mm/transparent_hugepage/enabled echo never > /sys/kernel/mm/transparent_hugepage/defrag# 加入开机自启动 echo …

[数据集][目标检测][数据集][目标检测]智能手机检测数据集VOC格式5447张

数据集格式&#xff1a;Pascal VOC格式(不包含分割的txt文件&#xff0c;仅仅包含jpg图片和对应的xml) 图片数量(jpg文件个数)&#xff1a;5447 标注数量(xml文件个数)&#xff1a;5447 标注类别数&#xff1a;1 标注类别名称:["phone"] 每个类别标注的框数&#xff…

容器技术基础理论与常用命令:必知必会,效率翻倍!

如何利用容器技术提升你的工作效率&#xff1f;掌握基础理论和常用命令是必不可少的&#xff0c;本文将为你全面介绍容器技术&#xff0c;并教你必知必会的技能&#xff0c;让你工作、学习效率翻倍&#xff0c;对于网络安全工作者也是必不可少的技能&#xff01; 0. 引言 学习…

大型制造业集团IT信息化总体规划方案(65页PPT)

方案介绍&#xff1a; 本大型制造业集团IT信息化总体规划方案旨在通过构建先进、高效、稳定的IT信息化系统&#xff0c;支撑集团各业务领域的运营和管理需求&#xff0c;促进集团整体运营效率和竞争力的提升。通过实施本项目&#xff0c;集团将能够更好地应对市场变化和客户需…

python编程:创建 SQLite 数据库和表的图形用户界面应用程序

在本文中&#xff0c;我将介绍如何使用 wxPython 模块创建一个图形用户界面&#xff08;GUI&#xff09;应用程序&#xff0c;该应用程序允许用户选择 SQLite 数据库的存放路径、数据库名称、表名称&#xff0c;并动态添加字段及其类型。以下是具体的实现步骤和代码示例。 C:\p…

LeetCode503:下一个更大元素Ⅱ

题目描述 给定一个循环数组 nums &#xff08; nums[nums.length - 1] 的下一个元素是 nums[0] &#xff09;&#xff0c;返回 nums 中每个元素的 下一个更大元素 。 数字 x 的 下一个更大的元素 是按数组遍历顺序&#xff0c;这个数字之后的第一个比它更大的数&#xff0c;这…

配置arduino和ESP8266

首先准备好arduino 的IDE和ESP8266的驱动以及板子 1.安装驱动&#xff0c;双击x64的版本驱动&#xff0c;安装好以后&#xff0c;在资源管理器检查端口&#xff0c;比如下下图出现的COM4就是esp8266所使用的端口 2.安装好arduino最好不要在路径中存在中文符号&#xff0c;打开…

专升本的硕士学历被歧视了。。

精品推荐&#xff1a; 《征服数据结构》&#xff0c;《经典图论算法》 在牛客网上看到一个帖子&#xff0c;一网友说之前已经签了一家公司&#xff0c;现在又找了一家公司&#xff0c;并且这家公司也发了offer&#xff0c;让他和上一家公司解约。结果他和上一家公司解约完之后&…

FENDI CLUB精酿啤酒中原麦汁浓度的高低有何区别?

关于精酿啤酒&#xff0c;有两个关键数据&#xff0c;一个是原麦汁浓度&#xff0c;一个是酒精度。酒精度无非是含酒精的高低&#xff0c;但原麦汁浓度又是什么呢&#xff1f;另外精酿啤酒中原麦汁浓度有高有低&#xff0c;究竟有哪些区别呢&#xff1f; 原麦汁浓度是指啤…

【面试八股总结】MySQL索引(二):B+树数据结构、索引使用场景、索引优化、索引失效

参考资料&#xff1a;小林coding、阿秀 一、为什么InnoDB采用B树作为索引数据结构&#xff1f; B 树是一个自平衡多路搜索树&#xff0c;每一个节点最多可以包括 M 个子节点&#xff0c;M 称为 B 树的阶&#xff0c;所以 B 树就是一个多叉树。 B 树与 B 树的差异&#xff1a;…

为何选择 MindMapper

MindMapper是一款专业的可视化思维导图软件&#xff0c;通过智能绘图方法&#xff0c;在管理信息和 处理工作流程中&#xff0c;帮助提高组织、审查、合作、分享和交流能力。 企业创造力 在企业界&#xff0c;MindMapper思维导图软件可以提高生产力和沟通效果&#xff0c;以及…

react路由参数path不再支持正则?比较v5和v6写法的差异性

文章目录 前言v5方式&#xff1a;直接在path参数中&#xff0c;写入对应正则&#xff08;1&#xff09;代码详细注释如下&#xff08;2&#xff09;页面输出如下&#xff0c;会出现undefined的情况 v6方式: 在路由对象中配置&#xff0c;但只可配动态路由&#xff0c;不可用正则…

FTP原理

一、FTP工作原理 FTP是一种文件传输协议&#xff0c;用来上传和下载&#xff0c;实现远程共享文件。 工作原理 &#xff1a; 端口号21号端口&#xff0c;用于互联网上的控制文件的双向传输 是一个应用程序。工作在TCP/IP。 连接时同时处理服务器和客户端的连接命令和数据传输&…

CANOE制造dll文件,以及应用dll文件

1、使用canoe自带的capl dll 2、然后使用Visual Studio 2022 打开项目 3、项目打开后修改下项目属性 4、修改capldll.cpp文件 4.1 添加的内容 void CAPLEXPORT far CAPLPASCAL appSum(long i, long j, long* s){*s i j;} {"sum", (CAPL_FARCALL)appSum, "…

只出现一次的数字II ---- 位运算

题目链接 题目: 分析: 对于只出现一次的数字, 他的任意一个bit位, 可能是0或1对于其余出现3次的数字, 假设有3n个数, 那么他们的任意一个bit相加的和可能是3n个0或3n个1那么对于数组中的全部数字的任意一个bit位之和共有三种情况: 3n个1 1 3n13n个0 1 13n个1 0 3n3n个0…

海外媒体发稿:打造个人品牌的2个必备宣发套餐-华媒舍

个人品牌在现代社会中扮演着关键的角色&#xff0c;它可以帮助我们在职场竞争中脱颖而出。但是&#xff0c;要想打造一个成功的个人品牌&#xff0c;并不是一件容易的事情。在这篇文章中&#xff0c;我将为你介绍两个必备的宣发套餐&#xff0c;让你成为行家。 1. 社交媒体宣发…

HR人才测评,如何做营销人员岗位素质测评?

营销人员是企业中的重要角色&#xff0c;他们直接负责企业产品或服务的销售和推广&#xff0c;是企业中最直接影响销售业绩的人才之一。因此&#xff0c;营销人员的基本素质测评非常重要&#xff0c;能够有效评估营销人员的能力和潜力&#xff0c;为企业招聘和培养优秀的营销人…

企业如何进行快递运费对账?

在电子面单寄件取代手写纸质面单之后&#xff0c;加上月结寄件模式的推行&#xff0c;企业快递运费对账&#xff0c;成了行政的一个难题...... 早期的手写纸质面单寄件&#xff0c;企业行政或者财务相关人员&#xff0c;遵循寄前审批&#xff0c;寄后报销的原则进行对账。随着电…