从零自制docker-8-【构建实现run命令的容器】

文章目录

  • log "github.com/sirupsen/logrus"
  • `args...`
  • go module
  • import第三方包失败
  • package和 go import的导入
  • go build . 和go run
  • cli库
  • `log.SetFormatter(&log.JSONFormatter{})`
  • error和nil的关系
  • cmd.Wait()和cmd.Start()
  • arg……
  • context.Args().Get(0)
  • syscall.Exec和os/exec.Command
  • `syscall.Exec`
  • mountflags
  • syscall.Mount
  • 请注意,只有包中首字母大写的函数(public函数)才能被其他包调用。首字母小写的函数(private函数)只能在包内部使用
  • 代码
  • 最终效果
  • 问题

log “github.com/sirupsen/logrus”

log “github.com/sirupsen/logrus”: 这是引入了 github.com/sirupsen/logrus 包,并将其重命名为 log

args...

假设我们有一个切片 myArgs := []string{"arg1", "arg2", "arg3"},我们想将这个切片作为参数传递给 exec.Command() 函数。

如果直接传递 myArgs 作为参数,那么 exec.Command() 函数会将整个切片作为一个单独的参数:

cmd := exec.Command("/path/to/executable", myArgs)

这相当于执行命令 /path/to/executable ["arg1" "arg2" "arg3"]

但是如果我们使用 args... 语法,就可以将切片中的每个元素都作为独立的参数传递给 exec.Command() 函数:

cmd := exec.Command("/path/to/executable", myArgs...)

这相当于执行命令 /path/to/executable "arg1" "arg2" "arg3"

args... 语法会将切片 myArgs 中的每个元素都作为独立的参数传递给 exec.Command() 函数。这种方式更加灵活,可以方便地将任意长度的参数列表传递给外部命令。

另一个例子是:

args := []string{"-flag1", "value1", "-flag2", "value2"}
cmd := exec.Command("/path/to/executable", args...)

这会将 args 切片中的 6 个元素全部作为独立的参数传递给 /path/to/executable 命令。

总之,args... 语法可以将一个切片展开为多个独立的参数,传递给需要接受多个参数的函数,在处理命令行参数时非常有用。

go module

三种包管理方式参考连接

go get下载的第三方包的位置

在GOMODULE模式下,go get命令会将依赖包下载到$GOPATH/pkg/mod目录下

go module包管理方式(推荐使用)

GO111MODULE 是一个用来控制 Go Modules 行为的环境变量。在 Go 1.11 版本之后,Go 引入了 Go Modules 来管理依赖关系和版本控制。GO111MODULE 环境变量可以设置为以下几个值:

  1. GO111MODULE=on:这是启用 Go Modules 的模式。当设置为 on 时,Go 将会使用 Go Modules 来管理依赖关系,无需再依赖 GOPATH。

  2. GO111MODULE=off:这是禁用 Go Modules 的模式。当设置为 off 时,Go 将使用传统的 GOPATH 模式来管理依赖关系。

  3. GO111MODULE=auto:这是自动模式。在自动模式下,Go 将根据当前目录是否包含 go.mod 文件来决定是否启用 Go Modules。如果在项目根目录下存在 go.mod 文件,则会启用 Go Modules,否则使用 GOPATH 模式。

因此,当设置 GO111MODULE=''(即空字符串)时,表示未显式设置 GO111MODULE 环境变量,Go 将根据自动模式来决定是否启用 Go Modules,具体行为取决于当前项目的目录结构和是否存在 go.mod 文件。

go mod tidy:检测该文件夹目录下所有引入的依赖,写入 go.mod 文件。删除错误或者不使用的modules,下载没download的package(下载到$GOPATH/pkg/mod)

import第三方包失败

go env -w GOPROXY=https://goproxy.cn,direct

再尝试

package和 go import的导入

go import导入包详解

在这里插入图片描述

golang使用同目录下的文件,golang中的package使用简介

在golang 里面一个目录为一个package, 一个package级别的func, type, 变量, 常量, 这个package下的所有文件里的代码都可以随意访问, 也不需要首字母大写。
引用当前目录得其它子目录中的文件可以import这个文件所在的文件夹相对位置,也可以import 当前目录/子目录中的package

