如何将cobra与klog结合实现日志同时输出到终端和文件
问题:Cobra整合klog后日志无法写入文件
我需要用Cobra生成可执行文件,同时用klog打印并留存日志。单独测试klog时可以同时输出到终端和文件:
package main import ( "flag" "k8s.io/klog" ) func init() { var fs flag.FlagSet klog.InitFlags(&fs) fs.Set("logtostderr", "false") fs.Set("log_file_max_size", "100") fs.Set("log_file", "/home/test/workspace/klogfile/test.log") fs.Set("alsologtostderr", "true") } func main() { defer klog.Flush() klog.Info("info") klog.Warning("warning") klog.Error("error") }
日志文件/home/test/workspace/klogfile/test.log能正常生成并写入内容。但整合到Cobra后,虽然通过--help能看到klog的选项,但执行命令时日志仅输出到终端,不写入文件:
package main import ( "flag" "github.com/spf13/cobra" "k8s.io/klog" ) var ( str = "hello world" ) func NewCommand() *cobra.Command { cmd := &cobra.Command{ Use: "echo", Short: "use klog with cobra", Long: "Use klog together with cobra.", Run: func(cmd *cobra.Command, args []string) { Run() }, } klog.InitFlags(flag.CommandLine) cmd.Flags().AddGoFlagSet(flag.CommandLine) cmd.Flags().SortFlags = false cmd.Flags().StringVar(&str, "str", str, "string to print") return cmd } func Run() { defer klog.Flush() klog.Infof("Running, str:%s", str) } func main() { if err := NewCommand().Execute(); err != nil { klog.Fatalf("root cmd execute failed, err=%v", err) } }
执行命令:
go run main2.go --logtostderr false --log_file_max_size "100" --alsologtostderr true --log_file "/home/test/workspace/klogfile/test2.log"
仅终端输出日志,文件无内容。
原因与解决方法
原因
问题核心是klog没有读取到Cobra解析后的flag值。你只是把klog的flag集合添加到了Cobra中,但klog的初始化逻辑依赖标准库flag包的解析结果,而Cobra解析flag后并不会自动同步给flag.CommandLine,导致klog仍然使用默认配置,没有启用文件日志。
修改方法
在Cobra命令执行前,手动触发flag.CommandLine的解析,让klog读取到正确的配置。最直接的方式是在命令的PreRun函数中执行解析:
修改NewCommand函数,添加PreRun逻辑:
func NewCommand() *cobra.Command { cmd := &cobra.Command{ Use: "echo", Short: "use klog with cobra", Long: "Use klog together with cobra.", // 添加PreRun,解析klog的flags PreRun: func(cmd *cobra.Command, args []string) { // 触发flag.CommandLine解析,让klog读取配置 flag.CommandLine.Parse([]string{}) }, Run: func(cmd *cobra.Command, args []string) { Run() }, } klog.InitFlags(flag.CommandLine) cmd.Flags().AddGoFlagSet(flag.CommandLine) cmd.Flags().SortFlags = false cmd.Flags().StringVar(&str, "str", str, "string to print") return cmd }
验证
重新执行之前的命令,日志会同时输出到终端和指定文件/home/test/workspace/klogfile/test2.log,文件中会生成正确的日志内容。
内容的提问来源于stack exchange,提问作者moluzhui
相关产品推荐
相关产品推荐

