2

我使用 cobra 创建 CLI 命令工具。除了错误处理,一切看起来都很好

如果错误发送命令(错误的参数或错误的输入),我想要什么返回std.err而不是std.out

为了简化我创建的演示我的用例的secnario

package main

import (
    "errors"
    "fmt"
    "os"

    "github.com/spf13/cobra"
)

var (
    RootCmd = &cobra.Command{
        Use: "myApp",
        Run: func(cmd *cobra.Command, args []string) {
            fmt.Printf("ROOT verbose = %d, args = %v\n", args)
        },
    }

    provideCmd = &cobra.Command{
        Use: "provide",
        Run: nil,
    }

    appCmd = &cobra.Command{
        Use: "apps",
        RunE: func(cmd *cobra.Command, args []string) error {
            name := args[0]
            if name != "myapp" {
                err := errors.New("app name doesnt exist")
                return err
            }
            return nil
        },
        SilenceUsage:               true,
    }


)

func init() {
    // Add the application command to app command
    provideCmd.AddCommand(appCmd)
    //  add provide command to root command
    RootCmd.AddCommand(provideCmd)
}

func main() {
    if err := RootCmd.Execute(); err != nil {
        fmt.Println(err)
        os.Exit(-1)
    }
}

现在,如果我编译二进制文件并exec.Command针对二进制文件运行,一切都会按预期工作。但是如果我想测试错误场景,就像mycli provide apps apps1 我想看到返回的std.err而不是std.out

当我执行mycli provide apps myapp一切都应该没问题

但是如果我跑步,mycli provide apps myapp2我想得到 std.err 而不是 std.out ,这里不是这种情况......我在这里错过了什么?

https://play.golang.org/p/B00z4eZ7Sj-

4

1 回答 1

1

您的示例已经将错误打印到stdoutstderr

默认情况下,cobra包会将遇到的任何错误打印到stderr,除非您专门更改它。

因此,运行 会创建一个包含以下内容的文本文件(这是 cobra 在没有您干预的情况下./main provide apps something 2> ./stderr.txt写入的内容):stderr

Error: app name doesnt exist

并运行./main provide apps something > ./stdout.txt- 创建一个包含以下内容的文本文件(您自己使用fmt.Println(err),代码底部的第二行打印该文件):

app name doesnt exist

这意味着默认行为将错误打印到stdoutstderr

正如 Devin 所建议的那样,将最后一行更改为os.Stderr.WriteString(err)or fmt.Fprintln(os.Stderr, err)(我将使用的那个)将使您的项目将 所有内容打印为stderronly,这意味着打印错误两次:

Error: app name doesnt exist
app name doesnt exist

知道 cobra 允许您对错误打印行为进行一些控制可能会很有用。例如,您可以告诉 cobra 命令要打印到哪个流:

command.SetOutput(os.Stdout)     // Defaults to os.Stderr

您还可以防止打印错误:

command.SilenceErrors = true

或阻止打印使用文本:

command.SilenceUsage = true
于 2018-11-05T19:00:31.407 回答