Go语言中的包Package详解

包分为两种,一种是main函数(可执行文件)一种是库函数的包
可执行程序的包,编译完成后会生成一个可执行文件、静态库的包编译之后会生成一个.a为后缀的文件(在$GOPATH/pkg/里),自己不能执行只能被可执行包引用。

可执行程序的包必须以main作为包名,静态库的包名没有

main包和其他类库通过静态链接,最终形成的可执行文件是没有任何外部依赖的。

go build . 和go run

go build .将当前目录所有的文件都会编译并生成一个可执行程序
go run 编译单个程序并运行,此时如果多个package为main的程序有相互依赖,那么go run 其中一个会报错,因为用了其他package为main的程序

cli库

Go 每日一库之 cli

log.SetFormatter(&log.JSONFormatter{})

假设我们有一个简单的 Go 程序,用于记录一些基本的日志信息:

package mainimport ("log"
)func main() {// 设置日志输出格式为 JSON 格式log.SetFormatter(&log.JSONFormatter{})// 记录一些日志信息log.Println("This is an informational message")log.Printf("User %s logged in", "John Doe")log.Fatalf("Failed to connect to database: %s", "connection refused")
}

在这个例子中,我们首先使用 log.SetFormatter(&log.JSONFormatter{}) 将日志输出格式设置为 JSON 格式。

然后,我们分别使用 log.Println()log.Printf()log.Fatalf() 记录了三条不同级别的日志信息。

当我们运行这个程序时,日志输出将会是 JSON 格式,类似于以下内容:

{"level":"info","msg":"This is an informational message","time":"2024-04-07T12:34:56Z"}
{"level":"info","msg":"User John Doe logged in","time":"2024-04-07T12:34:56Z"}
{"level":"error","msg":"Failed to connect to database: connection refused","time":"2024-04-07T12:34:56Z"}

与默认的文本格式相比,JSON 格式的日志输出包含了更多的元信息,如日志级别(level)、消息内容(msg)和时间戳(time)。这种结构化的日志格式更加方便后续的处理和分析,特别是在需要机器解析日志的场景下。

总之,log.SetFormatter(&log.JSONFormatter{}) 是一个非常实用的方法,可以帮助我们更好地管理和处理 Go 程序的日志信息。

error和nil的关系

error类型和nil的关系是这样的:

  • error类型是Go语言中一个接口,用来表示一个错误情况。一个实现了Error()方法的值,即使没有实现任何具体的行为,也被称为一个error值。
  • nil是Go语言中的一个特殊值,它表示的是空值或不存在的值,对于error类型的值来说,nil表示没有错误发生。

在函数返回值中,当函数执行正确,没有遇到错误时,我们通常会用nil来表示。例如:

func someFunction() error {// 函数执行成功,没有错误return nil
}

当函数执行遇到错误时,我们会返回一个非nilerror值,例如:

func someFunction() error {// 函数执行失败,返回一个错误return errors.New("Some error occurred.")
}

所以,error类型和nil的关系是:nil表示error类型的值为非错误状态,非nilerror表示存在错误。在函数返回时,如果error值为nil,则表示函数执行成功,否则表示有错误发生。

cmd.Wait()和cmd.Start()

err变量在调用cmd.Wait()方法后得到返回值。当调用cmd.Start()时,该方法会启动命令并在后台执行。如果在启动命令时发生了错误(例如命令不存在、权限不足等),cmd.Start()会立即返回一个非nil的错误值。

而cmd.Wait()方法的作用是等待命令执行完毕。当命令执行结束后,此方法会返回。返回值有两个含义:

若命令执行成功结束,err将为nil。
若在命令执行过程中出现任何错误(比如命令被信号终止、超时退出等),err将包含相应的错误信息。
因此,在你的代码片段中,err = cmd.Wait()这一行会阻塞直到外部命令执行完毕,然后返回一个表示命令执行结果(成功与否及退出状态)的错误值。

arg……

在Go语言中,os/exec包提供了执行外部命令的功能。这里的代码片段是用于创建一个可执行命令的实例。

