背景
在云如火如荼的当下,相信很多人都听说过Kubernetes/etcd等。当我们看它的源代码或者重新开发时,可以发现它们都使用了命令行库Cobra,这是一个编写命令行的神器,提供了一个快速生成基于Cobra的应用框架的脚手架。
它的作者是一个非常著名的spf13。相信大家对vim都有所了解。可以用vim的终极终端SPF13-vim,一键配置,非常方便。其work viper是一套完整的配置解决方案,支持JSON/YAML/TOML/HCL/envFile等配置文件,还可以热加载、配置和保存。雨果也是他的作品。
我们可以使用Cobra快速开发我们想要的命令行工具,非常方便快捷。
两个功能特征
简单的子命令行模式,如app server、app fetch等。
与posix命令行模式兼容
嵌套子命令子命令
支持全局、本地和串行标志
使用Cobra轻松生成应用程序和命令,使用cobra create appname和cobra add cmdname。
如果命令输入错误,会提供智能建议,比如app srver,会提示srver是否没有命令,是否是app server。
自动生成命令和标志的帮助信息。
自动生成详细的帮助信息,比如app帮助。
自动识别-h,- help帮助标志
bash下自动生成应用命令的自动完成功能
自动生成应用手册
命令行别名
自定义帮助和使用信息
可选的紧密集成的viper应用
使用眼镜蛇三次
3.1安装
Cobra的安装非常简单,你可以使用go get来获得它。安装完成后,打开GOPATH目录。bin目录下应该有编译好的Cobra,当然也可以用源代码编译安装。
在使用cobra之前,你需要知道三个概念,也是命令行的三个部分,command,flag和args。
命令本身的一些基本信息,用命令来表达,就是cobra。命令
命令的一些标志或选项用flag表示,具体对象是flag。标志集
最后一个参数,用args表示,通常是[]string。
相应的例子如下:
去找test.com/a/b吧
复制代码
Get here是commond (special here),-u是flag,test.com/a/b是args。
3.2生成应用程序
$/Users/xuel/workspace/goworkspace/bin/cobra init-pkg-name smartant-CLI
您的Cobra应用程序已准备就绪
/Users/xuel/workspace/goworkspace/src/github . com/kali arch/smartant-CLI
$ ls
许可证cmd go.mod go.sum main.go
$树
。
├──许可证
├── cmd
│ └── root.go
├──围棋网
├──围棋. sum
└──大街。去
1个目录,5个文件
复制代码
3.3设计cls程序
在smartant-cli目录中创建一个imp目录,并重写utils.go文件,如下所示
包装效用
导入“fmt”
func Show(name string,age int) {
fmt。Printf("姓名是%s,年龄是%d ",姓名,年龄)
}
复制代码
main.go
主包装
导入“github . com/kali arch/smartant-CLI/cmd”
func main() {
cmd。执行()
}
复制代码
可以看到,main函数执行的是cmd包,所以我们只需要在cmd包内调用utils包就可以实现smartant-cli程序的要求。然后打开root.go文件进行查看:
root.go
/*
版权所有2021名称在此处
根据Apache许可证2.0版许可(“许可证”);
除非符合许可证的规定,否则您不得使用本文件。
您可以从以下网址获得许可证的副本
http://www.apache.org/licenses/LICENSE-2.0
除非适用法律要求或书面同意,软件
在许可证下分发是在“原样”的基础上分发的,
没有任何明示或暗示的保证或条件。
有关管理权限和的特定语言,请参见许可证
许可证下的限制。
*/
包装cmd
导入(
" fmt "
" github.com/spf13/cobra "
"操作系统"
homedir " github . com/Mitchell h/go-homedir "
" github.com/spf13/viper "
)
var cfgFile字符串
//在没有任何子命令的情况下调用时,rootCmd表示基本命令
var rootCmd = &cobra。命令{
使用:“smartant-cli”,
简称:“SmartAnt linux代理cli”,
长: `长
smartant-cli是用于smartant应用程序的cli。
这个应用程序是一个移植linux系统的工具,
//如果您的裸机应用程序
//有一个相关联的操作:
//Run:func(cmd * cobra。Command,args []string) { },
}
// Execute将所有子命令添加到根命令中,并相应地设置标志。
//这是由main.main()调用的。它只需要在rootCmd上发生一次。
函数执行(){
if err := rootCmd。执行();呃!=零{
fmt。Println(错误)
os。出口(1)
}
}
函数初始化(){
眼镜蛇。初始化(initConfig)
//在这里您将定义您的标志和配置设置。
// Cobra支持持久标志,如果在这里定义,
//对于您的应用程序将是全局的。
rootCmd。PersistentFlags()。StringVar(&cfgFile," config ","","配置文件(默认为$HOME/。smartant-cli.yaml)")
// Cobra也支持本地标志,它只会运行
//直接调用此动作时。
rootCmd。标志()。BoolP("toggle "," t ",false," toggle的帮助消息")
}
// initConfig读入配置文件和ENV变量(如果已设置)。
func initConfig() {
if cfgFile!= "" {
//使用标志中的配置文件。
毒蛇。SetConfigFile(cfgFile)
}否则{
//查找主目录。
home,err := homedir。目录()
如果err!=零{
fmt。Println(错误)
os。出口(1)
}
//在名为"的主目录中搜索配置。smartant-cli "(不带扩展名)。
毒蛇。AddConfigPath(主页)
毒蛇。SetConfigName("。smartant-cli”)
}
毒蛇。AutomaticEnv() //读入匹配的环境变量
//如果找到配置文件,则读入该文件。
如果err :=毒蛇。readin config();错误==零{
fmt。Println("使用配置文件:",viper。ConfigFileUsed())
}
}
复制代码
从源代码来看,cmd包执行一些初始化操作,并提供执行接口。很简单,这里viper是cobra的集成配置文件读取库。这里不需要用到,我们可以注释掉(不注释可能生成的应用大概10M左右,这里不用的话还是注释掉比较好)。cobra的所有命令都是通过结构cobra.Command实现的,为了实现smartant-cli功能,显然我们需要修改RootCmd。修改后的代码如下:
/*
版权所有2021名称在此处
根据Apache许可证2.0版许可(“许可证”);
除非符合许可证的规定,否则您不得使用本文件。
您可以从以下网址获得许可证的副本
http://www.apache.org/licenses/LICENSE-2.0
除非适用法律要求或书面同意,软件
在许可证下分发是在“原样”的基础上分发的,
没有任何明示或暗示的保证或条件。
有关管理权限和的特定语言,请参见许可证
许可证下的限制。
*/
包装cmd
导入(
" fmt "
" github.com/spf13/cobra "
//"github.com/spf13/viper "
" github . com/kali arch/cobra-demo/utils "
"操作系统"
)
var cfgFile字符串
//var名称字符串
//var age int
var命令字符串
//在没有任何子命令的情况下调用时,rootCmd表示基本命令
var rootCmd = &cobra。命令{
使用:“cobra-demo”,
简短:“对你的申请的简要描述”,
长:`跨越多行的较长描述,可能包含
使用你的应用程序的例子和用法。例如:
Cobra是一个用于Go的CLI库,支持应用程序。
这个应用程序是一个生成所需文件的工具
快速创建Cobra应用程序。
//如果您的裸机应用程序
//有一个相关联的操作:
//Run:func(cmd * cobra。Command,args []string) { },
Run: func(cmd *cobra。命令,args []string) {
//if len(name) == 0 {
//cmd。帮助()
//返回
//}
//imp。显示(姓名、年龄)
如果len(命令)== 0 {
cmd。帮助()
返回
}
utils。命令
},
}
// Execute将所有子命令添加到根命令中,并相应地设置标志。
//这是由main.main()调用的。它只需要在rootCmd上发生一次。
函数执行(){
if err := rootCmd。执行();呃!=零{
fmt。Println(错误)
os。退出(-1)
}
}
函数初始化(){
//眼镜蛇。初始化(initConfig)
//在这里您将定义您的标志和配置设置。
// Cobra支持持久标志,如果在这里定义,
//对于您的应用程序将是全局的。
rootCmd。PersistentFlags()。StringVar(&cfgFile," config ","","配置文件(默认为$HOME/。smartant-agent.yaml)")
// Cobra也支持本地标志,它只会运行
//直接调用此操作时。
//rootCmd。标志()。BoolP("toggle "," t ",false," toggle的帮助消息")
//rootCmd。PersistentFlags()。StringVarP(&name," name "," n "," person name ")
//rootCmd。PersistentFlags()。IntVarP(&age,"年龄"," a ",0,"人的年龄")
rootCmd。PersistentFlags()。StringVarP(&command," command "," o ","执行命令上下文")
}
// initConfig读入配置文件和ENV变量(如果已设置)。
//func initConfig() {
//if CFG file!= "" {
////使用标志中的配置文件。
//毒蛇。SetConfigFile(cfgFile)
//}其他{
////查找主目录。
//home,err := homedir。目录()
//if err!=零{
//fmt。Println(错误)
//OS。出口(1)
// }
//
////在名为"的主目录中搜索配置。cobra-demo”(无扩展)。
//毒蛇。AddConfigPath(主页)
//毒蛇。SetConfigName("。cobra-演示”)
// }
//
//毒蛇。AutomaticEnv() //读入匹配的环境变量
//
////如果找到了配置文件,则读入该文件。
//if err:= viper。readin config();错误==零{
//fmt。Println("使用配置文件:",viper。ConfigFileUsed())
// }
//}
复制代码
3.4执行
#编译
$ go build -o smartant-cli
$ ./smartant-cli
smartant-cli是用于smartant应用程序的cli。
这个应用程序是一个移植linux系统的工具。
用法:
smartant-CLI[标志]
标志:
-a,-年龄int人的年龄
-h,-help smartant-CLI的帮助
-n,- name字符串人名
$ ./smartant-cli -a 11 -n "xuel "
名字叫薛,年龄是11%
复制代码
4.用子命令实现CLI
执行cobra.exe初始化演示后,继续使用cobra为演示添加子命令测试:
4.1生成sysinfo子命令
$/Users/xuel/workspace/goworkspace/bin/cobra添加sysinfo
sysinfo创建于/Users/xuel/workspace/goworkspace/src/github . com/kali arch/smartant-CLI
$树
。
├──许可证
├── cmd
│ ├── root.go
│ └── sysinfo.go
├──围棋网
├──围棋. sum
├──大街。去
├──智能客户端
└──·尤蒂斯
└──·尤蒂尔斯去吧
复制代码
4.2查看子命令
$ go build -o smartant-cli
$ ./smartant-cli
smartant-cli是用于smartant应用程序的cli。
这个应用程序是一个移植linux系统的工具。
用法:
smartant-CLI[标志]
smartant-CLI[命令]
可用命令:
帮助关于任何命令的帮助
sysinfo命令的简要描述
标志:
-a,-年龄int人的年龄
-h,-help smartant-CLI的帮助
-n,- name字符串人名
有关命令的详细信息,请使用“smartant-cli [command] - help”。
$ ./smartant-cli sysinfo -h
跨越多行并可能包含示例的较长描述
和使用命令的用法。例如:
Cobra是一个用于Go的CLI库,支持应用程序。
这个应用程序是一个生成所需文件的工具
快速创建Cobra应用程序。
用法:
smartant-CLI sysinfo[标志]
标志:
-h,-help sysinfo的帮助
复制代码
4.3写子命令
sysinfo.go
/*
版权所有2021名称在此处
根据Apache许可证2.0版许可(“许可证”);
除非符合许可证的规定,否则您不得使用本文件。
您可以从以下网址获得许可证的副本
http://www.apache.org/licenses/LICENSE-2.0
除非适用法律要求或书面同意,软件
在许可证下分发是在“原样”的基础上分发的,
没有任何明示或暗示的保证或条件。
有关管理权限和的特定语言,请参见许可证
许可证下的限制。
*/
包装cmd
导入(
" fmt "
" github . com/kali arch/smartant-CLI/utils "
" github.com/spf13/cobra "
)
风险值(
主机、密码、用户名字符串
港口国际
命令字符串
)
// sysinfoCmd表示sysinfo命令
var sysinfoCmd = &cobra。命令{
使用:“sysinfo”,
简短:“检查系统信息消息”,
长:`跨越多行的较长描述,可能包含示例
和使用命令的用法。例如:
Cobra是一个用于Go的CLI库,支持应用程序。
这个应用程序是一个生成所需文件的工具
快速创建Cobra应用程序。
Run: func(cmd *cobra。命令,args []string) {
如果len(host) == 0 || len(pwd) == 0 {
cmd。帮助()
返回
}
fmt。Println("调用sysinfo ")
utils。Sysinfo(主机、密码、用户名、端口、命令)
fmt。Println("sysinfo called commpled ")
},
}
函数初始化(){
rootCmd。AddCommand(sysinfoCmd)
//在这里您将定义您的标志和配置设置。
// Cobra支持适用于此命令的永久标志
//以及所有子命令,例如:
// sysinfoCmd。PersistentFlags()。String("foo "," foo的帮助")
// Cobra支持本地标志,这些标志仅在以下情况下运行
//被直接调用,例如:
// sysinfoCmd。标志()。BoolP("toggle "," t ",false," toggle的帮助消息")
sysinfoCmd。标志()。StringVarP(&host," host "," I "," host ip addr ")
sysinfoCmd。标志()。StringVarP(&username," username "," u "," host username ")
sysinfoCmd。标志()。StringVarP(&command," command "," c "," command ")
sysinfoCmd。标志()。StringVarP(&pwd," pwd "," p ","主机密码")
sysinfoCmd。标志()。IntVarP(&port," port "," P ",0,"主机端口")
}
复制代码
utils.go
包装效用
导入(
"字节"
" fmt "
" golang.org/x/crypto/ssh "
“网络”
"字符串"
//"strconv "
"日志"
)
// smartant-cli
func Show(name string,age int) {
fmt。Printf("姓名是%s,年龄是%d ",姓名,年龄)
}
func sshConnect(用户,密码,主机字符串,端口整数)(*ssh。会话,错误){
风险值(
auth []ssh。认证方法
地址字符串
客户端配置*ssh。客户端配置
客户端*ssh。客户
会话*ssh。会议
err错误
)
//获取验证方法
auth = make([]ssh。AuthMethod,0)
auth = append(auth,ssh。密码(pwd))
//主机密钥调用bk
hostKeyCallbk := func(主机字符串,远程网络。地址,按键ssh。公钥)错误{
返回零
}
客户端配置= &ssh。客户端配置{
用户:用户,
Auth: auth,
HostKeyCallback: hostKeyCallbk,
BannerCallback:零,
//ClientVersion:" ",
//HostKeyAlgorithms: nil,
//超时:10000000,
}
//连接到ssh
addr = fmt。Sprintf("%s:%d ",主机,端口)
如果是客户端,err = ssh。Dial("tcp ",addr,client config);呃!=零{
返回零,错误
}
//创建会话
如果会话,err = client。new session();呃!=零{
返回零,错误
}
返回会话,零
}
func Sysinfo(主机、密码、用户名字符串、端口整数、命令字符串){
变量stdOut,stdErr字节。缓冲器
//使用用户名和密码登录
会话,错误:= sshConnect(用户名,密码,主机,端口)
如果err!=零{
日志。致命(错误)
}
推迟会话。关闭()
会话。标准输出= &标准输出
会话。标准错误= &标准错误
会话。运行(cmd)
fmt。Println(字符串。替换(标准输出。String()," \n "," ",-1))
}
复制代码
执行测试
$ ./smartant-cli sysinfo
跨越多行并可能包含示例的较长描述
以及使用命令的用法。例如:
Cobra是一个用于Go的CLI库,支持应用程序。
这个应用程序是一个生成所需文件的工具
快速创建Cobra应用程序。
用法:
smartant-CLI sysinfo[标志]
标志:
-c,-命令字符串命令
-h,-help sysinfo的帮助
-i,-主机字符串主机ip地址
-P,- port int主机端口
-p,- pwd字符串主机密码
-u,-用户名字符串主机用户名
$ ./smartant-CLI sysinfo-I 121.3.10.55-u root-P 22-P xxxxxxx-c " cat/etc/hosts "
sysinfo已调用
1 localhost localhost . local domain localhost 6 localhost 6 . local domain 6 127 . 0 . 0 . 1 localhost localhost . local domain localho st4 localhost 4 . local domain 4 127 . 0 . 0 . 1 localhost localhost 127 . 0 . 0 . 1硬件服务器硬件服务器
sysinfo调用了commpled
复制代码
其他五个
Cobra非常强大,可以帮助我们快速创建命令行工具,但是如果只是直接写一个非常简单的命令行工具,标志选项非常少,golang内置的标志库就足够了。当然使用要看个人选择,Cobra更适合复杂的命令行工具。
参考链接
github.com/spf13/cobra
www.huweihuang.com/golang-note…
juejin.cn/post/692454…
o-my-chenjian.com/2017/09/20/…