记录学习一下golang中常用的命令行工具,并加以运用做一个轻量级的项目部署工具。
Go 中常用的命令行工具
标准库flag包
package main
import (
"flag"
"fmt"
)
func main() {
// 定义命令行参数
name := flag.String("name", "默认值", "参数说明")
age := flag.Int("age", 0, "年龄")
isVerbose := flag.Bool("verbose", false, "是否显示详细信息")
// 解析命令行参数
flag.Parse()
fmt.Printf("名字: %s\n", *name)
fmt.Printf("年龄: %d\n", *age)
fmt.Printf("详细模式: %v\n", *isVerbose)
}
Cobra包(较flag更推荐)
安装:
go get -u github.com/spf13/cobra
基本使用:
package main
import (
"fmt"
"github.com/spf13/cobra"
)
func main() {
var rootCmd = &cobra.Command{
Use: "myapp",
Short: "我的命令行工具",
}
// 添加子命令
var versionCmd = &cobra.Command{
Use: "version",
Short: "打印版本号",
Run: func(cmd *cobra.Command, args []string) {
fmt.Println("v1.0.0")
},
}
var serveCmd = &cobra.Command{
Use: "serve",
Short: "启动服务",
Run: func(cmd *cobra.Command, args []string) {
fmt.Println("服务启动中...")
},
}
rootCmd.AddCommand(versionCmd, serveCmd)
rootCmd.Execute()
}
命令行参数解析包 flag 和 cobra,常用功能: 命令行自动补全、帮助信息生成、参数验证、环境变量支持、配置文件集成
urfave/cli
github.com/urfave/cli 是一个强大的命令行工具,urfave/cli 是一个功能丰富的命令行工具包,它:
-
支持子命令
-
提供丰富的参数类型
-
支持命令别名
-
可自定义帮助信息
-
提供钩子函数
-
支持命令分类
-
提供完善的参数验证
这个包特别适合构建复杂的命令行应用,使用简单且功能强大。
看示例:
package main
import (
"fmt"
"log"
"os"
"github.com/urfave/cli/v2"
)
func main() {
app := &cli.App{
Name: "任务管理器",
Usage: "一个简单的任务管理CLI应用",
Flags: []cli.Flag{
&cli.StringFlag{
Name: "config",
Aliases: []string{"c"},
Usage: "配置文件路径",
},
&cli.BoolFlag{
Name: "debug",
Usage: "启用调试模式",
Value: false,
},
},
Commands: []*cli.Command{
{
Name: "task",
Usage: "任务管理",
Subcommands: []*cli.Command{
{
Name: "add",
Usage: "添加任务",
Flags: []cli.Flag{
&cli.StringFlag{
Name: "name",
Aliases: []string{"n"},
Usage: "任务名称",
Required: true,
},
},
Action: func(c *cli.Context) error {
name := c.String("name")
fmt.Printf("添加任务: %s\n", name)
return nil
},
},
{
Name: "list",
Usage: "列出所有任务",
Action: func(c *cli.Context) error {
fmt.Println("任务列表:")
return nil
},
},
},
},
},
Before: func(c *cli.Context) error {
// 在命令执行前运行
if c.Bool("debug") {
fmt.Println("调试模式已启用")
}
return nil
},
}
if err := app.Run(os.Args); err != nil {
log.Fatal(err)
}
}
做一个轻量级的项目部署工具
- 实现思路:
项目的部署命令记录在配置文件中,通过命令行cli选择想部署的项目,执行部署并实时打印执行结果
- 项目目录结构:
- 核心代码
// main.go
package main
import (
"os"
"github.com/shennonggo/single-deploy/internal/deploy"
"github.com/shennonggo/single-deploy/internal/utils"
"github.com/urfave/cli/v2"
)
func main() {
app := &cli.App{
Name: "single-deploy",
Usage: "Single Project Deployment Tool",
Flags: []cli.Flag{
&cli.StringFlag{
Name: "config",
Aliases: []string{"c"},
Value: "configs/deploy-config.json",
Usage: "Configuration file path",
},
},
Action: runDeploy,
}
if err := app.Run(os.Args); err != nil {
utils.LogError("Deployment failed: %v", err)
os.Exit(1)
}
}
func runDeploy(c *cli.Context) error {
return deploy.Start(c.String("config"))
}
// deploy.go
package deploy
import (
"fmt"
"time"
"github.com/AlecAivazis/survey/v2"
"github.com/briandowns/spinner"
"github.com/shennonggo/single-deploy/internal/config"
"github.com/shennonggo/single-deploy/internal/utils"
)
func Start(configPath string) error {
// Load configuration
cfg, err := config.LoadConfig(configPath)
if err != nil {
return err
}
if err := cfg.Validate(); err != nil {
return err
}
// Select project
project, err := selectProject(cfg.Projects)
if err != nil {
return err
}
// Create spinner
s := spinner.New(spinner.CharSets[11], 100*time.Millisecond)
s.Prefix = "🚀 "
// Execute deployment steps
steps := GetDeploySteps()
for _, step := range steps {
s.Suffix = fmt.Sprintf(" %s...", step.Name)
s.Start()
if err := step.Execute(project); err != nil {
s.Stop()
return fmt.Errorf("%s failed: %v", step.Name, err)
}
s.Stop()
utils.LogSuccess("%s completed", step.Name)
}
utils.LogSuccess("Project %s deployed successfully!", project.Name)
return nil
}
func selectProject(projects []config.Project) (config.Project, error) {
var selected string
options := make([]string, len(projects))
projectMap := make(map[string]config.Project)
for i, p := range projects {
options[i] = p.Name
projectMap[p.Name] = p
}
prompt := &survey.Select{
Message: "Please select the project to deploy:",
Options: options,
}
if err := survey.AskOne(prompt, &selected); err != nil {
return config.Project{}, err
}
return projectMap[selected], nil
}
// deploy-config.json
{
"projects": [
{
"name": "my-frontend",
"path": "./projects/frontend",
"type": "react",
"gitRepo": "https://github.com/username/frontend-app.git",
"gitBranch": "main",
"buildCmd": "npm install && npm run build",
"startCmd": "npm start",
"healthCheck": {
"url": "http://localhost:3000",
"timeout": 30
}
},
{
"name": "my-backend",
"path": "./projects/backend",
"type": "golang",
"gitRepo": "https://github.com/username/backend-service.git",
"gitBranch": "main",
"buildCmd": "go mod download && go build -o app",
"startCmd": "./app",
"healthCheck": {
"url": "http://localhost:8080/health",
"timeout": 60
}
}
]
}
- 功能点介绍(形容词美化版)
- 🚀 使用单个命令部署多个项目
- 📦 支持不同项目类型(Node.js、React 等)
- 🔄 集成 Git 进行源代码管理
- 🏗️ 自定义构建和启动命令
- 🏥 健康检查监控
- 💻 跨平台支持(Windows、Linux、macOS)
- 项目地址
种下代码,收获未来 Plant Code, Harvest Future