Инициализация проекта
Всем привет :)
This commit is contained in:
121
internal/database/pidfile.go
Normal file
121
internal/database/pidfile.go
Normal file
@@ -0,0 +1,121 @@
|
||||
package database
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
"os/exec"
|
||||
"strconv"
|
||||
"strings"
|
||||
"syscall"
|
||||
)
|
||||
|
||||
const pidFile = "/opt/wg_serf/wg_serf.pid"
|
||||
|
||||
// CheckAndKillOldProcess проверяет и завершает старый процесс
|
||||
func CheckAndKillOldProcess() error {
|
||||
// Проверяем существует ли PID файл
|
||||
if _, err := os.Stat(pidFile); os.IsNotExist(err) {
|
||||
// Файла нет - это первый запуск
|
||||
return nil
|
||||
}
|
||||
|
||||
// Читаем PID из файла
|
||||
data, err := os.ReadFile(pidFile)
|
||||
if err != nil {
|
||||
log.Println("⚠️ Не удалось прочитать PID файл:", err)
|
||||
return nil
|
||||
}
|
||||
|
||||
oldPID, err := strconv.Atoi(strings.TrimSpace(string(data)))
|
||||
if err != nil {
|
||||
log.Println("⚠️ Некорректный PID в файле:", err)
|
||||
os.Remove(pidFile)
|
||||
return nil
|
||||
}
|
||||
|
||||
// Проверяем существует ли процесс
|
||||
if !processExists(oldPID) {
|
||||
log.Println("📝 Старый процесс не найден, очищаю PID файл")
|
||||
os.Remove(pidFile)
|
||||
return nil
|
||||
}
|
||||
|
||||
// Проверяем что это действительно wg-panel
|
||||
if !isWGPanelProcess(oldPID) {
|
||||
log.Println("⚠️ PID принадлежит другому процессу, очищаю файл")
|
||||
os.Remove(pidFile)
|
||||
return nil
|
||||
}
|
||||
|
||||
// Завершаем старый процесс
|
||||
log.Printf("🔄 Обнаружена запущенная версия (PID: %d), завершаю...", oldPID)
|
||||
if err := killProcess(oldPID); err != nil {
|
||||
return fmt.Errorf("не удалось завершить старый процесс: %v", err)
|
||||
}
|
||||
|
||||
log.Println("✅ Старый процесс завершен")
|
||||
os.Remove(pidFile)
|
||||
return nil
|
||||
}
|
||||
|
||||
// WritePIDFile записывает PID текущего процесса в файл
|
||||
func WritePIDFile() error {
|
||||
pid := os.Getpid()
|
||||
return os.WriteFile(pidFile, []byte(fmt.Sprintf("%d", pid)), 0644)
|
||||
}
|
||||
|
||||
// RemovePIDFile удаляет PID файл
|
||||
func RemovePIDFile() {
|
||||
os.Remove(pidFile)
|
||||
}
|
||||
|
||||
// processExists проверяет существует ли процесс с данным PID
|
||||
func processExists(pid int) bool {
|
||||
process, err := os.FindProcess(pid)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
|
||||
// Отправляем сигнал 0 для проверки существования процесса
|
||||
err = process.Signal(syscall.Signal(0))
|
||||
return err == nil
|
||||
}
|
||||
|
||||
// isWGPanelProcess проверяет что процесс действительно wg-panel
|
||||
func isWGPanelProcess(pid int) bool {
|
||||
// Читаем командную строку процесса
|
||||
cmdline, err := os.ReadFile(fmt.Sprintf("/proc/%d/cmdline", pid))
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
|
||||
// Проверяем что в командной строке есть wg-panel
|
||||
return strings.Contains(string(cmdline), "wg-panel")
|
||||
}
|
||||
|
||||
// killProcess завершает процесс
|
||||
func killProcess(pid int) error {
|
||||
process, err := os.FindProcess(pid)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Сначала пробуем мягко (SIGTERM)
|
||||
if err := process.Signal(syscall.SIGTERM); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Ждем немного
|
||||
cmd := exec.Command("sleep", "1")
|
||||
cmd.Run()
|
||||
|
||||
// Проверяем завершился ли процесс
|
||||
if processExists(pid) {
|
||||
// Если нет - убиваем принудительно (SIGKILL)
|
||||
log.Println("⚠️ Процесс не завершился, использую SIGKILL")
|
||||
return process.Signal(syscall.SIGKILL)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
Reference in New Issue
Block a user