задний фон
В тот момент, когда облачная разработка находится в самом разгаре, я полагаю, что многие люди слышали о Kubernetes/etcd и т. д. Когда мы смотрим на его исходный код или проводим вторичную разработку, мы можем обнаружить, что он использует библиотеку командной строки Cobra, которая Артефакт для написания командных строк, обеспечивающий основу для быстрого создания фреймворков приложений на основе Cobra.
Его автор - очень известный spf13. Я думаю, что все знают о vim. Вы можете использовать конечный терминал vim spf13-vim, который можно настроить одним щелчком мыши, что очень удобно. Его другие работы viper - это полное решение для настройки. Он поддерживает конфигурационные файлы, такие как JSON/YAML/TOML/HCL/envFile, а также горячая загрузка, сохранение конфигурации и т. д. Hugo — это тоже его работа.
Мы можем использовать Cobra для быстрой разработки нужных нам инструментов командной строки, что очень удобно и быстро.
Две функциональные характеристики
- Простой режим подкомандной строки, такой как сервер приложений, выборка приложений и т. д.
- Полностью совместим с режимом командной строки POSIX.
- вложенная подкоманда
- Поддержка глобальных, локальных, составных флагов
- Используйте Cobra для простого создания приложений и команд, используйте cobra create appname и cobra add cmdname
- Если вы введете неправильную команду, будут предоставлены интеллектуальные предложения, такие как сервер приложений, вам будет предложено сервер приложений, нет ли сервер приложений
- Автоматически генерировать справочную информацию для команд и флагов
- Автоматически создавать подробную справочную информацию, например справку по приложению.
- Автоматически распознавать флаг -h, --help help
- Автоматически генерировать автозавершение команды приложения под bash
- Автоматически генерировать справочные страницы для приложений
- псевдоним командной строки
- Настройка справки и информации об использовании
- Дополнительные плотно интегрированные приложения Viper
3 Используйте Cobra
3.1 Установка
Установка Cobra очень проста, вы можете использовать Go Get, чтобы получить его, после завершения установки, откройте каталог GOPATH, каталог BIN должен был скомпилировать Cobra, конечно, вы также можете использовать исходную компиляцию и установку.
Нужно знать три концепции перед использованием Cobra, которая также есть три части командной строки, командования, флагом и args
- Командовать какой-то основной информацией о себе, по команде сказала, что конкретный объект является Cobra.command
- Некоторые флаги или параметры команды, представленные флагом, конкретным объектом является флаг.FlagSet
- Последний параметр, представленный Args, обычно [] String
Соответствует следующему примеру:
go get -u test.com/a/b
здесьget
Это обычное дело (здесь оно особенное),-u
это флаг,test.com/a/b
аргументы
3.2 Создание приложения
$ /Users/xuel/workspace/goworkspace/bin/cobra init --pkg-name smartant-cli
Your Cobra application is ready at
/Users/xuel/workspace/goworkspace/src/github.com/kaliarch/smartant-cli
$ ls
LICENSE cmd go.mod go.sum main.go
$ tree
.
├── LICENSE
├── cmd
│ └── root.go
├── go.mod
├── go.sum
└── main.go
1 directory, 5 files
3.3 Программа разработки cls
Создайте каталог imp в каталоге smartant-cli, перепишите файл utils.go и введите следующее:
package utils
import "fmt"
func Show(name string, age int) {
fmt.Printf("name is %s, age is %d", name, age)
}
- main.go
package main
import "github.com/kaliarch/smartant-cli/cmd"
func main() {
cmd.Execute()
}
Видно, что основная функция выполняет пакет cmd, поэтому нам нужно только вызвать пакет utils в пакете cmd, чтобы выполнить требования программы smartant-cli. Затем откройте файл root.go для просмотра:
- root.go
/*
Copyright © 2021 NAME HERE <EMAIL ADDRESS>
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package cmd
import (
"fmt"
"github.com/spf13/cobra"
"os"
homedir "github.com/mitchellh/go-homedir"
"github.com/spf13/viper"
)
var cfgFile string
// rootCmd represents the base command when called without any subcommands
var rootCmd = &cobra.Command{
Use: "smartant-cli",
Short: "SmartAnt linux agent cli",
Long: `
smartant-cli is a CLI for SmartAnt applications.
This application is a tool to migrations linux system.`,
// Uncomment the following line if your bare application
// has an action associated with it:
// Run: func(cmd *cobra.Command, args []string) { },
}
// 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() {
if err := rootCmd.Execute(); err != nil {
fmt.Println(err)
os.Exit(1)
}
}
func init() {
cobra.OnInitialize(initConfig)
// 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/.smartant-cli.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")
}
// initConfig reads in config file and ENV variables if set.
func initConfig() {
if cfgFile != "" {
// Use config file from the flag.
viper.SetConfigFile(cfgFile)
} else {
// Find home directory.
home, err := homedir.Dir()
if err != nil {
fmt.Println(err)
os.Exit(1)
}
// Search config in home directory with name ".smartant-cli" (without extension).
viper.AddConfigPath(home)
viper.SetConfigName(".smartant-cli")
}
viper.AutomaticEnv() // read in environment variables that match
// If a config file is found, read it in.
if err := viper.ReadInConfig(); err == nil {
fmt.Println("Using config file:", viper.ConfigFileUsed())
}
}
Из исходного кода пакет cmd выполняет некоторые операции инициализации и предоставляет интерфейс Execute. Все очень просто, где viper это библиотека, читаемая интегрированным конфигурационным файлом кобры, здесь он не нужен, его можно закомментировать (приложение, которое может быть сгенерировано без комментирования, составляет около 10М, лучше его закомментировать, если оно здесь не используется). Все команды кобры реализованы через структуру cobra.Command. Чтобы реализовать функциональность smartant-cli, очевидно, нам нужно изменить RootCmd. Модифицированный код выглядит следующим образом:
/*
Copyright © 2021 NAME HERE <EMAIL ADDRESS>
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package cmd
import (
"fmt"
"github.com/spf13/cobra"
//"github.com/spf13/viper"
"github.com/kaliarch/cobra-demo/utils"
"os"
)
var cfgFile string
//var name string
//var age int
var command string
// rootCmd represents the base command when called without any subcommands
var rootCmd = &cobra.Command{
Use: "cobra-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) {
//if len(name) == 0 {
// cmd.Help()
// return
//}
//imp.Show(name, age)
if len(command) == 0 {
cmd.Help()
return
}
utils.Cmd(command)
},
}
// 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() {
if err := rootCmd.Execute(); err != nil {
fmt.Println(err)
os.Exit(-1)
}
}
func init() {
//cobra.OnInitialize(initConfig)
// 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/.smartant-agent.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")
//rootCmd.PersistentFlags().StringVarP(&name, "name", "n", "", "person name")
//rootCmd.PersistentFlags().IntVarP(&age, "age", "a", 0, "person age")
rootCmd.PersistentFlags().StringVarP(&command, "command", "o", "", "execute command context")
}
// initConfig reads in config file and ENV variables if set.
//func initConfig() {
// if cfgFile != "" {
// // Use config file from the flag.
// viper.SetConfigFile(cfgFile)
// } else {
// // Find home directory.
// home, err := homedir.Dir()
// if err != nil {
// fmt.Println(err)
// os.Exit(1)
// }
//
// // Search config in home directory with name ".cobra-demo" (without extension).
// viper.AddConfigPath(home)
// viper.SetConfigName(".cobra-demo")
// }
//
// viper.AutomaticEnv() // read in environment variables that match
//
// // If a config file is found, read it in.
// if err := viper.ReadInConfig(); err == nil {
// fmt.Println("Using config file:", viper.ConfigFileUsed())
// }
//}
3.4 Исполнение
# 编译
$ go build -o smartant-cli
$ ./smartant-cli
smartant-cli is a CLI for SmartAnt applications.
This application is a tool to migrations linux system.
Usage:
smartant-cli [flags]
Flags:
-a, --age int persons age
-h, --help help for smartant-cli
-n, --name string persons name
$ ./smartant-cli -a 11 -n "xuel"
name is xuel, age is 11%
CLIS достигается с четырьмя подпрограммами
После выполнения демонстрационного примера инициализации cobra.exe продолжайте использовать cobra для добавления подкоманды test для демонстрационного примера:
4.1 Создать подкоманду sysinfo
$ /Users/xuel/workspace/goworkspace/bin/cobra add sysinfo
sysinfo created at /Users/xuel/workspace/goworkspace/src/github.com/kaliarch/smartant-cli
$ tree
.
├── LICENSE
├── cmd
│ ├── root.go
│ └── sysinfo.go
├── go.mod
├── go.sum
├── main.go
├── smartant-cli
└── utils
└── utils.go
4.2 Просмотр подкоманд
$ go build -o smartant-cli
$ ./smartant-cli
smartant-cli is a CLI for SmartAnt applications.
This application is a tool to migrations linux system.
Usage:
smartant-cli [flags]
smartant-cli [command]
Available Commands:
help Help about any command
sysinfo A brief description of your command
Flags:
-a, --age int persons age
-h, --help help for smartant-cli
-n, --name string persons name
Use "smartant-cli [command] --help" for more information about a command.
$ ./smartant-cli sysinfo -h
A longer description that spans multiple lines and likely contains examples
and usage of using your command. 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:
smartant-cli sysinfo [flags]
Flags:
-h, --help help for sysinfo
4.3 Написание подкоманд
- sysinfo.go
/*
Copyright © 2021 NAME HERE <EMAIL ADDRESS>
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package cmd
import (
"fmt"
"github.com/kaliarch/smartant-cli/utils"
"github.com/spf13/cobra"
)
var (
host, pwd, username string
port int
command string
)
// sysinfoCmd represents the sysinfo command
var sysinfoCmd = &cobra.Command{
Use: "sysinfo",
Short: "check sys info message",
Long: `A longer description that spans multiple lines and likely contains examples
and usage of using your command. 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.`,
Run: func(cmd *cobra.Command, args []string) {
if len(host) == 0 || len(pwd) == 0 {
cmd.Help()
return
}
fmt.Println("sysinfo called")
utils.Sysinfo(host, pwd, username, port, command)
fmt.Println("sysinfo called commpled")
},
}
func init() {
rootCmd.AddCommand(sysinfoCmd)
// Here you will define your flags and configuration settings.
// Cobra supports Persistent Flags which will work for this command
// and all subcommands, e.g.:
// sysinfoCmd.PersistentFlags().String("foo", "", "A help for foo")
// Cobra supports local flags which will only run when this command
// is called directly, e.g.:
// sysinfoCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle")
sysinfoCmd.Flags().StringVarP(&host, "host", "i", "", "host ip addr")
sysinfoCmd.Flags().StringVarP(&username, "username", "u", "", "host username")
sysinfoCmd.Flags().StringVarP(&command, "command", "c", "", "command")
sysinfoCmd.Flags().StringVarP(&pwd, "pwd", "p", "", "host password")
sysinfoCmd.Flags().IntVarP(&port, "port", "P", 0, "host port")
}
- utils.go
package utils
import (
"bytes"
"fmt"
"golang.org/x/crypto/ssh"
"net"
"strings"
//"strconv"
"log"
)
// smartant-cli
func Show(name string, age int) {
fmt.Printf("name is %s, age is %d", name, age)
}
func sshConnect(user, pwd, host string, port int) (*ssh.Session, error) {
var (
auth []ssh.AuthMethod
addr string
clientConfig *ssh.ClientConfig
client *ssh.Client
session *ssh.Session
err error
)
// get auth method
auth = make([]ssh.AuthMethod, 0)
auth = append(auth, ssh.Password(pwd))
// host key callbk
hostKeyCallbk := func(host string, remote net.Addr, key ssh.PublicKey) error {
return nil
}
clientConfig = &ssh.ClientConfig{
User: user,
Auth: auth,
HostKeyCallback: hostKeyCallbk,
BannerCallback: nil,
//ClientVersion: "",
//HostKeyAlgorithms: nil,
//Timeout: 10000000,
}
// connet to ssh
addr = fmt.Sprintf("%s:%d", host, port)
if client, err = ssh.Dial("tcp", addr, clientConfig); err != nil {
return nil, err
}
// create session
if session, err = client.NewSession(); err != nil {
return nil, err
}
return session, nil
}
func Sysinfo(host, pwd, username string, port int, cmd string) {
var stdOut, stdErr bytes.Buffer
// 使用用户名,密码登陆
session, err := sshConnect(username, pwd, host, port)
if err != nil {
log.Fatal(err)
}
defer session.Close()
session.Stdout = &stdOut
session.Stderr = &stdErr
session.Run(cmd)
fmt.Println(strings.Replace(stdOut.String(), "\n", " ", -1))
}
- выполнить тест
$ ./smartant-cli sysinfo
A longer description that spans multiple lines and likely contains examples
and usage of using your command. 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:
smartant-cli sysinfo [flags]
Flags:
-c, --command string command
-h, --help help for sysinfo
-i, --host string host ip addr
-P, --port int host port
-p, --pwd string host password
-u, --username string host username
$ ./smartant-cli sysinfo -i 121.3.10.55 -u root -P 22 -p xxxxxxx -c "cat /etc/hosts"
sysinfo called
::1 localhost localhost.localdomain localhost6 localhost6.localdomain6 127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4 127.0.0.1 localhost localhost 127.0.0.1 hw-server hw-server
sysinfo called commpled
5 других
Cobra очень мощна и может помочь нам быстро создавать инструменты командной строки быстро, но если мы просто напишем очень простой инструмент командной строки, есть очень мало вариантов флага, а встроенная библиотека флага встроенного Golang. Конечно, использование зависит от личного выбора, Cobra более подходит для сложных инструментов командной строки.