douchuitang0642 2018-11-05 16:22
浏览 26
已采纳

GO:使用错误的参数运行cli命令

I use cobra to create CLI command tool. everything is looking OK except the error handling

what I want that if command was sent by mistake (wrong args or wrong input) return std.err instead of std.out

to simplify the secnario I've created this which demonstrate my use-case

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
", 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)
    }
}

Now if I compile the binary and run exec.Command against the binary everything is working as expected. but if I want to test the error scenario like mycli provide apps apps1 I want to see that returned in std.err and not at std.out

When I execute mycli provide apps myapp everything should be OK

but if I run mycli provide apps myapp2 I want to get std.err and not std.out , which is not the case here ...what am I missing here ?

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

  • 写回答

1条回答 默认 最新

  • dongzen2675 2018-11-05 19:00
    关注

    Your sample already prints the error both to stdout and stderr.

    By default the cobra package prints any errors it encounters to stderr, unless you specifically change that.

    So running ./main provide apps something 2> ./stderr.txt creates a text file with the following content (this is what cobra writes to stderr without your intervention):

    Error: app name doesnt exist
    

    And running ./main provide apps something > ./stdout.txt - creates a text file with the following content (you printed that yourself with fmt.Println(err), the second line from the bottom in your code):

    app name doesnt exist
    

    Which means default behaviour prints errors both to stdout and stderr.

    As Devin has advised you, changing the last line to os.Stderr.WriteString(err) or fmt.Fprintln(os.Stderr, err) (the one I would use) will make your project to print everything to stderr only, which means printing errors twice:

    Error: app name doesnt exist
    app name doesnt exist
    

    It might be useful to know that cobra allows you some control of error printing behaviour. For example, you can tell a cobra command which stream to print to:

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

    you could also prevent printing of errors:

    command.SilenceErrors = true
    

    or prevent printing of usage text:

    command.SilenceUsage = true
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥50 NT4.0系统 STOP:0X0000007B
  • ¥15 想问一下stata17中这段代码哪里有问题呀
  • ¥15 flink cdc无法实时同步mysql数据
  • ¥100 有人会搭建GPT-J-6B框架吗?有偿
  • ¥15 求差集那个函数有问题,有无佬可以解决
  • ¥15 【提问】基于Invest的水源涵养
  • ¥20 微信网友居然可以通过vx号找到我绑的手机号
  • ¥15 寻一个支付宝扫码远程授权登录的软件助手app
  • ¥15 解riccati方程组
  • ¥15 使用rabbitMQ 消息队列作为url源进行多线程爬取时,总有几个url没有处理的问题。