main.go 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156
  1. package main
  2. import (
  3. "bufio"
  4. "context"
  5. "encoding/json"
  6. "fmt"
  7. "log"
  8. "os"
  9. "strings"
  10. )
  11. // Config 配置文件结构 (直接映射环境名称到配置)
  12. type Config map[string]EnvConfig
  13. // EnvConfig 每个环境的配置
  14. type EnvConfig struct {
  15. SSH SSHConfig `json:"ssh"`
  16. Mongo MongoConfig `json:"mongo"`
  17. Redis RedisConfig `json:"redis"`
  18. }
  19. // MongoConfig MongoDB 清理配置
  20. type MongoConfig struct {
  21. Config DBConfig `json:"config"`
  22. DropDatabases []string `json:"drop_databases"`
  23. }
  24. // RedisConfig Redis 清理配置
  25. type RedisConfig struct {
  26. Config DBConfig `json:"config"`
  27. DeleteKeys []string `json:"delete_keys"`
  28. }
  29. func main() {
  30. // 默认配置
  31. configPath := "config.json"
  32. var envName string
  33. args := os.Args[1:] // 获取实际参数 (排除程序名)
  34. if len(args) >= 2 {
  35. // 方式: ./cleandb <configPath> <envName>
  36. configPath = args[0]
  37. envName = args[1]
  38. } else if len(args) == 1 {
  39. // 方式: ./cleandb <envName> (配置路径使用默认值)
  40. envName = args[0]
  41. }
  42. if envName == "" {
  43. log.Fatal("使用说明:\n 方式1: ./cleandb <configPath> <envName>\n 方式2: ./cleandb <envName> (默认加载当前目录下的 config.json)")
  44. }
  45. // 加载配置
  46. data, err := os.ReadFile(configPath)
  47. if err != nil {
  48. log.Fatalf("无法读取配置文件: %v", err)
  49. }
  50. var totalConfig Config
  51. if err := json.Unmarshal(data, &totalConfig); err != nil {
  52. log.Fatalf("解析配置文件失败: %v", err)
  53. }
  54. env, ok := totalConfig[envName]
  55. if !ok {
  56. log.Fatalf("未找到环境配置: %s", envName)
  57. }
  58. ctx := context.Background()
  59. // 1. 处理 MongoDB 清理
  60. if len(env.Mongo.DropDatabases) > 0 {
  61. cleanMongo(ctx, env.SSH, env.Mongo)
  62. }
  63. // 2. 处理 Redis 清理
  64. if len(env.Redis.DeleteKeys) > 0 {
  65. cleanRedis(ctx, env.SSH, env.Redis)
  66. }
  67. fmt.Println("\n所有任务已完成!")
  68. }
  69. func cleanMongo(ctx context.Context, sshConf SSHConfig, mongoConf MongoConfig) {
  70. fmt.Printf("\n--- MongoDB 清理 [%v] ---\n", mongoConf.Config.Host)
  71. fmt.Printf("待删除数据库: %v\n", mongoConf.DropDatabases)
  72. client, tunnel, err := ConnectMongoViaSSH(sshConf, mongoConf.Config)
  73. if err != nil {
  74. log.Fatalf("连接 MongoDB 失败: %v", err)
  75. }
  76. defer client.Disconnect(ctx)
  77. if tunnel != nil {
  78. defer tunnel.Close()
  79. }
  80. for _, dbName := range mongoConf.DropDatabases {
  81. err := client.Database(dbName).Drop(ctx)
  82. if err != nil {
  83. fmt.Printf("警告: 删除数据库 %s 失败: %v\n", dbName, err)
  84. } else {
  85. fmt.Printf("成功删除数据库: %s\n", dbName)
  86. }
  87. }
  88. }
  89. func cleanRedis(ctx context.Context, sshConf SSHConfig, redisConf RedisConfig) {
  90. fmt.Printf("\n--- Redis 清理 [%v] ---\n", redisConf.Config.Host)
  91. fmt.Printf("待删除键: %v\n", redisConf.DeleteKeys)
  92. rdb, tunnel, err := ConnectRedisViaSSH(sshConf, redisConf.Config)
  93. if err != nil {
  94. log.Fatalf("连接 Redis 失败: %v", err)
  95. }
  96. defer rdb.Close()
  97. if tunnel != nil {
  98. defer tunnel.Close()
  99. }
  100. for _, keyPattern := range redisConf.DeleteKeys {
  101. if strings.Contains(keyPattern, "*") {
  102. // 处理通配符
  103. iter := rdb.Scan(ctx, 0, keyPattern, 0).Iterator()
  104. count := 0
  105. for iter.Next(ctx) {
  106. if err := rdb.Del(ctx, iter.Val()).Err(); err != nil {
  107. fmt.Printf("警告: 删除键 %s 失败: %v\n", iter.Val(), err)
  108. } else {
  109. count++
  110. }
  111. }
  112. fmt.Printf("模式 [%s] 已删除 %d 个键\n", keyPattern, count)
  113. } else {
  114. // 处理单个键
  115. if err := rdb.Del(ctx, keyPattern).Err(); err != nil {
  116. fmt.Printf("警告: 删除键 %s 失败: %v\n", keyPattern, err)
  117. } else {
  118. fmt.Printf("成功删除键: %s\n", keyPattern)
  119. }
  120. }
  121. }
  122. }
  123. func confirm(prompt string) bool {
  124. reader := bufio.NewReader(os.Stdin)
  125. fmt.Printf("%s (y/n): ", prompt)
  126. input, _ := reader.ReadString('\n')
  127. input = strings.TrimSpace(strings.ToLower(input))
  128. return input == "y" || input == "yes"
  129. }