Optimize Docker configuration and script.

pull/2148/head
skiffer-git 1 year ago
parent b1bc8324fb
commit 551dbb2a09

@ -25,4 +25,5 @@ func main() {
if err := cmd.NewApiCmd().Exec(); err != nil {
program.ExitWithError(err)
}
}

@ -60,4 +60,5 @@ func listenOnPort(port int) {
// Normally, you would accept connections with l.Accept() in a loop here.
// For this example, just sleep indefinitely to simulate a service.
select {}
}

@ -15,7 +15,7 @@ require (
github.com/mitchellh/mapstructure v1.5.0
github.com/openimsdk/localcache v0.0.1
github.com/openimsdk/protocol v0.0.60
github.com/openimsdk/tools v0.0.47-alpha.16
github.com/openimsdk/tools v0.0.47-alpha.14
github.com/pkg/errors v0.9.1 // indirect
github.com/prometheus/client_golang v1.18.0
github.com/stretchr/testify v1.8.4
@ -34,6 +34,7 @@ require (
github.com/go-redis/redis v6.15.9+incompatible
github.com/kelindar/bitmap v1.5.2
github.com/likexian/gokit v0.25.13
github.com/magefile/mage v1.15.0
github.com/redis/go-redis/v9 v9.4.0
github.com/robfig/cron/v3 v3.0.1
github.com/shirou/gopsutil v3.21.11+incompatible
@ -99,7 +100,6 @@ require (
github.com/klauspost/cpuid/v2 v2.2.6 // indirect
github.com/leodido/go-urn v1.4.0 // indirect
github.com/lithammer/shortuuid v3.0.0+incompatible // indirect
github.com/magefile/mage v1.15.0 // indirect
github.com/magiconair/properties v1.8.7 // indirect
github.com/mattn/go-colorable v0.1.13 // indirect
github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0 // indirect

@ -4,7 +4,7 @@
package main
import (
"github.com/openimsdk/tools/utils/mageutil"
"github.com/openimsdk/open-im-server/v3/pkg/util/mageutil"
"os"
"strings"
)
@ -21,7 +21,7 @@ func Build() {
mageutil.CompileForPlatform(platform)
}
mageutil.PrintGreen("Compilation complete.")
mageutil.PrintGreen("All binaries under cmd and tools were successfully compiled.")
}
func Start() {

@ -0,0 +1,117 @@
package mageutil
import (
"fmt"
"os"
"os/exec"
"path/filepath"
"strconv"
"strings"
)
// StopBinaries iterates over all binary files and terminates their corresponding processes.
func StopBinaries() {
for binary := range serviceBinaries {
fullPath := GetBinFullPath(binary)
KillExistBinary(fullPath)
}
}
// StartBinaries Start all binary services.
func StartBinaries() error {
for binary, count := range serviceBinaries {
binFullPath := filepath.Join(OpenIMOutputHostBin, binary)
for i := 0; i < count; i++ {
args := []string{"-i", strconv.Itoa(i), "-c", OpenIMOutputConfig}
cmd := exec.Command(binFullPath, args...)
fmt.Printf("Starting %s\n", cmd.String())
cmd.Dir = OpenIMOutputHostBin
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
if err := cmd.Start(); err != nil {
fmt.Fprintf(os.Stderr, "Failed to start %s with args %v: %v\n", binFullPath, args, err)
return err
}
}
}
return nil
}
// StartTools starts all tool binaries.
func StartTools() error {
for _, tool := range toolBinaries {
toolFullPath := GetToolFullPath(tool)
cmd := exec.Command(toolFullPath, "-c", OpenIMOutputConfig)
fmt.Printf("Starting %s\n", cmd.String())
cmd.Dir = OpenIMOutputHostBinTools
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
if err := cmd.Start(); err != nil {
fmt.Printf("Failed to start %s with error: %v\n", toolFullPath, err)
return err
}
if err := cmd.Wait(); err != nil {
fmt.Printf("Failed to execute %s with exit code: %v\n", toolFullPath, err)
return err
}
fmt.Printf("Starting %s successfully \n", cmd.String())
}
return nil
}
// KillExistBinaries iterates over all binary files and kills their corresponding processes.
func KillExistBinaries() {
for binary := range serviceBinaries {
fullPath := GetBinFullPath(binary)
KillExistBinary(fullPath)
}
}
// CheckBinariesStop checks if all binary files have stopped and returns an error if there are any binaries still running.
func CheckBinariesStop() error {
var runningBinaries []string
for binary := range serviceBinaries {
fullPath := GetBinFullPath(binary)
if CheckProcessNamesExist(fullPath) {
runningBinaries = append(runningBinaries, binary)
}
}
if len(runningBinaries) > 0 {
return fmt.Errorf("the following binaries are still running: %s", strings.Join(runningBinaries, ", "))
}
return nil
}
// CheckBinariesRunning checks if all binary files are running as expected and returns any errors encountered.
func CheckBinariesRunning() error {
var errorMessages []string
for binary, expectedCount := range serviceBinaries {
fullPath := GetBinFullPath(binary)
err := CheckProcessNames(fullPath, expectedCount)
if err != nil {
errorMessages = append(errorMessages, fmt.Sprintf("binary %s is not running as expected: %v", binary, err))
}
}
if len(errorMessages) > 0 {
return fmt.Errorf(strings.Join(errorMessages, "\n"))
}
return nil
}
// PrintListenedPortsByBinaries iterates over all binary files and prints the ports they are listening on.
func PrintListenedPortsByBinaries() {
for binary, _ := range serviceBinaries {
basePath := GetBinFullPath(binary)
fullPath := basePath
PrintBinaryPorts(fullPath)
}
}

@ -0,0 +1,198 @@
package mageutil
import (
"fmt"
"github.com/magefile/mage/sh"
"os"
"path/filepath"
"strings"
"sync"
)
// CheckAndReportBinariesStatus checks the running status of all binary files and reports it.
func CheckAndReportBinariesStatus() {
err := CheckBinariesRunning()
if err != nil {
PrintRed("Some programs are not running properly:")
PrintRedNoTimeStamp(err.Error())
return
}
PrintGreen("All services are running normally.")
PrintBlue("Display details of the ports listened to by the service:")
PrintListenedPortsByBinaries()
}
// StopAndCheckBinaries stops all binary processes and checks if they have all stopped.
func StopAndCheckBinaries() {
KillExistBinaries()
err := CheckBinariesStop()
if err != nil {
PrintRed("Some services have not been stopped, details are as follows:" + err.Error())
return
}
PrintGreen("All services have been stopped")
}
// StartToolsAndServices starts the process for tools and services.
func StartToolsAndServices() {
PrintBlue("Starting tools primarily involves component verification and other preparatory tasks.")
if err := StartTools(); err != nil {
PrintRed("Some tools failed to start, details are as follows, abort start")
PrintRedNoTimeStamp(err.Error())
return
}
PrintGreen("All tools executed successfully")
KillExistBinaries()
err := CheckBinariesStop()
if err != nil {
PrintRed("Some services running, details are as follows, abort start " + err.Error())
return
}
PrintBlue("Starting services involves multiple RPCs and APIs and may take some time. Please be patient")
err = StartBinaries()
if err != nil {
PrintRed("Failed to start all binaries")
PrintRedNoTimeStamp(err.Error())
return
}
CheckAndReportBinariesStatus()
}
// CompileForPlatform Main compile function
func CompileForPlatform(platform string) {
PrintBlue(fmt.Sprintf("Compiling cmd for %s...", platform))
compileDir(filepath.Join(rootDirPath, "cmd"), platformsOutputBase, platform)
PrintBlue(fmt.Sprintf("Compiling tools for %s...", platform))
compileDir(filepath.Join(rootDirPath, "tools"), toolsOutputBase, platform)
}
func compileDir(sourceDir, outputBase, platform string) {
targetOS, targetArch := strings.Split(platform, "_")[0], strings.Split(platform, "_")[1]
outputDir := filepath.Join(outputBase, targetOS, targetArch)
if err := os.MkdirAll(outputDir, 0755); err != nil {
fmt.Printf("Failed to create directory %s: %v\n", outputDir, err)
os.Exit(1)
}
var wg sync.WaitGroup
errors := make(chan error, 1)
sem := make(chan struct{}, 4)
err := filepath.Walk(sourceDir, func(path string, info os.FileInfo, err error) error {
if err != nil {
return err
}
if info.IsDir() || filepath.Base(path) != "main.go" {
return nil
}
wg.Add(1)
go func() {
sem <- struct{}{}
defer wg.Done()
defer func() { <-sem }()
dir := filepath.Dir(path)
dirName := filepath.Base(dir)
outputFileName := dirName
if targetOS == "windows" {
outputFileName += ".exe"
}
PrintBlue(fmt.Sprintf("Compiling dir: %s for platform: %s binary: %s ...", dirName, platform, outputFileName))
err := sh.RunWith(map[string]string{"GOOS": targetOS, "GOARCH": targetArch}, "go", "build", "-o", filepath.Join(outputDir, outputFileName), filepath.Join(dir, "main.go"))
if err != nil {
errors <- fmt.Errorf("failed to compile %s for %s: %v", dirName, platform, err)
PrintRed("Compilation aborted. " + fmt.Sprintf("failed to compile %s for %s: %v", dirName, platform, err))
os.Exit(1)
return
}
PrintGreen(fmt.Sprintf("Successfully compiled. dir: %s for platform: %s binary: %s", dirName, platform, outputFileName))
}()
return nil
})
if err != nil {
fmt.Println("Error walking through directories:", err)
os.Exit(1)
}
wg.Wait()
close(errors)
// Check for errors
if err, ok := <-errors; ok {
fmt.Println(err)
os.Exit(1)
}
}
// compileDir compiles Go programs in a specified directory, appending .exe extension for output files on Windows platform
//func compileDir(sourceDir, outputBase, platform string) {
// targetOS, targetArch := strings.Split(platform, "_")[0], strings.Split(platform, "_")[1]
// outputDir := filepath.Join(outputBase, targetOS, targetArch)
//
// if err := os.MkdirAll(outputDir, 0755); err != nil {
// fmt.Printf("Failed to create directory %s: %v\n", outputDir, err)
// os.Exit(1)
// }
//
// var wg sync.WaitGroup
// errors := make(chan error, 1)
//
// err := filepath.Walk(sourceDir, func(path string, info os.FileInfo, err error) error {
// if err != nil {
// return err
// }
// if info.IsDir() || filepath.Base(path) != "main.go" {
// return nil
// }
//
// wg.Add(1)
// go func() {
// defer wg.Done()
//
// dir := filepath.Dir(path)
// dirName := filepath.Base(dir)
// outputFileName := dirName
// if targetOS == "windows" {
// outputFileName += ".exe"
// }
//
// PrintBlue(fmt.Sprintf("Compiling dir: %s for platform: %s binary: %s ...", dirName, platform, outputFileName))
// err := sh.RunWith(map[string]string{"GOOS": targetOS, "GOARCH": targetArch}, "go", "build", "-o", filepath.Join(outputDir, outputFileName), filepath.Join(dir, "main.go"))
// if err != nil {
// errors <- fmt.Errorf("failed to compile %s for %s: %v", dirName, platform, err)
// PrintRed("Compilation aborted. " + fmt.Sprintf("failed to compile %s for %s: %v", dirName, platform, err))
// os.Exit(1)
// return
// }
// PrintGreen(fmt.Sprintf("Compiling dir: %s for platform: %s binary: %s ...", dirName, platform, outputFileName))
// }()
//
// return nil
// })
//
// if err != nil {
// fmt.Println("Error walking through directories:", err)
// os.Exit(1)
// }
//
// wg.Wait()
// close(errors)
//
// // Check for errors
// if err, ok := <-errors; ok {
// fmt.Println(err)
// fmt.Println("Compilation aborted.")
// os.Exit(1)
// }
//}

@ -0,0 +1,46 @@
package mageutil
import (
"gopkg.in/yaml.v3"
"io/ioutil"
"log"
"runtime"
)
var (
serviceBinaries map[string]int
toolBinaries []string
MaxFileDescriptors int
)
type Config struct {
ServiceBinaries map[string]int `yaml:"serviceBinaries"`
ToolBinaries []string `yaml:"toolBinaries"`
MaxFileDescriptors int `yaml:"maxFileDescriptors"`
}
func init() {
yamlFile, err := ioutil.ReadFile("start-config.yml")
if err != nil {
log.Fatalf("error reading YAML file: %v", err)
}
// 解析YAML
var config Config
err = yaml.Unmarshal(yamlFile, &config)
if err != nil {
log.Fatalf("error unmarshalling YAML: %v", err)
}
adjustedBinaries := make(map[string]int)
for binary, count := range config.ServiceBinaries {
if runtime.GOOS == "windows" {
binary += ".exe"
}
adjustedBinaries[binary] = count
}
serviceBinaries = adjustedBinaries
toolBinaries = config.ToolBinaries
MaxFileDescriptors = config.MaxFileDescriptors
}

@ -0,0 +1,56 @@
package mageutil
import (
"fmt"
"os"
"time"
)
const (
ColorBlue = "\033[0;34m"
ColorGreen = "\033[0;32m"
ColorRed = "\033[0;31m"
ColorReset = "\033[0m"
)
func PrintBlueTwoLine(message string) {
currentTime := time.Now().Format("[2006-01-02 15:04:05 MST]")
fmt.Println(currentTime)
fmt.Printf("%s%s%s\n", ColorBlue, message, ColorReset)
}
func PrintBlue(message string) {
currentTime := time.Now().Format("[2006-01-02 15:04:05 MST]")
fmt.Printf("%s %s%s%s\n", currentTime, ColorBlue, message, ColorReset)
}
func PrintGreenTwoLine(message string) {
currentTime := time.Now().Format("[2006-01-02 15:04:05 MST]")
fmt.Println(currentTime)
fmt.Printf("%s%s%s\n", ColorGreen, message, ColorReset)
}
func PrintGreen(message string) {
currentTime := time.Now().Format("[2006-01-02 15:04:05 MST]")
fmt.Printf("%s %s%s%s\n", currentTime, ColorGreen, message, ColorReset)
}
func PrintRed(message string) {
currentTime := time.Now().Format("[2006-01-02 15:04:05 MST]")
fmt.Printf("%s %s%s%s\n", currentTime, ColorRed, message, ColorReset)
}
func PrintRedNoTimeStamp(message string) {
fmt.Printf("%s%s%s\n", ColorRed, message, ColorReset)
}
func PrintGreenNoTimeStamp(message string) {
fmt.Printf("%s%s%s\n", ColorGreen, message, ColorReset)
}
func PrintRedToStdErr(a ...interface{}) (n int, err error) {
return fmt.Fprint(os.Stderr, "\033[31m", fmt.Sprint(a...), "\033[0m")
}
func PrintGreenToStdOut(a ...interface{}) (n int, err error) {
return fmt.Fprint(os.Stdout, "\033[32m", fmt.Sprint(a...), "\033[0m")
}

@ -0,0 +1,85 @@
package mageutil
import (
"fmt"
"os"
"path/filepath"
)
var (
OpenIMRoot string
OpenIMOutputConfig string
OpenIMOutput string
OpenIMOutputTools string
OpenIMOutputTmp string
OpenIMOutputLogs string
OpenIMOutputBin string
OpenIMOutputBinPath string
OpenIMOutputBinToolPath string
OpenIMInitErrLogFile string
OpenIMInitLogFile string
OpenIMOutputHostBin string
OpenIMOutputHostBinTools string
)
func init() {
currentDir, err := os.Getwd()
if err != nil {
panic("Error getting current directory: " + err.Error())
}
OpenIMRoot = currentDir
OpenIMOutputConfig = filepath.Join(OpenIMRoot, "config") + string(filepath.Separator)
OpenIMOutput = filepath.Join(OpenIMRoot, "_output") + string(filepath.Separator)
OpenIMOutputTools = filepath.Join(OpenIMOutput, "tools") + string(filepath.Separator)
OpenIMOutputTmp = filepath.Join(OpenIMOutput, "tmp") + string(filepath.Separator)
OpenIMOutputLogs = filepath.Join(OpenIMOutput, "logs") + string(filepath.Separator)
OpenIMOutputBin = filepath.Join(OpenIMOutput, "bin") + string(filepath.Separator)
OpenIMOutputBinPath = filepath.Join(OpenIMOutputBin, "platforms") + string(filepath.Separator)
OpenIMOutputBinToolPath = filepath.Join(OpenIMOutputBin, "tools") + string(filepath.Separator)
OpenIMInitErrLogFile = filepath.Join(OpenIMOutputLogs, "openim-init-err.log")
OpenIMInitLogFile = filepath.Join(OpenIMOutputLogs, "openim-init.log")
OpenIMOutputHostBin = filepath.Join(OpenIMOutputBinPath, OsArch()) + string(filepath.Separator)
OpenIMOutputHostBinTools = filepath.Join(OpenIMOutputBinToolPath, OsArch()) + string(filepath.Separator)
dirs := []string{
OpenIMOutputConfig,
OpenIMOutput,
OpenIMOutputTools,
OpenIMOutputTmp,
OpenIMOutputLogs,
OpenIMOutputBin,
OpenIMOutputBinPath,
OpenIMOutputBinToolPath,
OpenIMOutputHostBin,
OpenIMOutputHostBinTools,
}
for _, dir := range dirs {
createDirIfNotExist(dir)
}
}
func createDirIfNotExist(dir string) {
if err := os.MkdirAll(dir, 0755); err != nil {
fmt.Printf("Failed to create directory %s: %v\n", dir, err)
os.Exit(1)
}
}
// GetBinFullPath constructs and returns the full path for the given binary name.
func GetBinFullPath(binName string) string {
binFullPath := filepath.Join(OpenIMOutputHostBin, binName)
return binFullPath
}
// GetToolFullPath constructs and returns the full path for the given tool name.
func GetToolFullPath(toolName string) string {
toolFullPath := filepath.Join(OpenIMOutputHostBinTools, toolName)
return toolFullPath
}

@ -0,0 +1,208 @@
package mageutil
import (
"fmt"
"github.com/shirou/gopsutil/net"
"github.com/shirou/gopsutil/process"
"os"
"path/filepath"
"runtime"
"strings"
)
func OsArch() string {
os := runtime.GOOS
arch := runtime.GOARCH
if os == "windows" {
return fmt.Sprintf("%s\\%s", os, arch)
}
return fmt.Sprintf("%s/%s", os, arch)
}
func CheckProcessNames(processPath string, expectedCount int) error {
processes, err := process.Processes()
if err != nil {
return fmt.Errorf("failed to get processes: %v", err)
}
runningCount := 0
for _, p := range processes {
exePath, err := p.Exe()
if err != nil {
continue
}
if strings.EqualFold(exePath, processPath) {
runningCount++
}
}
if runningCount == expectedCount {
return nil
} else {
return fmt.Errorf("%s Expected %d processes, but %d running", processPath, expectedCount, runningCount)
}
}
// CheckProcessNamesExist checks if there are any processes running that match the specified path.
func CheckProcessNamesExist(processPath string) bool {
processes, err := process.Processes()
if err != nil {
fmt.Printf("Failed to get processes: %v\n", err)
return false
}
for _, p := range processes {
exePath, err := p.Exe()
if err != nil {
continue
}
if exePath == processPath {
return true // 找到至少一个匹配的进程
}
}
return false
}
// PrintBinaryPorts prints the ports listened by the process of a specified binary file along with its command line arguments.
func PrintBinaryPorts(binaryPath string) {
pids, err := FindPIDsByBinaryPath(binaryPath)
if err != nil {
fmt.Println("Error finding PIDs:", err)
return
}
if len(pids) == 0 {
fmt.Printf("No running processes found for binary: %s\n", binaryPath)
return
}
for _, pid := range pids {
proc, err := process.NewProcess(int32(pid))
if err != nil {
fmt.Printf("Failed to create process object for PID %d: %v\n", pid, err)
continue
}
cmdline, err := proc.Cmdline()
if err != nil {
fmt.Printf("Failed to get command line for PID %d: %v\n", pid, err)
continue
}
connections, err := net.ConnectionsPid("all", int32(pid))
if err != nil {
fmt.Printf("Error getting connections for PID %d: %v\n", pid, err)
continue
}
portsMap := make(map[string]struct{})
for _, conn := range connections {
if conn.Status == "LISTEN" {
port := fmt.Sprintf("%d", conn.Laddr.Port)
portsMap[port] = struct{}{}
}
}
if len(portsMap) == 0 {
PrintGreen(fmt.Sprintf("Cmdline: %s, PID: %d is not listening on any ports.", cmdline, pid))
} else {
ports := make([]string, 0, len(portsMap))
for port := range portsMap {
ports = append(ports, port)
}
PrintGreen(fmt.Sprintf("Cmdline: %s, PID: %d is listening on ports: %s", cmdline, pid, strings.Join(ports, ", ")))
}
}
}
// FindPIDsByBinaryPath finds all matching process PIDs by binary path.
func FindPIDsByBinaryPath(binaryPath string) ([]int, error) {
var pids []int
processes, err := process.Processes()
if err != nil {
return nil, err
}
for _, proc := range processes {
exePath, err := proc.Exe()
if err != nil {
continue
}
if strings.EqualFold(exePath, binaryPath) {
pids = append(pids, int(proc.Pid))
}
}
return pids, nil
}
// KillExistBinary kills all processes matching the given binary file path.
func KillExistBinary(binaryPath string) {
processes, err := process.Processes()
if err != nil {
fmt.Printf("Failed to get processes: %v\n", err)
return
}
for _, p := range processes {
exePath, err := p.Exe()
if err != nil {
continue
}
if strings.Contains(strings.ToLower(exePath), strings.ToLower(binaryPath)) {
//if strings.EqualFold(exePath, binaryPath) {
cmdline, err := p.Cmdline()
if err != nil {
fmt.Printf("Failed to get command line for process %d: %v\n", p.Pid, err)
continue
}
err = p.Terminate()
if err != nil {
err = p.Kill()
if err != nil {
fmt.Printf("Failed to kill process cmdline: %s, pid: %d, err: %v\n", cmdline, p.Pid, err)
} else {
fmt.Printf("Killed process cmdline: %s, pid: %d\n", cmdline, p.Pid)
}
} else {
fmt.Printf("Terminated process cmdline: %s, pid: %d\n", cmdline, p.Pid)
}
}
}
}
// DetectPlatform detects the operating system and architecture.
func DetectPlatform() string {
targetOS, targetArch := runtime.GOOS, runtime.GOARCH
switch targetArch {
case "amd64", "arm64":
default:
fmt.Printf("Unsupported architecture: %s\n", targetArch)
os.Exit(1)
}
return fmt.Sprintf("%s_%s", targetOS, targetArch)
}
// rootDir gets the absolute path of the current directory.
func rootDir() string {
dir, err := os.Getwd()
if err != nil {
fmt.Println("Failed to get current directory:", err)
os.Exit(1)
}
return dir
}
var rootDirPath = rootDir()
var platformsOutputBase = filepath.Join(rootDirPath, "_output/bin/platforms")
var toolsOutputBase = filepath.Join(rootDirPath, "_output/bin/tools")

@ -0,0 +1,67 @@
# mageutil使用指南
**mageutil** 是基于 mage 构建的一个工具,它提供了跨平台和多架构的编译支持,同时也简化了服务的启动、停止、检测流程。
## 使用指南
### 准备工作
1. 将此目录下除README以外的6个文件复制到项目的根目录
2. 项目根目录下需要包含三个目录:`cmd`、`tools`和`config`。
- `cmd` 目录专门用于存放那些作为后台服务运行的应用的启动代码。
- `tools`目录用于存放那些作为工具应用(不以后台服务形式运行)的启动代码。
- `config`目录用于存放配置文件。
3. `cmd`和`tools`目录可以包含多层多个子目录。对于包含`main`函数的`main package`文件,需以`main.go`命名。例如:
- `cmd/openim-rpc/openim-rpc-msg/main.go`
- `tools/check-free-memory/main.go`
- 所有代码都应属于同一个项目,子目录不应使用独立的`go.mod`和`go.sum`文件。
### 初始化项目
- 对于Linux/Mac系统先执行`bootstrap.sh`脚本。
- 对于Windows系统先执行`bootstrap.bat`脚本。
### 编译项目
- 执行`mage`或`mage build`来编译项目。
- 编译完成后,二进制文件将生成在`_output/bin/platforms/<操作系统>/<架构>`目录下,其中二进制文件的命名规则为对应的`main.go`所在的目录名。例如:
- `_output/bin/platforms/linux/amd64/openim-rpc-msg`
- `_output/bin/tools/linux/amd64/check-free-memory`
- **注意:** Windows平台的二进制文件会自动添加`.exe`扩展名。
### 启动工具和服务
1. 首先,编辑`start-config.yml`文件,指定服务和工具相关配置,例如:
```yaml
#cmd服务子目录名: 实例数
serviceBinaries:
openim-rpc-msg: 2
#tools工具子目录名
toolBinaries:
- check-free-memory
maxFileDescriptors: 10000
```
**注意:**服务和工具名与`cmd`和`tools`下的子目录名保持一致
3. 执行`mage start`来启动服务和工具。
- 工具将以同步方式执行,如果工具执行失败(退出代码非零),则整个启动过程中断。
- 服务将以异步方式启动。
对于所有工具,将采用以下命令格式启动:`[程序绝对路径] -i 0 -c [配置文件绝对目录]`。
若服务实例数设置为`n`,则服务将启动`n`个实例,每个实例使用的命令格式为:`[程序路径] -i [实例索引] -c [配置文件目录]`,其中实例索引从`0`到`n-1`。
**注意**:本项目仅指定了配置文件的路径,并不负责读取配置文件内容。这样做的目的是为了支持使用多个配置文件的情况。程序和配置文件的路径都自动使用绝对路径。
### 检查和停止服务
- 执行`mage check`来检查服务状态和监听的端口。
- 执行`mage stop`来停止服务,该命令会向服务发送停止信号。
---

@ -0,0 +1,31 @@
@echo off
SETLOCAL
mage -version >nul 2>&1
IF %ERRORLEVEL% EQU 0 (
echo Mage is already installed.
GOTO DOWNLOAD
)
go version >nul 2>&1
IF NOT %ERRORLEVEL% EQU 0 (
echo Go is not installed. Please install Go and try again.
exit /b 1
)
echo Installing Mage...
go install github.com/magefile/mage@latest
mage -version >nul 2>&1
IF NOT %ERRORLEVEL% EQU 0 (
echo Mage installation failed.
echo Please ensure that %GOPATH%/bin is in your PATH.
exit /b 1
)
echo Mage installed successfully.
:DOWNLOAD
go mod download
ENDLOCAL

@ -0,0 +1,23 @@
#!/bin/bash
if [[ ":$PATH:" == *":$HOME/.local/bin:"* ]]; then
TARGET_DIR="$HOME/.local/bin"
else
TARGET_DIR="/usr/local/bin"
echo "Using /usr/local/bin as the installation directory. Might require sudo permissions."
fi
if ! command -v mage &> /dev/null; then
echo "Installing Mage to $TARGET_DIR ..."
GOBIN=$TARGET_DIR go install github.com/magefile/mage@latest
fi
if ! command -v mage &> /dev/null; then
echo "Mage installation failed."
echo "Please ensure that $TARGET_DIR is in your \$PATH."
exit 1
fi
echo "Mage installed successfully."
go mod download

@ -0,0 +1,38 @@
//go:build mage
// +build mage
package main
import (
"github.com/openimsdk/tools/utils/mageutil"
"os"
"strings"
)
var Default = Build
func Build() {
platforms := os.Getenv("PLATFORMS")
if platforms == "" {
platforms = mageutil.DetectPlatform()
}
for _, platform := range strings.Split(platforms, " ") {
mageutil.CompileForPlatform(platform)
}
mageutil.PrintGreen("Compilation complete.")
}
func Start() {
setMaxOpenFiles()
mageutil.StartToolsAndServices()
}
func Stop() {
mageutil.StopAndCheckBinaries()
}
func Check() {
mageutil.CheckAndReportBinariesStatus()
}

@ -0,0 +1,20 @@
//go:build mage && !windows
// +build mage,!windows
package main
import (
"github.com/openimsdk/tools/utils/mageutil"
"syscall"
)
func setMaxOpenFiles() error {
var rLimit syscall.Rlimit
err := syscall.Getrlimit(syscall.RLIMIT_NOFILE, &rLimit)
if err != nil {
return err
}
rLimit.Max = uint64(mageutil.MaxFileDescriptors)
rLimit.Cur = uint64(mageutil.MaxFileDescriptors)
return syscall.Setrlimit(syscall.RLIMIT_NOFILE, &rLimit)
}

@ -0,0 +1,8 @@
//go:build mage
// +build mage
package main
func setMaxOpenFiles() error {
return nil
}

@ -0,0 +1,8 @@
serviceBinaries:
openim-no-port: 1
openim-test: 1
toolBinaries:
- check-free-memory
maxFileDescriptors: 10000

@ -24,7 +24,6 @@ import (
"github.com/openimsdk/tools/db/redisutil"
"github.com/openimsdk/tools/discovery/zookeeper"
"github.com/openimsdk/tools/mq/kafka"
"github.com/openimsdk/tools/s3/minio"
"github.com/openimsdk/tools/system/program"
"path/filepath"
"time"
@ -45,8 +44,8 @@ func CheckRedis(ctx context.Context, config *config.Redis) error {
}
func CheckMinIO(ctx context.Context, config *config.Minio) error {
return minio.Check()
//return minio.Check()
return nil
}
func CheckKafka(ctx context.Context, conf *config.Kafka) error {

@ -25,6 +25,7 @@ import (
"github.com/openimsdk/protocol/auth"
"github.com/openimsdk/protocol/constant"
"github.com/openimsdk/protocol/third"
"github.com/openimsdk/tools/errs"
)
type Api struct {

Loading…
Cancel
Save