七天用 Go 写个 docker(第五天)
是不是以为太监了,哈哈,我又回来了
查看完整源码
通过前面四天,我们其实已经基本实现了docker的最核心的功能,后面几天,我将带大家实现一些docker的其他命令,今天我们主要是来实现一下 docker logs 功能,也就是查看docker内部日志
写日志
说下总体思路,这个功能其实比较简单,说白了,就是之前往控制台输出,现在改成往文件里面输出就好了,我们通过
docker logs
查看日志,也就是打开该文件,显示该文件里面的内容
开始改造
我们将之前的
tty
传递到创建父级线程哪里也就是process.go
的NewParentProcess函数 ,tty 也即是-ti
参数,也就是以命令行互动模式启动,如果用户没有输入-ti
, 那么我就将日志信息输出到文件里,这里我们将容器的Name作为文件名,后面方便我们通过容器名直接查询该容器里面的日志。
func NewParentProcess(tty bool, volume, containerName, imageName string, envs []string) (*exec.Cmd, *os.File) {
// .....
if tty {
cmd.Stdin = os.Stdin
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
} else {
// 把日志输出到文件里
logDir := path.Join(common.DefaultContainerInfoPath, containerName)
if _, err := os.Stat(logDir); err != nil && os.IsNotExist(err) {
err := os.MkdirAll(logDir, os.ModePerm)
if err != nil {
logrus.Errorf("mkdir container log, err: %v", err)
}
}
logFileName := path.Join(logDir, common.ContainerLogFileName)
file, err := os.Create(logFileName)
if err != nil {
logrus.Errorf("create log file, err: %v", err)
}
// 将cmd的输出流改到文件流中
cmd.Stdout = file
}
}
查看日志
新增一个command命令参数:
logs
`var logCommand = cli.Command{
Name: "logs",
Usage: "look container log",
Action: func(ctx *cli.Context) error {
if len(ctx.Args()) < 1 {
return fmt.Errorf("missing container name")
}
containerName := ctx.Args().Get(0)
container.LookContainerLog(containerName)
return nil
},
}
看一下 LookContainerLog
的具体实现,主要就是读文件….
// 查看容器内日志信息
func LookContainerLog(containerName string) {
logFileName := path.Join(common.DefaultContainerInfoPath, containerName, common.ContainerLogFileName)
file, err := os.Open(logFileName)
if err != nil {
logrus.Errorf("open log file, path: %s, err: %v", logFileName, err)
}
bs, err := ioutil.ReadAll(file)
if err != nil {
logrus.Errorf("read log file, err: %v", err)
}
_, _ = fmt.Fprint(os.Stdout, string(bs))
}
虽然木人关注,但是我还是厚着脸把公众号放上来了,希望能和大家共同成长。
本作品采用《CC 协议》,转载必须注明作者和本文链接
推荐文章: