2024-07-12
한어Русский языкEnglishFrançaisIndonesianSanskrit日本語DeutschPortuguêsΕλληνικάespañolItalianoSuomalainenLatina
Lorsque j'ai ouvert le code de k8s, j'ai découvert que les services principaux utilisaient la bibliothèque cobra comme capacité de traitement en ligne de commande.Par conséquent, afin d'avoir une compréhension plus approfondie de l'apprentissage du code derrière le code, écrivons d'abord une démo basée sur cette bibliothèque pour approfondir notre compréhension de cette bibliothèque.
Github :GitHub - spf13/cobra : un commandant pour les interactions modernes avec Go CLI Voilà, Cobra est un outil en ligne de commande implémenté en langage Go. Et il est désormais utilisé par de nombreux projets, comme Kubernetes, Hugo et Github CLI, etc.En utilisant Cobra, nous pouvons créer rapidement des outils en ligne de commande, particulièrement adaptés à l'écriture测试脚本
, diverses prestations Admin CLI
attendez.
En raison des paramètres de ligne de commande, Golang lui-même est livré avec la bibliothèque "flag". Comment utiliser la bibliothèque flag ?
- flag.Parse()
-
- args := flag.Args()
Après analyse, chaque commande doit être jugée, ce qui est très gênant.
Mais lorsque nous l'utilisons, nous devons effectuer diverses analyses et jugements sur la ligne de commande, mais avec cette bibliothèque, nous pouvons réduire ce code redondant.
Sans plus tarder, expliquons directement comment utiliser ce projet. Mon environnement est sur Macos.
Exécution en ligne de commande
go get -u github.com/spf13/cobra@latest
$ go install github.com/spf13/cobra-cli@latest
Parce que j'ai déjà construit le répertoire bin dans mon chemin de code golang, donc après avoir exécuté cette commande, c'est comme suit
Nous avons vu le fichier exécutable de cobra-cli.
Ici, nous pouvons utiliser cette chose dans la commande pour l'initialiser.Les étapes collectives sont les suivantes
- xxx@MBP src % mkdir greet
- xxx@MBP src % cd greet
- xxx@MBP test % ls
- xxx@MBP greet % cobra-cli init
- Error: Please run `go mod init <MODNAME>` before `cobra-cli init`
- xxx@MBP greet % go mod init greet
- go: creating new go.mod: module greet
- xxx@MBP greet % ls
- go.mod
- xxx@MBP greet % cobra-cli init
- Your Cobra application is ready at
- /Users/XXX/workspace/golang/src/greet
- xxx@MBP greet % ls
- LICENSE cmd go.mod go.sum main.go
- xxx@MBP greet %
La première étape consiste à créer un répertoire de test, puis à exécuter go mod init test, puis à exécuter la ligne de commande cobra-cli init, et le fichier d'échafaudage sera généré.
Les fichiers suivants seront générés dans le répertoire :
- main.go cmd LICENSE go.mod go.sum
- ├── LICENSE
- ├── cmd
- │ └── root.go
- └── main.go
- go.mod
- go.sum
Le fichier qui vient d'être généré peut ne pas être d'une grande utilité car il n'y a pas d'options de commande spécifiques, nous continuons donc à exécuter et à ajouter un mot de commande
cobra-cli add [command]
De cette façon, il générera un autre fichier.
Par exemple, exécutez
cobra-cli ajouter salutation
- // Package cmd /*
- package cmd
-
- import (
- "fmt"
-
- "github.com/spf13/cobra"
- )
-
- // greetCmd represents the greet command
- var greetCmd = &cobra.Command{
- Use: "greet",
- Short: "A brief description of your command",
- 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(args) < 1 {
- cmd.Help()
- return
- }
- name := args[0]
- fmt.Println("greet called:", name)
- },
- }
-
- func init() {
- rootCmd.AddCommand(greetCmd)
-
- // Here you will define your flags and configuration settings.
-
- // Cobra supports Persistent Flags which will work for this command
- // and all subcommands, e.g.:
- // greetCmd.PersistentFlags().String("foo", "", "A help for foo")
-
- // Cobra supports local flags which will only run when this command
- // is called directly, e.g.:
- greetCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle")
- }
Par conséquent, nous pouvons voir que la commande greet a été ajoutée.
Ensuite, nous le compilons et générons le fichier cible, puis nous exécutons ce qui suit
- ./greet
-
- 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:
- greet [command]
-
- Available Commands:
- completion Generate the autocompletion script for the specified shell
- greet A brief description of your command
- help Help about any command
- mockMsg A brief description of your command
-
- Flags:
- -h, --help help for greet
- -t, --toggle Help message for toggle
-
- Use "greet [command] --help" for more information about a command.
-
D'après le contenu renvoyé ci-dessus, nous pouvons voir qu'il existe une sous-commande gree supplémentaire.
Et vous pouvez ajouter un indicateur, tel que -h
Le Run ci-dessus peut contenir la logique métier que nous souhaitons traiter.
Si nous voulons ajouter des valeurs d'indicateur, il nous suffit d'ajouter le code suivant lors de l'exécution
- g, _ := cmd.Flags().GetInt32("goroutine")
- p, _ := cmd.Flags().GetInt32("packet")
- fmt.Println("mockmsg called,flags:g=", g, ",p=", p, ",args:", args)
Par exemple, nous mettons en œuvre ce qui suit :
- Run: func(cmd *cobra.Command, args []string) {
- if len(args) < 1 {
- cmd.Help()
- return
- }
- name := args[0]
- fmt.Println("greet called:", name)
-
- g, _ := cmd.Flags().GetInt32("goroutine")
- p, _ := cmd.Flags().GetInt32("packet")
- fmt.Println("mockmsg called,flags:g=", g, ",p=", p, ",args:", args)
- },
De cette façon, il peut être utilisé comme ceci
- ./greet greet xx -p 10 -g 100
- greet called: xx
- greetCmd called,flags:g= 100 ,p= 10 ,args: [xx]
-
J'ai principalement regardé le code du module kubctl, et j'ai trouvé que ce module a une encapsulation plus riche de cmd pour prendre en charge des scénarios plus complexes.
Parmi eux, nous partons du principal de kubectl
une méthode de saisie
- // NewDefaultKubectlCommand creates the `kubectl` command with default arguments
- func NewDefaultKubectlCommand() *cobra.Command {
- ioStreams := genericiooptions.IOStreams{In: os.Stdin, Out: os.Stdout, ErrOut: os.Stderr}
- return NewDefaultKubectlCommandWithArgs(KubectlOptions{
- PluginHandler: NewDefaultPluginHandler(plugin.ValidPluginFilenamePrefixes),
- Arguments: os.Args,
- ConfigFlags: defaultConfigFlags().WithWarningPrinter(ioStreams),
- IOStreams: ioStreams,
- })
- }
Étant donné que kubectl peut traiter des fichiers et des indicateurs, divers paramètres doivent être définis pour cette situation. Nous avons constaté que chaque champ de la structure cmd a été pleinement utilisé.
Ces deux méthodes constituent les méthodes principales, qui sont essentiellement initialisées et affectées à la structure de commande.
- // NewDefaultKubectlCommandWithArgs creates the `kubectl` command with arguments
- func NewDefaultKubectlCommandWithArgs(o KubectlOptions) *cobra.Command {
- cmd := NewKubectlCommand(o)
Parmi eux, NewKubectlCommand est utilisé pour les nouvelles instances cmd.
- func NewKubectlCommand(o KubectlOptions) *cobra.Command {
- warningHandler := rest.NewWarningWriter(o.IOStreams.ErrOut, rest.WarningWriterOptions{Deduplicate: true, Color: term.AllowsColorOutput(o.IOStreams.ErrOut)})
- warningsAsErrors := false
- // Parent command to which all subcommands are added.
- cmds := &cobra.Command{
- Use: "kubectl",
C'est là que nous voyons l'utilisation des commandes kubectl. Parce que cet article parle principalement de l'utilisation de la commande, nous n'entrerons pas dans les détails des autres commandes get de k8, j'en parlerai dans le prochain article.
Vous trouverez ci-dessous une explication détaillée des champs spécifiques liés au commandement.
以下是对 `Command` 结构体中每个字段的详细解释:
- 1. `Use`:这是一个字符串,用于描述命令的基本使用方式。它规定了命令所需的参数和可选参数的格式,为用户提供了简洁明了的使用指导。
- - 例如:`"add [-F file | -D dir]... [-f format] profile"` 表示 `add` 命令可以有可选的 `-F` 和 `-D` 参数,其中 `-F` 后跟一个文件,`-D` 后跟一个目录,这两个参数是互斥的,并且可以多次出现,还有一个可选的 `-f` 参数后跟格式信息,最后需要一个 `profile` 参数。
-
- 2. `Aliases`:一个字符串切片,存储了该命令的别名。这使得用户可以通过不同的名称来调用同一个命令,增加了命令使用的灵活性。
- - 比如:`["add_item", "insert"]` 是 `add` 命令的别名。
-
- 3. `SuggestFor`:也是一个字符串切片,其中包含了此命令可能被建议替代的其他命令名称。这有助于在用户输入类似但不完全准确的命令时提供相关的建议。
-
- 4. `Short`:一个简短的字符串,用于在帮助输出中提供命令的简短描述,让用户快速了解命令的主要功能。
- - 例如:"添加新的项目"
-
- 5. `GroupID`:指定该子命令在其父命令的“帮助”输出中所属的组标识,便于对命令进行分组展示和管理。
-
- 6. `Long`:详细的长字符串,在“帮助 <此命令>”输出中提供更全面和深入的命令描述,包括更多的功能细节、使用示例、注意事项等。
-
- 7. `Example`:包含命令使用的示例字符串,通过实际的例子帮助用户更好地理解如何正确使用该命令。
-
- 8. `ValidArgs`:一个字符串切片,列出了在外壳自动补全中所有有效的非标志参数。
-
- 9. `ValidArgsFunction`:一个函数,动态地提供有效的非标志参数用于外壳自动补全,是一种更灵活的参数提供方式。
-
- 10. `Args`:定义了预期的参数的相关规则和处理方式。
-
- 11. `ArgAliases`:一个字符串切片,列出了有效参数的别名,这些别名不会在外壳自动补全中被提示,但手动输入时会被接受。
-
- 12. `BashCompletionFunction`:用于传统 Bash 自动补全生成器的自定义 Bash 函数,为特定的 Bash 环境提供定制的自动补全功能。
-
- 13. `Deprecated`:如果命令已被弃用,存储了使用该命令时将显示的提示信息,告知用户该命令不应再被使用。
-
- 14. `Annotations`:一个键值对映射,允许应用程序为命令添加自定义的标识、分组或特殊选项等元数据。
-
- 15. `Version`:存储命令的版本信息,用于版本控制和显示。
-
- 16. 各种 `Run` 函数:
- - `PersistentPreRun` 和 `PersistentPreRunE`:在命令执行前被调用,且子命令会继承并执行,用于进行一些持久的预处理操作。
- - `PreRun` 和 `PreRunE`:在命令执行前被调用,但子命令不会继承,用于特定于当前命令的预处理。
- - `Run` 和 `RunE`:实际的工作函数,实现命令的主要逻辑。
- - `PostRun` 和 `PostRunE`:在 `Run` 函数执行后被调用,用于进行后续的处理操作。
-
- 17. `commandgroups`:一个指针切片,指向子命令所属的组对象。
-
- 18. `args`:实际从标志解析得到的参数切片。
-
- 19. `flagErrorBuf`:一个字节缓冲区,用于存储来自 `pflag` 的错误消息。
-
- 20. `flags`:一个 `flag.FlagSet` 对象,包含了所有的标志。
-
- 21. `pflags`:存储持久的标志。
-
- 22. `lflags`:本地标志的缓存,用于优化 `LocalFlags` 函数调用。
-
- 23. `iflags`:继承的标志的缓存,用于优化相关函数调用。
-
- 24. `parentsPflags`:父命令的所有持久标志。
-
- 25. `globNormFunc`:一个全局的标准化函数,用于处理标志名称的标准化。
-
- 26. `usageFunc`:用户定义的使用函数,用于自定义命令的使用说明。
-
- 27. `usageTemplate`:用户定义的使用模板。
-
- 28. `flagErrorFunc`:用户定义的标志错误处理函数。
-
- 29. `helpTemplate`:用户定义的帮助模板。
-
- 30. `helpFunc`:用户定义的帮助函数。
-
- 31. `helpCommand`:具有“帮助”用途的命令,如果用户未定义,则使用默认的帮助命令。
-
- 32. `helpCommandGroupID`:帮助命令所属的组标识。
-
- 33. `completionCommandGroupID`:自动完成命令所属的组标识。
-
- 34. `versionTemplate`:用户定义的版本模板。
-
- 35. `errPrefix`:用户定义的错误消息前缀。
-
- 36. `inReader`:用户定义的输入读取器,替代标准输入。
-
- 37. `outWriter`:用户定义的输出写入器,替代标准输出。
-
- 38. `errWriter`:用户定义的错误输出写入器,替代标准错误输出。
-
- 39. `FParseErrWhitelist`:要忽略的标志解析错误的列表。
-
- 40. `CompletionOptions`:用于控制外壳自动完成的选项。
-
- 41. `commandsAreSorted`:一个布尔值,指示命令切片是否已排序。
-
- 42. `commandCalledAs`:一个结构体,记录命令被调用时的名称和是否被调用的状态。
-
- 43. `ctx`:上下文对象,用于传递和管理命令执行的上下文信息。
-
- 44. `commands`:一个指针切片,包含此命令支持的子命令。
-
- 45. `parent`:指向该命令的父命令的指针。
-
- 46. `Max lengths` 相关字段:记录命令相关字符串的最大长度,用于格式化和展示。
-
- 47. `TraverseChildren`:一个布尔值,决定是否在执行子命令之前解析所有父命令的标志。
-
- 48. `Hidden`:如果为真,该命令将在可用命令列表中隐藏,不向用户显示。
-
- 49. `SilenceErrors`:一个布尔值,用于控制是否静默处理错误。
-
- 50. `SilenceUsage`:一个布尔值,用于控制在发生错误时是否静默使用信息。
-
- 51. `DisableFlagParsing`:如果为真,将禁用标志解析,所有标志将作为参数传递给命令。
-
- 52. `DisableAutoGenTag`:如果为真,在生成文档时将禁用自动生成的标签。
-
- 53. `DisableFlagsInUseLine`:如果为真,将在使用行中禁用标志的添加。
-
- 54. `DisableSuggestions`:如果为真,将禁用基于编辑距离的建议功能。
-
- 55. `SuggestionsMinimumDistance`:定义显示建议的最小编辑距离,必须大于 0 。
Cet article est principalement une explication étape par étape de la façon d'utiliser la bibliothèque cobra. Lorsque nous utilisons cette bibliothèque, nous pouvons mieux comprendre son principe de fonctionnement, puis nous baser sur la façon d'utiliser les k8 spécifiques et l'utilisation de champs spécifiques. exploiter pleinement les capacités et la valeur de cmd