mirror of
				https://github.com/TeaOSLab/EdgeAPI.git
				synced 2025-11-04 07:50:25 +08:00 
			
		
		
		
	API节点启动失败后记录相关问题和处理建议
This commit is contained in:
		@@ -2,6 +2,7 @@ package main
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
	"encoding/json"
 | 
						"encoding/json"
 | 
				
			||||||
 | 
						"flag"
 | 
				
			||||||
	"fmt"
 | 
						"fmt"
 | 
				
			||||||
	"github.com/TeaOSLab/EdgeAPI/internal/apps"
 | 
						"github.com/TeaOSLab/EdgeAPI/internal/apps"
 | 
				
			||||||
	teaconst "github.com/TeaOSLab/EdgeAPI/internal/const"
 | 
						teaconst "github.com/TeaOSLab/EdgeAPI/internal/const"
 | 
				
			||||||
@@ -13,6 +14,7 @@ import (
 | 
				
			|||||||
	"github.com/iwind/TeaGo/maps"
 | 
						"github.com/iwind/TeaGo/maps"
 | 
				
			||||||
	"github.com/iwind/TeaGo/types"
 | 
						"github.com/iwind/TeaGo/types"
 | 
				
			||||||
	"github.com/iwind/gosock/pkg/gosock"
 | 
						"github.com/iwind/gosock/pkg/gosock"
 | 
				
			||||||
 | 
						"io/ioutil"
 | 
				
			||||||
	"log"
 | 
						"log"
 | 
				
			||||||
	"os"
 | 
						"os"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
@@ -21,12 +23,12 @@ func main() {
 | 
				
			|||||||
	if !Tea.IsTesting() {
 | 
						if !Tea.IsTesting() {
 | 
				
			||||||
		Tea.Env = "prod"
 | 
							Tea.Env = "prod"
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	app := apps.NewAppCmd()
 | 
						var app = apps.NewAppCmd()
 | 
				
			||||||
	app.Version(teaconst.Version)
 | 
						app.Version(teaconst.Version)
 | 
				
			||||||
	app.Product(teaconst.ProductName)
 | 
						app.Product(teaconst.ProductName)
 | 
				
			||||||
	app.Usage(teaconst.ProcessName + " [start|stop|restart|setup|upgrade|service|daemon]")
 | 
						app.Usage(teaconst.ProcessName + " [start|stop|restart|setup|upgrade|service|daemon|issues]")
 | 
				
			||||||
	app.On("setup", func() {
 | 
						app.On("setup", func() {
 | 
				
			||||||
		setupCmd := setup.NewSetupFromCmd()
 | 
							var setupCmd = setup.NewSetupFromCmd()
 | 
				
			||||||
		err := setupCmd.Run()
 | 
							err := setupCmd.Run()
 | 
				
			||||||
		result := maps.Map{}
 | 
							result := maps.Map{}
 | 
				
			||||||
		if err != nil {
 | 
							if err != nil {
 | 
				
			||||||
@@ -122,6 +124,43 @@ func main() {
 | 
				
			|||||||
			fmt.Println("prepared statements count: " + types.String(count))
 | 
								fmt.Println("prepared statements count: " + types.String(count))
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	})
 | 
						})
 | 
				
			||||||
 | 
						app.On("issues", func() {
 | 
				
			||||||
 | 
							var flagSet = flag.NewFlagSet("issues", flag.ExitOnError)
 | 
				
			||||||
 | 
							var formatJSON = false
 | 
				
			||||||
 | 
							flagSet.BoolVar(&formatJSON, "json", false, "")
 | 
				
			||||||
 | 
							_ = flagSet.Parse(os.Args[2:])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							data, err := ioutil.ReadFile(Tea.LogFile("issues.log"))
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								if formatJSON {
 | 
				
			||||||
 | 
									fmt.Print("[]")
 | 
				
			||||||
 | 
								} else {
 | 
				
			||||||
 | 
									fmt.Println("no issues yet")
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								var issueMaps = []maps.Map{}
 | 
				
			||||||
 | 
								err = json.Unmarshal(data, &issueMaps)
 | 
				
			||||||
 | 
								if err != nil {
 | 
				
			||||||
 | 
									if formatJSON {
 | 
				
			||||||
 | 
										fmt.Print("[]")
 | 
				
			||||||
 | 
									} else {
 | 
				
			||||||
 | 
										fmt.Println("no issues yet")
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								} else {
 | 
				
			||||||
 | 
									if formatJSON {
 | 
				
			||||||
 | 
										fmt.Print(string(data))
 | 
				
			||||||
 | 
									} else {
 | 
				
			||||||
 | 
										if len(issueMaps) == 0 {
 | 
				
			||||||
 | 
											fmt.Println("no issues yet")
 | 
				
			||||||
 | 
										} else {
 | 
				
			||||||
 | 
											for i, issue := range issueMaps {
 | 
				
			||||||
 | 
												fmt.Println("issue " + types.String(i+1) + ": " + issue.GetString("message"))
 | 
				
			||||||
 | 
											}
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	app.Run(func() {
 | 
						app.Run(func() {
 | 
				
			||||||
		nodes.NewAPINode().Start()
 | 
							nodes.NewAPINode().Start()
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -3,6 +3,7 @@ package nodes
 | 
				
			|||||||
import (
 | 
					import (
 | 
				
			||||||
	"context"
 | 
						"context"
 | 
				
			||||||
	"crypto/tls"
 | 
						"crypto/tls"
 | 
				
			||||||
 | 
						"encoding/json"
 | 
				
			||||||
	"errors"
 | 
						"errors"
 | 
				
			||||||
	"fmt"
 | 
						"fmt"
 | 
				
			||||||
	"github.com/TeaOSLab/EdgeAPI/internal/accesslogs"
 | 
						"github.com/TeaOSLab/EdgeAPI/internal/accesslogs"
 | 
				
			||||||
@@ -15,6 +16,7 @@ import (
 | 
				
			|||||||
	"github.com/TeaOSLab/EdgeAPI/internal/rpc"
 | 
						"github.com/TeaOSLab/EdgeAPI/internal/rpc"
 | 
				
			||||||
	"github.com/TeaOSLab/EdgeAPI/internal/setup"
 | 
						"github.com/TeaOSLab/EdgeAPI/internal/setup"
 | 
				
			||||||
	"github.com/TeaOSLab/EdgeAPI/internal/utils"
 | 
						"github.com/TeaOSLab/EdgeAPI/internal/utils"
 | 
				
			||||||
 | 
						"github.com/go-sql-driver/mysql"
 | 
				
			||||||
	"github.com/iwind/TeaGo/Tea"
 | 
						"github.com/iwind/TeaGo/Tea"
 | 
				
			||||||
	"github.com/iwind/TeaGo/dbs"
 | 
						"github.com/iwind/TeaGo/dbs"
 | 
				
			||||||
	"github.com/iwind/TeaGo/lists"
 | 
						"github.com/iwind/TeaGo/lists"
 | 
				
			||||||
@@ -35,6 +37,7 @@ import (
 | 
				
			|||||||
	"runtime"
 | 
						"runtime"
 | 
				
			||||||
	"sort"
 | 
						"sort"
 | 
				
			||||||
	"strconv"
 | 
						"strconv"
 | 
				
			||||||
 | 
						"strings"
 | 
				
			||||||
	"sync"
 | 
						"sync"
 | 
				
			||||||
	"time"
 | 
						"time"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -51,12 +54,18 @@ type APINode struct {
 | 
				
			|||||||
	sock *gosock.Sock
 | 
						sock *gosock.Sock
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	isStarting bool
 | 
						isStarting bool
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						issues     []*StartIssue
 | 
				
			||||||
 | 
						issuesFile string
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func NewAPINode() *APINode {
 | 
					func NewAPINode() *APINode {
 | 
				
			||||||
	return &APINode{
 | 
						return &APINode{
 | 
				
			||||||
		serviceInstanceMap: map[string]interface{}{},
 | 
							serviceInstanceMap: map[string]interface{}{},
 | 
				
			||||||
		sock:               gosock.NewTmpSock(teaconst.ProcessName),
 | 
							sock:               gosock.NewTmpSock(teaconst.ProcessName),
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							issues:     []*StartIssue{},
 | 
				
			||||||
 | 
							issuesFile: Tea.LogFile("issues.log"),
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -65,18 +74,27 @@ func (this *APINode) Start() {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	logs.Println("[API_NODE]start api node, pid: " + strconv.Itoa(os.Getpid()))
 | 
						logs.Println("[API_NODE]start api node, pid: " + strconv.Itoa(os.Getpid()))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// 检查数据库连接
 | 
						// 保存启动过程中的问题,以便于查看
 | 
				
			||||||
	err := this.checkDB()
 | 
						defer func() {
 | 
				
			||||||
	if err != nil {
 | 
							this.saveIssues()
 | 
				
			||||||
		logs.Println("[API_NODE]" + err.Error())
 | 
						}()
 | 
				
			||||||
		return
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// 本地Sock
 | 
						// 本地Sock
 | 
				
			||||||
	logs.Println("[API_NODE]listening sock ...")
 | 
						logs.Println("[API_NODE]listening sock ...")
 | 
				
			||||||
	err = this.listenSock()
 | 
						err := this.listenSock()
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		logs.Println("[API_NODE]" + err.Error())
 | 
							var errString = "start local sock failed: " + err.Error()
 | 
				
			||||||
 | 
							logs.Println("[API_NODE]" + errString)
 | 
				
			||||||
 | 
							this.addStartIssue("sock", errString, "")
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// 检查数据库连接
 | 
				
			||||||
 | 
						err = this.checkDB()
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							var errString = "check database connection failed: " + err.Error()
 | 
				
			||||||
 | 
							logs.Println("[API_NODE]" + errString)
 | 
				
			||||||
 | 
							this.addStartIssue("db", errString, this.dbIssueSuggestion(err.Error()))
 | 
				
			||||||
		return
 | 
							return
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -84,7 +102,9 @@ func (this *APINode) Start() {
 | 
				
			|||||||
	logs.Println("[API_NODE]auto upgrading ...")
 | 
						logs.Println("[API_NODE]auto upgrading ...")
 | 
				
			||||||
	err = this.autoUpgrade()
 | 
						err = this.autoUpgrade()
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		logs.Println("[API_NODE]auto upgrade failed: " + err.Error())
 | 
							var errString = "auto upgrade failed: " + err.Error()
 | 
				
			||||||
 | 
							logs.Println("[API_NODE]" + errString)
 | 
				
			||||||
 | 
							this.addStartIssue("db", errString, this.dbIssueSuggestion(err.Error()))
 | 
				
			||||||
		return
 | 
							return
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -105,7 +125,9 @@ func (this *APINode) Start() {
 | 
				
			|||||||
	logs.Println("[API_NODE]reading api config ...")
 | 
						logs.Println("[API_NODE]reading api config ...")
 | 
				
			||||||
	config, err := configs.SharedAPIConfig()
 | 
						config, err := configs.SharedAPIConfig()
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		logs.Println("[API_NODE]start failed: " + err.Error())
 | 
							var errString = "read api config failed: " + err.Error()
 | 
				
			||||||
 | 
							logs.Println("[API_NODE]" + errString)
 | 
				
			||||||
 | 
							this.addStartIssue("config", errString, "")
 | 
				
			||||||
		return
 | 
							return
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	sharedAPIConfig = config
 | 
						sharedAPIConfig = config
 | 
				
			||||||
@@ -113,15 +135,23 @@ func (this *APINode) Start() {
 | 
				
			|||||||
	// 校验
 | 
						// 校验
 | 
				
			||||||
	apiNode, err := models.SharedAPINodeDAO.FindEnabledAPINodeWithUniqueIdAndSecret(nil, config.NodeId, config.Secret)
 | 
						apiNode, err := models.SharedAPINodeDAO.FindEnabledAPINodeWithUniqueIdAndSecret(nil, config.NodeId, config.Secret)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		logs.Println("[API_NODE]start failed: read api node from database failed: " + err.Error())
 | 
							var errString = "start failed: read api node from database failed: " + err.Error()
 | 
				
			||||||
 | 
							logs.Println("[API_NODE]" + errString)
 | 
				
			||||||
 | 
							this.addStartIssue("db", errString, "")
 | 
				
			||||||
		return
 | 
							return
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if apiNode == nil {
 | 
						if apiNode == nil {
 | 
				
			||||||
		logs.Println("[API_NODE]can not start node, wrong 'nodeId' or 'secret'")
 | 
							var errString = "can not start node, wrong 'nodeId' or 'secret'"
 | 
				
			||||||
 | 
							logs.Println("[API_NODE]" + errString)
 | 
				
			||||||
 | 
							this.addStartIssue("config", errString, "请在api.yaml配置文件中填写正确的`nodeId`和`secret`,如果数据库或者管理节点或API节点是从别的服务器迁移过来的,请将老的系统配置拷贝到当前节点配置下")
 | 
				
			||||||
		return
 | 
							return
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	config.SetNumberId(int64(apiNode.Id))
 | 
						config.SetNumberId(int64(apiNode.Id))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// 清除上一次启动错误
 | 
				
			||||||
 | 
						// 这个错误文件可能不存在,不需要处理错误
 | 
				
			||||||
 | 
						_ = os.Remove(this.issuesFile)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// 设置rlimit
 | 
						// 设置rlimit
 | 
				
			||||||
	_ = utils.SetRLimit(1024 * 1024)
 | 
						_ = utils.SetRLimit(1024 * 1024)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -138,10 +168,12 @@ func (this *APINode) Start() {
 | 
				
			|||||||
	// 监听RPC服务
 | 
						// 监听RPC服务
 | 
				
			||||||
	remotelogs.Println("API_NODE", "starting RPC server ...")
 | 
						remotelogs.Println("API_NODE", "starting RPC server ...")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	isListening := this.listenPorts(apiNode)
 | 
						var isListening = this.listenPorts(apiNode)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if !isListening {
 | 
						if !isListening {
 | 
				
			||||||
		remotelogs.Error("API_NODE", "the api node require at least one listening address")
 | 
							var errString = "the api node require at least one listening address"
 | 
				
			||||||
 | 
							remotelogs.Error("API_NODE", errString)
 | 
				
			||||||
 | 
							this.addStartIssue("config", errString, "请给当前API节点设置一个监听端口")
 | 
				
			||||||
		return
 | 
							return
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -154,9 +186,8 @@ func (this *APINode) Start() {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
// Daemon 实现守护进程
 | 
					// Daemon 实现守护进程
 | 
				
			||||||
func (this *APINode) Daemon() {
 | 
					func (this *APINode) Daemon() {
 | 
				
			||||||
	path := os.TempDir() + "/" + teaconst.ProcessName + ".sock"
 | 
						var path = os.TempDir() + "/" + teaconst.ProcessName + ".sock"
 | 
				
			||||||
	isDebug := lists.ContainsString(os.Args, "debug")
 | 
						var isDebug = lists.ContainsString(os.Args, "debug")
 | 
				
			||||||
	isDebug = true
 | 
					 | 
				
			||||||
	for {
 | 
						for {
 | 
				
			||||||
		conn, err := net.DialTimeout("unix", path, 1*time.Second)
 | 
							conn, err := net.DialTimeout("unix", path, 1*time.Second)
 | 
				
			||||||
		if err != nil {
 | 
							if err != nil {
 | 
				
			||||||
@@ -199,14 +230,14 @@ func (this *APINode) Daemon() {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
// InstallSystemService 安装系统服务
 | 
					// InstallSystemService 安装系统服务
 | 
				
			||||||
func (this *APINode) InstallSystemService() error {
 | 
					func (this *APINode) InstallSystemService() error {
 | 
				
			||||||
	shortName := teaconst.SystemdServiceName
 | 
						var shortName = teaconst.SystemdServiceName
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	exe, err := os.Executable()
 | 
						exe, err := os.Executable()
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return err
 | 
							return err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	manager := utils.NewServiceManager(shortName, teaconst.ProductName)
 | 
						var manager = utils.NewServiceManager(shortName, teaconst.ProductName)
 | 
				
			||||||
	err = manager.Install(exe, []string{})
 | 
						err = manager.Install(exe, []string{})
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return err
 | 
							return err
 | 
				
			||||||
@@ -242,21 +273,33 @@ func (this *APINode) checkDB() error {
 | 
				
			|||||||
		return err
 | 
							return err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	maxTries := 600
 | 
						// 第一次测试连接
 | 
				
			||||||
	for i := 0; i <= maxTries; i++ {
 | 
						_, err = db.Exec("SELECT 1")
 | 
				
			||||||
		_, err := db.Exec("SELECT 1")
 | 
						if err != nil {
 | 
				
			||||||
		if err != nil {
 | 
							var errString = "check database connection failed: " + err.Error()
 | 
				
			||||||
			if i == maxTries-1 {
 | 
							logs.Println("[API_NODE]" + errString)
 | 
				
			||||||
				return err
 | 
							this.addStartIssue("db", errString, this.dbIssueSuggestion(errString))
 | 
				
			||||||
			} else {
 | 
					
 | 
				
			||||||
				if i%10 == 0 { // 这让提示不会太多
 | 
							// 多次尝试
 | 
				
			||||||
					logs.Println("[API_NODE]reconnecting to database (" + fmt.Sprintf("%.1f", float32(i*100)/float32(maxTries+1)) + "%) ...")
 | 
							var maxTries = 600
 | 
				
			||||||
 | 
							if Tea.IsTesting() {
 | 
				
			||||||
 | 
								maxTries = 600
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							for i := 0; i <= maxTries; i++ {
 | 
				
			||||||
 | 
								_, err := db.Exec("SELECT 1")
 | 
				
			||||||
 | 
								if err != nil {
 | 
				
			||||||
 | 
									if i == maxTries-1 {
 | 
				
			||||||
 | 
										return err
 | 
				
			||||||
 | 
									} else {
 | 
				
			||||||
 | 
										if i%10 == 0 { // 这让提示不会太多
 | 
				
			||||||
 | 
											logs.Println("[API_NODE]reconnecting to database (" + fmt.Sprintf("%.1f", float32(i*100)/float32(maxTries+1)) + "%) ...")
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
										time.Sleep(1 * time.Second)
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
				time.Sleep(1 * time.Second)
 | 
								} else {
 | 
				
			||||||
 | 
									logs.Println("[API_NODE]database connected")
 | 
				
			||||||
 | 
									return nil
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		} else {
 | 
					 | 
				
			||||||
			logs.Println("[API_NODE]database connected")
 | 
					 | 
				
			||||||
			return nil
 | 
					 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -270,7 +313,7 @@ func (this *APINode) autoUpgrade() error {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// 执行SQL
 | 
						// 执行SQL
 | 
				
			||||||
	config := &dbs.Config{}
 | 
						var config = &dbs.Config{}
 | 
				
			||||||
	configData, err := ioutil.ReadFile(Tea.ConfigFile("db.yaml"))
 | 
						configData, err := ioutil.ReadFile(Tea.ConfigFile("db.yaml"))
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return errors.New("read database config file failed: " + err.Error())
 | 
							return errors.New("read database config file failed: " + err.Error())
 | 
				
			||||||
@@ -681,3 +724,62 @@ func (this *APINode) unaryInterceptor(ctx context.Context, req interface{}, info
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
	return result, err
 | 
						return result, err
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// 添加启动相关的Issue
 | 
				
			||||||
 | 
					func (this *APINode) addStartIssue(code string, message string, suggestion string) {
 | 
				
			||||||
 | 
						this.issues = append(this.issues, NewStartIssue(code, message, suggestion))
 | 
				
			||||||
 | 
						this.saveIssues()
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// 增加数据库建议
 | 
				
			||||||
 | 
					func (this *APINode) dbIssueSuggestion(errString string) string {
 | 
				
			||||||
 | 
						// 数据库配置
 | 
				
			||||||
 | 
						db, err := dbs.Default()
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return ""
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						config, err := db.Config()
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return ""
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						var dsn = config.Dsn
 | 
				
			||||||
 | 
						dsnConfig, err := mysql.ParseDSN(dsn)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return ""
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						var addr = dsnConfig.Addr
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// 配置文件位置
 | 
				
			||||||
 | 
						var dbConfigPath = Tea.ConfigFile("db.yaml")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// 连接被拒绝
 | 
				
			||||||
 | 
						if strings.Contains(errString, "connection refused") {
 | 
				
			||||||
 | 
							// 本机
 | 
				
			||||||
 | 
							if strings.HasPrefix(addr, "127.0.0.1:") || strings.HasPrefix(addr, "localhost:") {
 | 
				
			||||||
 | 
								return "试图连接到数据库被拒绝,请检查:1)本地数据库服务是否已经启动;2)数据库IP和端口(" + addr + ")是否正确;(当前数据库配置为:" + dsn + ",配置文件位置:" + dbConfigPath + ")。"
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								return "试图连接到数据库被拒绝,请检查:1)数据库服务是否已经启动;2)数据库IP和端口(" + addr + ")是否正确;3)防火墙设置;(当前数据库配置为:" + dsn + ",配置文件位置:" + dbConfigPath + ")。"
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// 权限错误
 | 
				
			||||||
 | 
						if strings.Contains(errString, "Error 1045") {
 | 
				
			||||||
 | 
							return "使用的用户和密码没有权限连接到指定数据库,请检查:数据库配置文件中的用户名(" + dsnConfig.User + ")和密码(" + dsnConfig.Passwd + ")是否正确;(当前数据库配置为:" + dsn + ",配置文件位置:" + dbConfigPath + ")。"
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// 数据库名称错误
 | 
				
			||||||
 | 
						if strings.Contains(errString, "Error 1049") {
 | 
				
			||||||
 | 
							return "数据库名称配置错误,请检查:数据库配置文件中数据库名称(" + dsnConfig.DBName + ")是否正确;(当前数据库配置为:" + dsn + ",配置文件位置:" + dbConfigPath + ")。"
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return ""
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// 保存issues
 | 
				
			||||||
 | 
					func (this *APINode) saveIssues() {
 | 
				
			||||||
 | 
						issuesJSON, err := json.Marshal(this.issues)
 | 
				
			||||||
 | 
						if err == nil {
 | 
				
			||||||
 | 
							_ = ioutil.WriteFile(this.issuesFile, issuesJSON, 0666)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										17
									
								
								internal/nodes/start_issue.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								internal/nodes/start_issue.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,17 @@
 | 
				
			|||||||
 | 
					// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					package nodes
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type StartIssue struct {
 | 
				
			||||||
 | 
						Code       string `json:"code"`
 | 
				
			||||||
 | 
						Message    string `json:"message"`
 | 
				
			||||||
 | 
						Suggestion string `json:"suggestion"`
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func NewStartIssue(code string, message string, suggestion string) *StartIssue {
 | 
				
			||||||
 | 
						return &StartIssue{
 | 
				
			||||||
 | 
							Code:       code,
 | 
				
			||||||
 | 
							Message:    message,
 | 
				
			||||||
 | 
							Suggestion: suggestion,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
		Reference in New Issue
	
	Block a user