一、简介
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"