step011: run command
This commit is contained in:
6
internal/cmd/init.go
Normal file
6
internal/cmd/init.go
Normal file
@ -0,0 +1,6 @@
|
||||
package cmd
|
||||
|
||||
func init() {
|
||||
initRootCommand()
|
||||
initRunCommand()
|
||||
}
|
16
internal/cmd/root.go
Normal file
16
internal/cmd/root.go
Normal file
@ -0,0 +1,16 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
var (
|
||||
rootCommand = &cobra.Command{
|
||||
Use: "upod",
|
||||
Short: "upod is a simple container runtime implementation",
|
||||
}
|
||||
)
|
||||
|
||||
func initRootCommand() {
|
||||
|
||||
}
|
44
internal/cmd/run.go
Normal file
44
internal/cmd/run.go
Normal file
@ -0,0 +1,44 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"os"
|
||||
"upod/internal/container"
|
||||
"upod/internal/log"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
var (
|
||||
runCommand = &cobra.Command{
|
||||
Use: "run",
|
||||
Short: "upod run [OPTIONS] IMAGE [COMMAND] [ARG...]",
|
||||
RunE: func(ctx *cobra.Command, args []string) error {
|
||||
var (
|
||||
err error
|
||||
)
|
||||
|
||||
log.Debug("runCommand: args=%v", args)
|
||||
|
||||
if len(args) == 0 {
|
||||
return errors.New("upod run requires at least 1 argument")
|
||||
}
|
||||
|
||||
cmd := container.NewParentProcess(true, args[0])
|
||||
|
||||
if err = cmd.Start(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
cmd.Wait()
|
||||
|
||||
os.Exit(0)
|
||||
|
||||
return nil
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
func initRunCommand() {
|
||||
rootCommand.AddCommand(runCommand)
|
||||
}
|
19
internal/cmd/start.go
Normal file
19
internal/cmd/start.go
Normal file
@ -0,0 +1,19 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"context"
|
||||
"os"
|
||||
"upod/internal/container"
|
||||
"upod/internal/log"
|
||||
)
|
||||
|
||||
func Start(ctx context.Context) error {
|
||||
|
||||
if len(os.Args) >= 3 && os.Args[1] == "init" {
|
||||
log.Debug("cmd.Start: init args=%v", os.Args)
|
||||
|
||||
container.RunContainerInitProcess(os.Args[2], os.Args[2:])
|
||||
}
|
||||
|
||||
return rootCommand.ExecuteContext(ctx)
|
||||
}
|
32
internal/container/new.go
Normal file
32
internal/container/new.go
Normal file
@ -0,0 +1,32 @@
|
||||
package container
|
||||
|
||||
import (
|
||||
"os"
|
||||
"os/exec"
|
||||
"syscall"
|
||||
)
|
||||
|
||||
// NewParentProcess 启动一个新进程
|
||||
/*
|
||||
这里是父进程,也就是当前进程执行的内容。
|
||||
1.这里的/proc/se1f/exe调用中,/proc/self/ 指的是当前运行进程自己的环境,exec 其实就是自己调用了自己,使用这种方式对创建出来的进程进行初始化
|
||||
2.后面的args是参数,其中init是传递给本进程的第一个参数,在本例中,其实就是会去调用initCommand去初始化进程的一些环境和资源
|
||||
3.下面的clone参数就是去fork出来一个新进程,并且使用了namespace隔离新创建的进程和外部环境。
|
||||
4.如果用户指定了-it参数,就需要把当前进程的输入输出导入到标准输入输出上
|
||||
*/
|
||||
func NewParentProcess(tty bool, command string) *exec.Cmd {
|
||||
args := []string{"init", command}
|
||||
cmd := exec.Command("/proc/self/exe", args...)
|
||||
cmd.SysProcAttr = &syscall.SysProcAttr{
|
||||
Cloneflags: syscall.CLONE_NEWUTS | syscall.CLONE_NEWPID | syscall.CLONE_NEWNS |
|
||||
syscall.CLONE_NEWNET | syscall.CLONE_NEWIPC,
|
||||
}
|
||||
|
||||
if tty {
|
||||
cmd.Stdin = os.Stdin
|
||||
cmd.Stdout = os.Stdout
|
||||
cmd.Stderr = os.Stderr
|
||||
}
|
||||
|
||||
return cmd
|
||||
}
|
35
internal/container/run.go
Normal file
35
internal/container/run.go
Normal file
@ -0,0 +1,35 @@
|
||||
package container
|
||||
|
||||
import (
|
||||
"os"
|
||||
"syscall"
|
||||
"upod/internal/log"
|
||||
)
|
||||
|
||||
// RunContainerInitProcess 启动容器的init进程
|
||||
/*
|
||||
这里的init函数是在容器内部执行的,也就是说,代码执行到这里后,容器所在的进程其实就已经创建出来了,
|
||||
这是本容器执行的第一个进程。
|
||||
使用mount先去挂载proc文件系统,以便后面通过ps等系统命令去查看当前进程资源的情况。
|
||||
*/
|
||||
func RunContainerInitProcess(command string, args []string) error {
|
||||
var (
|
||||
err error
|
||||
)
|
||||
|
||||
log.Debug("RunContainerInitProcess: command=%s args=%v", command, args)
|
||||
|
||||
syscall.Mount("", "/", "", syscall.MS_PRIVATE|syscall.MS_REC, "")
|
||||
|
||||
defaultMountFlags := syscall.MS_NOEXEC | syscall.MS_NOSUID | syscall.MS_NODEV
|
||||
|
||||
_ = syscall.Mount("proc", "/proc", "proc", uintptr(defaultMountFlags), "")
|
||||
|
||||
argv := []string{command}
|
||||
|
||||
if err = syscall.Exec(command, argv, os.Environ()); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
19
internal/log/log.go
Normal file
19
internal/log/log.go
Normal file
@ -0,0 +1,19 @@
|
||||
package log
|
||||
|
||||
import (
|
||||
"os"
|
||||
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/spf13/cast"
|
||||
)
|
||||
|
||||
func init() {
|
||||
if cast.ToBool(os.Getenv("UPOD_DEBUG")) {
|
||||
logrus.SetLevel(logrus.DebugLevel)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func Debug(msg string, args ...any) {
|
||||
logrus.Debugf(msg, args...)
|
||||
}
|
Reference in New Issue
Block a user