args := []string{"init", cmd} 是定义了一个字符串切片(slice),它存储了要执行的命令及其参数。在这个例子中:

  • "init":是一个命令参数,表示要执行的子命令为 “init”。
  • cmd:是一个变量,通常代表另一个命令参数。具体的值取决于程序上下文中的赋值情况。

然后,command := exec.Command("/proc/self/exe", args...) 这一行是用来创建一个新的 *Cmd 结构体实例,这个实例代表了一个待执行的命令。

"/proc/self/exe" 是一个特殊路径,在Linux系统中指向当前正在运行的可执行文件。也就是说,这里实际上是打算执行与当前进程相同的一个新进程,并且传入参数 args

args... 是Go语言中的变长参数语法,它会将字符串切片 args 扩展为多个单独的参数传递给 exec.Command 函数。

所以整个语句的作用是,根据给定的参数列表 args,执行与当前进程相同的新的命令行程序,并且第一个参数是 “init”,第二个参数是变量 cmd 的值。

context.Args().Get(0)

在Go语言中,这段代码片段是基于第三方命令行工具库(如urfave/clicobra)来定义一个命令行命令init的结构体。在这些库中,cli.Context对象包含了从命令行输入解析出来的所有信息。

context.Args().Get(0) 这一行代码在用户调用命令 init 并带有一个或多个额外参数时,用于获取命令行中紧随命令名 init 之后的第一个参数。

举个例子,假设用户在命令行中执行了如下命令:

./myapp init mycontainer

在上述代码段中,context.Args().Get(0) 将返回字符串 "mycontainer"。这是因为context.Args() 返回的是一个包含所有非命令名称参数的字符串切片,索引0位置的元素就是第一个参数。

然而,根据这段代码的具体上下文,看起来开发者并未真正使用到 cmd 变量(它保存了第一个参数的值),而是直接调用了 contain.init() 方法初始化容器。如果预期是利用第一个参数来定制初始化行为,那么应该会在 contain.init() 调用中使用到 cmd 变量。

syscall.Exec和os/exec.Command

在Go语言中,syscall.Execos/exec.Command 都是用来执行外部程序的,但它们在用途和机制上有显著的不同:

  1. syscall.Exec

    • syscall.Exec 是一个低级别的系统调用,直接在当前进程中替换当前程序的映像和数据,执行新的程序。
    • syscall.Exec 成功执行后,原始程序的内存空间、文件描述符等资源将被新程序接管,原始程序不会恢复执行,因为它已经被完全替换掉了。
    • 通常用在那些希望彻底转换当前进程上下文而不返回的情况。
  2. os/exec.Command

    • os/exec.Command 提供了一种高级别的、更易于使用的API来执行外部程序,并且它不会替换当前进程的内容。
    • exec.Command 创建并返回一个 *Cmd 类型的结构体,调用其 Run() 方法来执行外部程序,执行完成后,当前Go程序会继续执行后续代码。
    • 你可以通过 Output()CombinedOutput() 等方法获取子进程的输出,并且可以控制子进程的标准输入、输出和错误流。
    • 如果需要在同一进程中连续执行多个外部命令,或者需要处理子进程的输出结果,那么 os/exec 库是非常适合的。

简单来说,syscall.Exec 更像是进程自身的“变身”,而 os/exec.Command 则是在当前进程中启动一个新的子进程来进行任务,并且可以对子进程进行更多的控制和通信。

syscall.Exec

