Golang 中使用 Cobra 创建 CLI 应用

一、简介

github : https://github.com/spf13/cobra
推荐参考文档 : https://juejin.cn/post/6924541628031959047

  • Cobra 是一个 Go 语言开发的命令行(CLI)框架,它提供了简洁、灵活且强大的方式来创建命令行程序。它包含一个用于创建命令行程序的库(Cobra 库),以及一个用于快速生成基于 Cobra 库的命令行程序工具(Cobra 命令)。Cobra 是由 Go 团队成员 spf13 为 Hugo 项目创建的,并已被许多流行的 Go 项目所采用,如 Kubernetes、Helm、Docker (distribution)、Etcd 等。

二、概念

  • Cobra 是构建在命令、参数和标识符之上的 :
    • Commands 表示执行动作
    • Args 表示执行参数
    • Flags 表示这些动作的标识符
  • 基本的执行命令如下 :
$ APPNAME Command Args --Flags
# 或者
$ APPNAME Command --Flags Args
  • 比如我们平时使用的一些命令行工具:
git clone URL -bare
go get -u URL
npm install package –save
kubectl get pods -n kube-system -l app=cobra

三、示例

3.1、初始化

  • 1、新建项目并初始化 modules
$ mkdir demo-cobra    
$ go mod init demo-cobra    
  • 2、安装cobra
# 推荐配置代理
$ export GOPROXY=https://goproxy.cn
$ go get -u github.com/spf13/cobra@latest
$ go install github.com/spf13/cobra-cli@latest

1
2
  • 3、使用 cobra init appname 和 cobra add cmdname 轻松生成应用程序和命令
$ cobra-cli init demo      
Your Cobra application is ready at
/Users/daizhe/Desktop/myself/k8s-operator/basic/demo-cobra/demo

.
└── demo-cobra
    ├── demo
    │   ├── LICENSE
    │   ├── cmd
    │   │   └── root.go
    │   └── main.go
    ├── go.mod
    └── go.sum

  • 4、 main.go 是 CLI 应用的入口,在 main.go 里面调用好了 cmd/root.go 下面的 Execute 函数
/*
Copyright © 2024 NAME HERE <EMAIL ADDRESS>
*/
package main

import "demo-cobra/demo/cmd"

func main() {
	cmd.Execute()
}

3.2、rootCmd

  • root (根) 命令就是Cli工具的最基本的命令,比如对于 go get URL 来说,其中 go 就是root命令,而get就是go这个根命令的子命令,而在 root.go 中就直接使用了 cobra 命令来初始化了 Cmd 结构,Cli中的其他所有命令都是 rootCmd 这个根命令的子命令了。
  • 将 cmd/root.go 里面的 rootCmd 变量内部的注释去掉,并在 Run 函数里面加上一句 fmt.Println(“Hello Cobra CLI”) :
/*
Copyright © 2024 NAME HERE <EMAIL ADDRESS>
*/
package cmd

import (
	"fmt"
	"os"

	"github.com/spf13/cobra"
)

// rootCmd represents the base command when called without any subcommands
var rootCmd = &cobra.Command{
	Use:   "demo",
	Short: "A brief description of your application",
	Long: `A longer description that spans multiple lines and likely contains
examples and usage of using your application. For example:

Cobra is a CLI library for Go that empowers applications.
This application is a tool to generate the needed files
to quickly create a Cobra application.`,
	// Uncomment the following line if your bare application
	// has an action associated with it:
	// Run: func(cmd *cobra.Command, args []string) { },

	//
	Run: func(cmd *cobra.Command, args []string) {
		fmt.Println("Hello Cobra CLI")
	},
}

// Execute adds all child commands to the root command and sets flags appropriately.
// This is called by main.main(). It only needs to happen once to the rootCmd.
func Execute() {
	err := rootCmd.Execute()
	if err != nil {
		os.Exit(1)
	}
}

