Инициализация проекта
Стабильный рабочий проект.
This commit is contained in:
25
Backend/tools/AbsPatch.go
Normal file
25
Backend/tools/AbsPatch.go
Normal file
@@ -0,0 +1,25 @@
|
||||
package tools
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// getAbsPath получает абсолютный путь с автоматической проверкой существования для файлов
|
||||
func AbsPath(path string) (string, error) {
|
||||
absPath, err := filepath.Abs(path)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("ошибка получения абсолютного пути: %v", err)
|
||||
}
|
||||
|
||||
// Проверяем существование только для файлов (с расширением)
|
||||
if strings.Contains(filepath.Base(absPath), ".") {
|
||||
if _, err := os.Stat(absPath); os.IsNotExist(err) {
|
||||
return "", fmt.Errorf("файл не найден: %s", absPath)
|
||||
}
|
||||
}
|
||||
|
||||
return absPath, nil
|
||||
}
|
79
Backend/tools/FunctionAll.go
Normal file
79
Backend/tools/FunctionAll.go
Normal file
@@ -0,0 +1,79 @@
|
||||
package tools
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
"time"
|
||||
)
|
||||
|
||||
// Время запуска сервера
|
||||
var ServerStartTime time.Time
|
||||
|
||||
// isPortInUse проверяет, занят ли указанный порт
|
||||
func Port_check(service string, host string, port string) bool {
|
||||
conn, err := net.DialTimeout("tcp", host+":"+port, time.Millisecond*300)
|
||||
if err != nil {
|
||||
return false // порт свободен
|
||||
}
|
||||
conn.Close()
|
||||
Logs_file(1, service, "⚠️ Порт "+port+" уже занят, сервис не запущен", "logs_error.log", true)
|
||||
return true // порт занят
|
||||
}
|
||||
|
||||
// Управление временем работы сервера
|
||||
func ServerUptime(action string, asSeconds ...bool) interface{} {
|
||||
switch action {
|
||||
case "start":
|
||||
// Инициализация времени запуска
|
||||
ServerStartTime = time.Now()
|
||||
return nil
|
||||
|
||||
case "get":
|
||||
// Получить время работы
|
||||
if ServerStartTime.IsZero() {
|
||||
if len(asSeconds) > 0 && asSeconds[0] {
|
||||
return int64(0)
|
||||
}
|
||||
return "Сервер не запущен"
|
||||
}
|
||||
|
||||
uptime := time.Since(ServerStartTime)
|
||||
|
||||
// Возвращаем секунды
|
||||
if len(asSeconds) > 0 && asSeconds[0] {
|
||||
return int64(uptime.Seconds())
|
||||
}
|
||||
|
||||
// Возвращаем читаемый формат
|
||||
days := int(uptime.Hours()) / 24
|
||||
hours := int(uptime.Hours()) % 24
|
||||
minutes := int(uptime.Minutes()) % 60
|
||||
seconds := int(uptime.Seconds()) % 60
|
||||
|
||||
if days > 0 {
|
||||
return fmt.Sprintf("%dд %dч %dм", days, hours, minutes)
|
||||
} else if hours > 0 {
|
||||
return fmt.Sprintf("%dч %dм", hours, minutes)
|
||||
} else if minutes > 0 {
|
||||
return fmt.Sprintf("%dм", minutes)
|
||||
} else {
|
||||
return fmt.Sprintf("%dс", seconds)
|
||||
}
|
||||
|
||||
default:
|
||||
return "Неизвестное действие"
|
||||
}
|
||||
}
|
||||
|
||||
func Error_check(err error, message string) bool {
|
||||
if err != nil {
|
||||
fmt.Printf("Ошибка: %v\n", message)
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
10
Backend/tools/check_error.go
Normal file
10
Backend/tools/check_error.go
Normal file
@@ -0,0 +1,10 @@
|
||||
package tools
|
||||
|
||||
|
||||
func CheckError(err error) error {
|
||||
if err != nil {
|
||||
return err
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
}
|
131
Backend/tools/cmd_go.go
Normal file
131
Backend/tools/cmd_go.go
Normal file
@@ -0,0 +1,131 @@
|
||||
//go:build windows
|
||||
|
||||
package tools
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"os"
|
||||
"os/exec"
|
||||
"syscall"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
var (
|
||||
kernel32 = syscall.NewLazyDLL("kernel32.dll")
|
||||
procSetConsoleMode = kernel32.NewProc("SetConsoleMode")
|
||||
procGetConsoleMode = kernel32.NewProc("GetConsoleMode")
|
||||
procCreateMutex = kernel32.NewProc("CreateMutexW")
|
||||
procCloseHandle = kernel32.NewProc("CloseHandle")
|
||||
)
|
||||
|
||||
const ENABLE_VIRTUAL_TERMINAL_PROCESSING = 0x0004
|
||||
|
||||
var mutexHandle syscall.Handle
|
||||
|
||||
func init() {
|
||||
enableVirtualTerminal()
|
||||
|
||||
}
|
||||
|
||||
func enableVirtualTerminal() {
|
||||
handle := os.Stdout.Fd()
|
||||
var mode uint32
|
||||
|
||||
// Получаем текущий режим консоли
|
||||
_, _, _ = procGetConsoleMode.Call(uintptr(handle), uintptr(unsafe.Pointer(&mode)))
|
||||
|
||||
// Добавляем флаг поддержки ANSI
|
||||
mode |= ENABLE_VIRTUAL_TERMINAL_PROCESSING
|
||||
|
||||
// Устанавливаем новый режим
|
||||
_, _, _ = procSetConsoleMode.Call(uintptr(handle), uintptr(mode))
|
||||
}
|
||||
|
||||
func RunBatScript(script string) (string, error) {
|
||||
// Создание временного файла
|
||||
tmpFile, err := os.CreateTemp("", "script-*.bat")
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("ошибка создания temp-файла: %w", err)
|
||||
}
|
||||
defer os.Remove(tmpFile.Name())
|
||||
|
||||
// Запись скрипта в файл
|
||||
if _, err := tmpFile.WriteString(script); err != nil {
|
||||
return "", fmt.Errorf("ошибка записи в temp-файл: %w", err)
|
||||
}
|
||||
tmpFile.Close()
|
||||
|
||||
// Выполняем файл через cmd
|
||||
cmd := exec.Command("cmd", "/C", tmpFile.Name())
|
||||
output, err := cmd.CombinedOutput()
|
||||
|
||||
return string(output), err
|
||||
}
|
||||
|
||||
// Функция для логирования вывода процесса в консоль
|
||||
func Logs_console(process *exec.Cmd, check bool) error {
|
||||
|
||||
if check {
|
||||
// Настраиваем pipes для захвата вывода
|
||||
stdout, err := process.StdoutPipe()
|
||||
CheckError(err)
|
||||
stderr, err := process.StderrPipe()
|
||||
CheckError(err)
|
||||
|
||||
// Запускаем процесс
|
||||
process.Start()
|
||||
|
||||
// Захватываем stdout и stderr для вывода логов
|
||||
go func() {
|
||||
scanner := bufio.NewScanner(stdout)
|
||||
for scanner.Scan() {
|
||||
fmt.Println(scanner.Text())
|
||||
}
|
||||
}()
|
||||
|
||||
go func() {
|
||||
scanner := bufio.NewScanner(stderr)
|
||||
for scanner.Scan() {
|
||||
fmt.Println(scanner.Text())
|
||||
}
|
||||
}()
|
||||
} else {
|
||||
// Просто запускаем процесс без логирования
|
||||
return process.Start()
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// CheckSingleInstance проверяет, не запущена ли программа уже через мьютекс
|
||||
func CheckSingleInstance() bool {
|
||||
mutexName, _ := syscall.UTF16PtrFromString("Global\\vServer_SingleInstance")
|
||||
|
||||
handle, _, err := procCreateMutex.Call(
|
||||
0,
|
||||
0,
|
||||
uintptr(unsafe.Pointer(mutexName)),
|
||||
)
|
||||
|
||||
if handle == 0 {
|
||||
return false // не удалось создать мьютекс
|
||||
}
|
||||
|
||||
mutexHandle = syscall.Handle(handle)
|
||||
|
||||
// Если GetLastError возвращает ERROR_ALREADY_EXISTS (183), значит мьютекс уже существует
|
||||
if err.(syscall.Errno) == 183 {
|
||||
return false // программа уже запущена
|
||||
}
|
||||
|
||||
return true // успешно создали мьютекс, программа не запущена
|
||||
}
|
||||
|
||||
// ReleaseMutex освобождает мьютекс при завершении программы
|
||||
func ReleaseMutex() {
|
||||
if mutexHandle != 0 {
|
||||
procCloseHandle.Call(uintptr(mutexHandle))
|
||||
mutexHandle = 0
|
||||
}
|
||||
}
|
88
Backend/tools/message.go
Normal file
88
Backend/tools/message.go
Normal file
@@ -0,0 +1,88 @@
|
||||
package tools
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
"regexp"
|
||||
"time"
|
||||
)
|
||||
|
||||
const (
|
||||
Красный = "\033[31m"
|
||||
Зелёный = "\033[32m"
|
||||
Жёлтый = "\033[33m"
|
||||
Синий = "\033[34m"
|
||||
Голубой = "\033[36m"
|
||||
Фиолетовый = "\033[35m"
|
||||
Белый = "\033[37m"
|
||||
Серый = "\033[90m"
|
||||
Оранжевый = "\033[38;5;208m"
|
||||
Сброс_Цвета = "\033[0m"
|
||||
)
|
||||
|
||||
// Функция окрашивания текста
|
||||
func Color(text, ansi string) string {
|
||||
return ansi + text + Сброс_Цвета
|
||||
}
|
||||
|
||||
// Функция для удаления ANSI-кодов из строки
|
||||
func RemoveAnsiCodes(text string) string {
|
||||
// Регулярное выражение для удаления ANSI escape sequences
|
||||
ansiRegex := regexp.MustCompile(`\x1b\[[0-9;]*[a-zA-Z]`)
|
||||
return ansiRegex.ReplaceAllString(text, "")
|
||||
}
|
||||
|
||||
// Логирование в файл
|
||||
/*
|
||||
type_log:
|
||||
0 - INFO
|
||||
1 - ERROR
|
||||
2 - WARNING
|
||||
*/
|
||||
func Logs_file(type_log int, service string, message string, log_file string, console bool) {
|
||||
|
||||
color_data := ""
|
||||
|
||||
service_str := Color(" ["+service+"] ", Жёлтый)
|
||||
type_log_str := Color(" [INFO] ", Голубой)
|
||||
log_files := log_file
|
||||
|
||||
switch type_log {
|
||||
case 0:
|
||||
type_log_str = Color(" [-INFOS-]", Голубой)
|
||||
case 1:
|
||||
type_log_str = Color(" [-ERROR-]", Красный)
|
||||
case 2:
|
||||
type_log_str = Color(" [WARNING]", Жёлтый)
|
||||
}
|
||||
|
||||
if type_log == 1 {
|
||||
color_data = Красный
|
||||
} else {
|
||||
color_data = Зелёный
|
||||
}
|
||||
|
||||
if console {
|
||||
// Очищаем текущую строку (стираем промпт >) и выводим лог с новой строки
|
||||
fmt.Print("\r\033[K")
|
||||
fmt.Println(Color(time.Now().Format("2006-01-02 15:04:05")+type_log_str+service_str+message, color_data))
|
||||
}
|
||||
|
||||
// Создаем текст с цветами, затем удаляем ANSI-коды для файла
|
||||
colored_text := time.Now().Format("2006-01-02 15:04:05") + type_log_str + service_str + message
|
||||
text := RemoveAnsiCodes(colored_text) + "\n"
|
||||
|
||||
// Открываем файл для дозаписи, создаём если нет, права на запись.
|
||||
file, err := os.OpenFile("WebServer/tools/logs/"+log_files, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
defer file.Close()
|
||||
|
||||
// Пишем строку в файл
|
||||
if _, err := file.WriteString(text); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
}
|
72
Backend/tools/powershell_runner.go
Normal file
72
Backend/tools/powershell_runner.go
Normal file
@@ -0,0 +1,72 @@
|
||||
package tools
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"os/exec"
|
||||
"strings"
|
||||
"sync"
|
||||
)
|
||||
|
||||
// Глобальная persistent PowerShell сессия
|
||||
var (
|
||||
psCmd *exec.Cmd
|
||||
psStdin *bufio.Writer
|
||||
psStdout *bufio.Scanner
|
||||
psMutex sync.Mutex
|
||||
)
|
||||
|
||||
// RunPersistentScript выполняет команды через постоянную PowerShell сессию
|
||||
func RunPersistentScript(commands []string) string {
|
||||
psMutex.Lock()
|
||||
defer psMutex.Unlock()
|
||||
|
||||
// Инициализируем если еще не запущен
|
||||
if psCmd == nil {
|
||||
psCmd = exec.Command("powershell", "-NoExit", "-Command", "-")
|
||||
stdin, _ := psCmd.StdinPipe()
|
||||
stdout, _ := psCmd.StdoutPipe()
|
||||
psStdin = bufio.NewWriter(stdin)
|
||||
psStdout = bufio.NewScanner(stdout)
|
||||
psCmd.Start()
|
||||
}
|
||||
|
||||
// Выполняем команды
|
||||
fullCommand := strings.Join(commands, "; ")
|
||||
psStdin.WriteString(fullCommand + "; Write-Output '---END---'\n")
|
||||
psStdin.Flush()
|
||||
|
||||
// Читаем результат - только последняя строка с данными
|
||||
var lastLine string
|
||||
for psStdout.Scan() {
|
||||
line := psStdout.Text()
|
||||
if line == "---END---" {
|
||||
break
|
||||
}
|
||||
if strings.TrimSpace(line) != "" {
|
||||
lastLine = line
|
||||
}
|
||||
}
|
||||
|
||||
return lastLine
|
||||
}
|
||||
|
||||
// RunPowerShellCommand выполняет PowerShell команду и возвращает результат
|
||||
// Если ошибка - возвращает текст ошибки в строке
|
||||
func RunPScode(command string) string {
|
||||
cmd := exec.Command("powershell", "-Command", command)
|
||||
|
||||
output, err := cmd.Output()
|
||||
if err != nil {
|
||||
return "ERROR: " + err.Error()
|
||||
}
|
||||
|
||||
return strings.TrimSpace(string(output))
|
||||
}
|
||||
|
||||
// RunPowerShellScript выполняет несколько команд PowerShell
|
||||
func RunPowerShellScript(commands []string) string {
|
||||
// Объединяем команды через точку с запятой
|
||||
fullCommand := strings.Join(commands, "; ")
|
||||
|
||||
return RunPScode(fullCommand)
|
||||
}
|
Reference in New Issue
Block a user