在Go语言中,当程序执行到 syscall.Exec 函数时,会发生以下情况:

  1. 当前进程替换
    syscall.Exec 函数负责执行一个新的程序,同时替换当前进程的映像和内存空间。这意味着当前执行的Go程序的所有代码和数据都会被新的程序所取代,不再有任何机会回到原来的Go程序执行流中。

  2. 资源继承
    新程序将继承当前进程的PID(进程ID)、打开的文件描述符以及其他一些进程相关的资源。这意味着新程序可以从原先的进程中接过控制权,例如继续监听同一套网络端口或读写已打开的文件。

  3. 程序执行
    syscall.Exec 函数接受一系列参数,包括要执行的程序路径、命令行参数和环境变量。新程序将以指定的方式执行,就像它是由shell或其他启动器直接启动的一样。

  4. 永不返回
    一旦 syscall.Exec 成功执行了新程序,原Go程序的代码将不再被执行,并且 syscall.Exec 函数本身也不会返回——因为它已经不再是那个进程的一部分了。如果 syscall.Exec 失败(例如由于找不到要执行的程序或权限问题),它会返回一个错误,但这种情况下的“返回”实际上已经是当前进程内的紧急错误处理逻辑了,而不是原Go程序的逻辑继续执行。

  5. 用途
    syscall.Exec 通常用于服务程序升级、执行子进程并替换自己以进入不同的执行环境等情况,或者是不需要原程序继续运行的场景。相比之下,如果你想在当前进程中启动一个子进程并与其交互或等待子进程结束后继续执行,应该使用 os/exec 包中的 CommandRun 等方法。

  • syscall.Exec(command, argv, os.Environ()) 的作用是:

    • command:这是要执行的新程序的路径或者可执行文件名。
    • argv:这是一个字符串切片,包含传递给新程序的命令行参数。在这个例子中,只有 command 一个参数,但实际上可以有多个,比如 argv := []string{command, arg1, arg2, ...}
    • os.Environ():这个函数返回当前进程的环境变量列表,格式为 key=value 的字符串切片。在 syscall.Exec 中,这个参数用于传递给新程序,使其继承当前进程的环境变量。

mountflags

  1. syscall.MS_NOEXEC
    设置此标志后,挂载的文件系统上的所有文件都无法被执行,即使是可执行文件。这是一项重要的安全措施,可以阻止恶意或误操作尝试执行存储在特定文件系统分区中的程序。例如,在只用于数据存储的分区上启用此选项可以增强安全性,确保即便有潜在恶意脚本或程序也不得运行。

  2. syscall.MS_NOSUID
    当挂载文件系统时带有此标志,系统会忽略文件的Set-User-ID (SUID) 和 Set-Group-ID (SGID) 位的效果。在Linux中,SUID和SGID权限通常允许用户在执行某个文件时暂时获取文件所有者的权限或执行该文件时的组权限。禁用SUID和SGID意味着,无论文件本身有何种特殊权限设定,进程在执行文件时不会继承文件所有者的用户ID或组ID,从而限制了可能因滥用特权而导致的安全风险。

  3. syscall.MS_NODEV
    使用此标志挂载文件系统时,系统将不允许任何设备特殊文件在该文件系统上工作。设备文件是用来访问硬件设备(如硬盘、终端、打印机等)的接口。禁止设备文件意味着无法在该挂载点创建或访问设备节点,这对于防止未经授权的设备访问以及增强隔离环境的安全性非常有用,比如在沙箱环境中或对安全性要求较高的文件系统分区。

syscall.Mount

syscall.Mount 是 Go 语言标准库 syscall 包中提供的一个函数,用于直接调用操作系统的系统调用来完成文件系统的挂载操作。在Linux环境下,这个函数对应的就是Linux内核提供的mount(2)系统调用接口。

函数签名一般如下所示(可能会根据不同Go版本有所变化):

func Mount(source string, target string, fstype string, flags int, data string) error

参数含义:

  • source:待挂载的文件系统源,它可以是设备名(如 /dev/sda1)、网络共享路径或者其他形式,对于虚拟文件系统如 proc,则是一个标识符字符串。

  • target:挂载点,即目标挂载路径,通常是一个已经存在的目录。

  • fstype:文件系统的类型名称,如 ext4ntfs 或者像上面提到的 proc 这样的特殊文件系统类型。

  • flags:挂载标志,是一个整数值,由多个标志位组合而成,例如 syscall.MS_NOEXEC | syscall.MS_NOSUID | syscall.MS_NODEV,这些标志位用于控制挂载行为的不同属性。

  • data:可选的额外挂载选项,通常是一个字符串,格式取决于所使用的文件系统类型,对于一些文件系统,可能包含挂载选项的列表或其他特定信息,对于不需要额外数据的文件系统,可以传入空字符串 ""

函数执行的结果是成功或失败,若失败则返回一个错误对象。

在给出的例子中:

syscall.Mount("proc", "/proc", "proc", uintptr(defaultMountFlags), "")