func init() {
	// Here you will define your flags and configuration settings.
	// Cobra supports persistent flags, which, if defined here,
	// will be global for your application.

	// rootCmd.PersistentFlags().StringVar(&cfgFile, "config", "", "config file (default is $HOME/.demo-cobra.yaml)")

	// Cobra also supports local flags, which will only run
	// when this action is called directly.
	rootCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle")
}
  • 在项目根目录下面执行如下命令进行构建并执行测试:
$ go build -o demo                                                   
$ ./demo       
Hello Cobra CLI

$ ./demo -h 
A longer description that spans multiple lines and likely contains
examples and usage of using your application. For example:

Cobra is a CLI library for Go that empowers applications.
This application is a tool to generate the needed files
to quickly create a Cobra application.

Usage:
  demo [flags]

Flags:
  -h, --help     help for demo
  -t, --toggle   Help message for toggle

3.3、init

  • init 函数是 Golang 中初始化包的时候第一个调用的函数。
// cmd/root.go
func init() {
    fmt.Println("I'm inside init function in cmd/root.go")
    cobra.OnInitialize(initConfig)
    ...
}

func initConfig() {
    fmt.Println("I'm inside initConfig function in cmd/root.go")
    ...
}

// main.go
func main() {
     fmt.Println("I'm inside main function in main.go")
     cmd.Execute()
}
  • init 函数最后处理的就是 flags 了,Flags 就类似于命令的标识符,我们可以把他们看成是某种条件操作,在 Cobra 中提供了两种类型的标识符:Persistent Flags 和 Local Flags。
  • Persistent Flags: 该标志可用于为其分配的命令以及该命令的所有子命令。
    Local Flags: 该标志只能用于分配给它的命令。

3.4、新增命令 - 实现一个ssh

  • cmd/ssh.go
package cmd

import (
	"fmt"
	"github.com/spf13/cobra"
	"golang.org/x/crypto/ssh"
	"os"
)

var (
	host     string
	port     int
	user     string
	password string
	keyFile  string
	command  string
)

var sshCmd = &cobra.Command{
	Use:   "ssh",
	Short: "SSH to a server and run a command",
	Run: func(cmd *cobra.Command, args []string) {
		config := &ssh.ClientConfig{
			User: user,
			Auth: []ssh.AuthMethod{
				ssh.Password(password),
			},
			HostKeyCallback: ssh.InsecureIgnoreHostKey(),
		}

		addr := fmt.Sprintf("%s:%d", host, port)
		client, err := ssh.Dial("tcp", addr, config)
		if err != nil {
			fmt.Fprintf(os.Stderr, "failed to dial: %v\n", err)
			os.Exit(1)
		}
		defer client.Close()

		session, err := client.NewSession()
		if err != nil {
			fmt.Fprintf(os.Stderr, "failed to create session: %v\n", err)
			os.Exit(1)
		}
		defer session.Close()

		// Run the command and capture stdout and stderr
		output, err := session.CombinedOutput(command)
		if err != nil {
			fmt.Fprintf(os.Stderr, "failed to run command: %v\n", err)
			os.Exit(1)
		}

		fmt.Println(string(output))
	},
}

func init() {
	rootCmd.AddCommand(sshCmd)

	sshCmd.PersistentFlags().StringVar(&host, "host", "localhost", "SSH server host")
	sshCmd.PersistentFlags().IntVar(&port, "port", 22, "SSH server port")
	sshCmd.PersistentFlags().StringVar(&user, "user", "root", "SSH user name")
	sshCmd.PersistentFlags().StringVar(&password, "password", "", "SSH user password")
	sshCmd.PersistentFlags().StringVar(&keyFile, "key", "", "SSH private key file")
	sshCmd.PersistentFlags().StringVar(&command, "command", "uptime", "Command to run on SSH server")
}
dzcli ssh --host example.com --port 22 --user root --password yourpassword --command "ls"
  • 4
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值