是不是以為太監了,哈哈,我又回來了
檢視完整原始碼
通過前面四天,我們其實已經基本實現了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 協議》,轉載必須註明作者和本文連結