这是在挂载Linux的虚拟文件系统 /proc/proc 目录下,并且使用了 defaultMountFlags 中定义的一系列安全相关的挂载标志。

请注意,只有包中首字母大写的函数(public函数)才能被其他包调用。首字母小写的函数(private函数)只能在包内部使用

代码

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

最终效果

在这里插入图片描述
在这里插入图片描述

问题

发现只能run一次,下次就出现在这里插入图片描述
有待解决

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

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

相关文章

【Leetcode每日一题】 递归 - 验证二叉搜索树(难度⭐⭐)(53)

1. 题目解析 题目链接:98. 验证二叉搜索树 这个问题的理解其实相当简单,只需看一下示例,基本就能明白其含义了。 2.算法原理 中序遍历是二叉树遍历中的一种重要方式,它按照左子树、根节点、右子树的顺序访问每个节点。这种方式…

2024mathorcup妈妈杯数学建模A题思路模型

2024mathorcup妈妈杯数学建模A题思路模型:比赛开始后第一时间更新,更新见文末名片,下面对2022年B题进行介绍: 2022Mathorcup B题题目介绍 ​ B题无人仓的搬运机器人调度问题本题考在无人仓内的仓库管理问题之一,搬运机…

机场数据治理系列介绍(5)民用机场智慧能源系统评价体系设计

目录 一、背景 二、体系设计 1、评价体系设计维度 2、评价体系相关约定 3、评价指标体系框架设计 4、能源利用评价指标 5、环境友好评价指标 6、智慧管控评价指标 7、安全保障评价指标 三、具体落地措施 一、背景 在“双碳”国策之下,各类机场将能源系统建…

深入解析template,掌握C++模板的精髓!

