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
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 nginx中的CORS策略应该如何配置
  • ¥30 信号与系统实验:采样定理分析
  • ¥100 我想找人帮我写Python 的股票分析代码,有意请加mathtao
  • ¥20 Vite 打包的 Vue3 组件库,图标无法显示
  • ¥15 php 同步电商平台多个店铺增量订单和订单状态
  • ¥15 关于logstash转发日志时发生的部分内容丢失问题
  • ¥17 pro*C预编译“闪回查询”报错SCN不能识别
  • ¥15 微信会员卡接入微信支付商户号收款
  • ¥15 如何获取烟草零售终端数据
  • ¥15 数学建模招标中位数问题