掌握C模板(template)的优雅之道! 一、什么是模板?二、模板如何工作?三、C 中的模板类型3.1、 类模板3.2、 函数模板 四、模板参数推导4.1、模板参数推导示例4.2、函数模板参数推导4.3、类模板参数推导(C17 …

2024年MathorCup妈妈杯数学建模思路C题思路解析+参考成品

1 赛题思路 (赛题出来以后第一时间在群内分享,点击下方群名片即可加群) 2 比赛日期和时间 报名截止时间:2024年4月11日(周四)12:00 比赛开始时间:2024年4月12日(周五)8:00 比赛结束时间&…

GPU部署ChatGLM3

首先,检查一下自己的电脑有没有CUDA环境,没有的话,去安装一个。我的电脑是4060显卡,买回来就自带这些环境了。没有显卡的话,也不要紧,这个懒人安装包支持CPU运行,会自动识别没有GPU,…

启明智显M4核心板驱动17寸屏 为您打造无与伦比的视觉盛宴

近日,启明智显推出M4核心板驱动17寸屏,8 Link LVDS接口下1280*1024分辨率为用户展现了超强的视觉体验。 M4核心板采用纯国产架构,内置了16位DDR内存,为设备提供强大的数据处理能力和高效的运行速度。无论是处理复杂的任务还是进…

【简单讲解下C++max函数的使用】

🌈个人主页: 程序员不想敲代码啊 🏆CSDN优质创作者,CSDN实力新星,CSDN博客专家 👍点赞⭐评论⭐收藏 🤝希望本文对您有所裨益,如有不足之处,欢迎在评论区提出指正,让我们共…

Java | Leetcode Java题解之第13题罗马数字转整数

题目&#xff1a; 题解&#xff1a; class Solution {Map<Character, Integer> symbolValues new HashMap<Character, Integer>() {{put(I, 1);put(V, 5);put(X, 10);put(L, 50);put(C, 100);put(D, 500);put(M, 1000);}};public int romanToInt(String s) {int …

考研数学|刷题用汤家凤《1800》还是张宇《1000》?看完这篇你就懂了

考研数学的复习是一个系统的过程&#xff0c;不同的习题集有各自的特点和适用场景。汤家凤的1800题和张宇的1000题都是非常受欢迎的考研数学复习资料&#xff0c;它们各有侧重点和优势。 汤家凤的1800题以其全面性和基础性著称&#xff0c;题目覆盖了考研数学的各个知识点&…

缓存穿透问题

缓存穿透 &#xff1a;缓存穿透是指客户端请求的数据在缓存中和数据库中都不存在&#xff0c;这样缓存永远不会生效&#xff0c;这些请求都会打到数据库。 常见的两种解决方案&#xff1a; 1.缓存空对象 优点&#xff1a;实现简单&#xff0c;维护方便 缺点&#xff1a;占用…

【40分钟速成智能风控4】传统风险管理体系

目录 人工审核 纸质材料评估 电话回访 线下走访尽调 专家模型 业务规则库 专家调查权重法 熵权法 随着大数据和机器学习技术的发展与成熟&#xff0c;智能风控已经逐步取代传统风控&#xff0c;成为国内互联网金融机构主流的风险管理模式。一方面&#xff0c;传统风控是…

U盘中病毒了会影响电脑吗 U盘中病毒了怎么恢复数据 easyrecovery数据恢复软件免费版 easyrecovery绿色版破解版激活密钥无需注册

EasyRecovery是世界著名数据恢复公司 Ontrack 的技术杰作&#xff0c;EasyRecovery破解版是一个威力非常强大的硬盘数据恢复工具&#xff0c;能够帮你恢复丢失的数据以及重建文件系统。您只需要按软件提示一步一步操作&#xff0c;就能恢复出你电脑上的文档、表格、图片、音频、…

LeetCode 热题 100 | 多维动态规划(一)

目录 1 多维动态规划 2 62. 不同路径 3 64. 最小路径和 菜鸟做题&#xff0c;语言是 C&#xff08;细品动态规划 ing&#xff09; 1 多维动态规划 目前的感觉&#xff1a;抽象为二维数组。 2 62. 不同路径 题眼&#xff1a;“机器人每次只能向下或者向右移动一步”。…

什么是sso?

SSO&#xff08;Single Sign-On&#xff09;&#xff0c;即单点登录&#xff0c;是一种安全协议&#xff0c;它允许用户在多个应用程序之间使用同一组登录凭据进行身份验证。这意味着用户只需要登录一次&#xff0c;就可以访问多个需要身份验证的应用程序。 SSO的工作原理如下…

亚信安慧AntDB数据库分享“UltraSync特性介绍”技术演讲,助力客户降本增效

3月30日&#xff0c;由中国开源软件联盟组织的PostgreSQL技术峰会活动在南京举办&#xff0c;各数据库厂商研发带头人、企业资深DBA和众多技术爱好者齐聚一堂。湖南亚信安慧科技有限公司&#xff08;简称&#xff1a;亚信安慧&#xff09; AntDB-T产品线研发负责人梁博受邀参会…

「每日跟读」英语常用句型公式 第6篇

「每日跟读」英语常用句型公式 第6篇 1. As ___ as possible 越 ___ 越好 As soon as possible (ASAP)(越快越好) As happy as possible (越快乐越好) As prepared as possible (越有准备越好) As much/many as possible (越多越好 *不可数/可数) As early as possible …

探秘KMP算法:解密字符串匹配的黑科技

KMP算法 在正式进入KMP算法之前&#xff0c;不得不先引经据典一番&#xff0c;因为直接去理解KMP&#xff0c;你可能会很痛苦&#xff08;别问&#xff0c;问就是我也痛苦过&#xff09;。所以做好前面的预热工作非常非常重要&#xff0c;为了搞明白KMP&#xff0c;在没见到KMP…

快速理解vim编辑器和软硬连接

刚开始学习linux基础命令时最难搞懂的应该就是vi和ln命令了&#x1f62d;&#xff0c;写这篇文章主要想和大家分享一下我对这两个命令的理解&#xff0c;希望能更快的帮助到那些还没搞懂的同学&#x1f61c; 首先我们要知道vim编辑器主要分为三个工作模式&#xff0c;分别是图上…

基于单片机钢琴电子节拍器系统设计

**单片机设计介绍&#xff0c;基于单片机钢琴电子节拍器系统设计 文章目录 一 概要二、功能设计三、 软件设计原理图 五、 程序六、 文章目录 一 概要 基于单片机钢琴电子节拍器系统设计是一个综合性的项目&#xff0c;它结合了单片机编程、音频处理、用户界面设计等多个领域的…