Исправление Сервера

This commit is contained in:
2026-06-28 00:44:31 +07:00
parent cb19d0b132
commit 3e2648a8ff
3 changed files with 2549 additions and 2537 deletions

View File

@@ -1,190 +1,202 @@
package webserver package webserver
import ( import (
"fmt" "fmt"
"os/exec" "os/exec"
"path/filepath" "path/filepath"
"syscall" "strings"
"time" "syscall"
config "vServer/Backend/config" "time"
tools "vServer/Backend/tools" config "vServer/Backend/config"
) tools "vServer/Backend/tools"
)
var mysqlProcess *exec.Cmd
var mysql_status bool = false var mysqlProcess *exec.Cmd
var mysql_secure bool = false var mysql_status bool = false
var mysql_secure bool = false
// GetMySQLStatus возвращает статус MySQL
func GetMySQLStatus() bool { // GetMySQLStatus возвращает статус MySQL
return mysql_status func GetMySQLStatus() bool {
} return mysql_status
}
var mysqldPath string
var configPath string func normalizeBindAddress(host string) string {
var dataDirAbs string parts := strings.Split(host, ",")
var binDirAbs string cleaned := make([]string, 0, len(parts))
var binPathAbs string for _, part := range parts {
if ip := strings.TrimSpace(part); ip != "" {
var mysql_port int cleaned = append(cleaned, ip)
var mysql_ip string }
}
var console_mysql bool = false return strings.Join(cleaned, ",")
}
func AbsPathMySQL() {
var mysqldPath string
var err error var configPath string
var dataDirAbs string
mysqldPath, err = tools.AbsPath(filepath.Join("WebServer/soft/MySQL/bin", "mysqld.exe")) var binDirAbs string
tools.CheckError(err) var binPathAbs string
configPath, err = tools.AbsPath("WebServer/soft/MySQL/my.ini") var mysql_port int
tools.CheckError(err) var mysql_ip string
dataDirAbs, err = tools.AbsPath("WebServer/soft/MySQL/bin/data") var console_mysql bool = false
tools.CheckError(err)
func AbsPathMySQL() {
binDirAbs, err = tools.AbsPath("WebServer/soft/MySQL/bin")
tools.CheckError(err) var err error
binPathAbs, err = tools.AbsPath("WebServer/soft/MySQL/bin") mysqldPath, err = tools.AbsPath(filepath.Join("WebServer/soft/MySQL/bin", "mysqld.exe"))
tools.CheckError(err) tools.CheckError(err)
} configPath, err = tools.AbsPath("WebServer/soft/MySQL/my.ini")
tools.CheckError(err)
// config_patch возвращает путь к mysqld, аргументы и бинарную директорию
func config_patch(secures bool) (string, []string, string) { dataDirAbs, err = tools.AbsPath("WebServer/soft/MySQL/bin/data")
tools.CheckError(err)
// Получаем абсолютные пути
AbsPathMySQL() binDirAbs, err = tools.AbsPath("WebServer/soft/MySQL/bin")
tools.CheckError(err)
// Объявляем args на уровне функции
var args []string binPathAbs, err = tools.AbsPath("WebServer/soft/MySQL/bin")
tools.CheckError(err)
if secures {
}
args = []string{
"--defaults-file=" + configPath, // config_patch возвращает путь к mysqld, аргументы и бинарную директорию
"--datadir=" + dataDirAbs, func config_patch(secures bool) (string, []string, string) {
"--shared-memory",
"--skip-grant-tables", // Получаем абсолютные пути
"--console", AbsPathMySQL()
}
// Объявляем args на уровне функции
} else { var args []string
args = []string{ if secures {
"--defaults-file=" + configPath,
"--port=" + fmt.Sprintf("%d", mysql_port), args = []string{
"--bind-address=" + mysql_ip, "--defaults-file=" + configPath,
"--datadir=" + dataDirAbs, "--datadir=" + dataDirAbs,
"--console", "--shared-memory",
} "--skip-grant-tables",
"--console",
} }
return mysqldPath, args, binDirAbs } else {
}
args = []string{
// StartMySQLServer запускает MySQL сервер "--defaults-file=" + configPath,
func StartMySQLServer(secure bool) { "--port=" + fmt.Sprintf("%d", mysql_port),
"--bind-address=" + mysql_ip,
mysql_port = config.ConfigData.Soft_Settings.Mysql_port "--datadir=" + dataDirAbs,
mysql_ip = config.ConfigData.Soft_Settings.Mysql_host "--console",
}
if mysql_status {
tools.Logs_file(1, "MySQL", "Сервер MySQL уже запущен", "logs_mysql.log", false) }
return
} return mysqldPath, args, binDirAbs
}
// Настройка режима
mysql_secure = secure // StartMySQLServer запускает MySQL сервер
mysqldPath, args, binDirAbs := config_patch(secure) func StartMySQLServer(secure bool) {
// Выбор сообщения mysql_port = config.ConfigData.Soft_Settings.Mysql_port
if secure { mysql_ip = normalizeBindAddress(config.ConfigData.Soft_Settings.Mysql_host)
tools.Logs_file(0, "MySQL", "Запуск сервера MySQL в режиме безопасности", "logs_mysql.log", false)
} else { if mysql_status {
tools.Logs_file(0, "MySQL", "Запуск сервера MySQL в обычном режиме", "logs_mysql.log", false) tools.Logs_file(1, "MySQL", "Сервер MySQL уже запущен", "logs_mysql.log", false)
} return
}
// Общая логика запуска
mysqlProcess = exec.Command(mysqldPath, args...) // Настройка режима
mysqlProcess.Dir = binDirAbs mysql_secure = secure
tools.Logs_console(mysqlProcess, console_mysql) mysqldPath, args, binDirAbs := config_patch(secure)
tools.Logs_file(0, "MySQL", fmt.Sprintf("Сервер MySQL запущен на %s:%d", mysql_ip, mysql_port), "logs_mysql.log", false) // Выбор сообщения
if secure {
mysql_status = true tools.Logs_file(0, "MySQL", "Запуск сервера MySQL в режиме безопасности", "logs_mysql.log", false)
} else {
} tools.Logs_file(0, "MySQL", "Запуск сервера MySQL в обычном режиме", "logs_mysql.log", false)
}
// StopMySQLServer останавливает MySQL сервер
func StopMySQLServer() { // Общая логика запуска
mysqlProcess = exec.Command(mysqldPath, args...)
if !mysql_status { mysqlProcess.Dir = binDirAbs
return // Уже остановлен tools.Logs_console(mysqlProcess, console_mysql)
}
tools.Logs_file(0, "MySQL", fmt.Sprintf("Сервер MySQL запущен на %s:%d", mysql_ip, mysql_port), "logs_mysql.log", false)
// Сначала пробуем завершить процесс корректно
if mysqlProcess != nil && mysqlProcess.Process != nil { mysql_status = true
mysqlProcess.Process.Kill()
mysqlProcess = nil }
}
// StopMySQLServer останавливает MySQL сервер
// Дополнительно убиваем все mysqld.exe процессы func StopMySQLServer() {
cmd := exec.Command("taskkill", "/F", "/IM", "mysqld.exe")
if !mysql_status {
// Скрываем окно taskkill return // Уже остановлен
cmd.SysProcAttr = &syscall.SysProcAttr{ }
HideWindow: true,
CreationFlags: 0x08000000, // Сначала пробуем завершить процесс корректно
} if mysqlProcess != nil && mysqlProcess.Process != nil {
mysqlProcess.Process.Kill()
cmd.Run() mysqlProcess = nil
}
tools.Logs_file(0, "MySQL", "Сервер MySQL остановлен", "logs_mysql.log", false)
mysql_status = false // Дополнительно убиваем все mysqld.exe процессы
cmd := exec.Command("taskkill", "/F", "/IM", "mysqld.exe")
}
// Скрываем окно taskkill
func ResetPasswordMySQL() { cmd.SysProcAttr = &syscall.SysProcAttr{
HideWindow: true,
NewPasswordMySQL := "root" CreationFlags: 0x08000000,
}
StopMySQLServer()
time.Sleep(2 * time.Second) cmd.Run()
mysql_secure = true
StartMySQLServer(true) tools.Logs_file(0, "MySQL", "Сервер MySQL остановлен", "logs_mysql.log", false)
time.Sleep(2 * time.Second) mysql_status = false
query := "FLUSH PRIVILEGES; ALTER USER 'root'@'%' IDENTIFIED BY '" + NewPasswordMySQL + "';"
СheckMySQLPassword(query) }
tools.Logs_file(0, "MySQL", "Новый пароль: "+NewPasswordMySQL, "logs_mysql.log", true)
println() func ResetPasswordMySQL() {
StopMySQLServer()
StartMySQLServer(false) NewPasswordMySQL := "root"
} StopMySQLServer()
time.Sleep(2 * time.Second)
// СheckMySQLPassword проверяет пароль для MySQL mysql_secure = true
func СheckMySQLPassword(query string) { StartMySQLServer(true)
time.Sleep(2 * time.Second)
AbsPathMySQL() query := "FLUSH PRIVILEGES; ALTER USER 'root'@'%' IDENTIFIED BY '" + NewPasswordMySQL + "';"
СheckMySQLPassword(query)
if mysql_secure { tools.Logs_file(0, "MySQL", "Новый пароль: "+NewPasswordMySQL, "logs_mysql.log", true)
println()
// В безопасном режиме подключаемся без пароля StopMySQLServer()
cmd := exec.Command(filepath.Join(binPathAbs, "mysql.exe"), "-u", "root", "-pRoot", "-e", query) StartMySQLServer(false)
cmd.Dir = binPathAbs
}
// Захватываем вывод для логирования
err := tools.Logs_console(cmd, false) // СheckMySQLPassword проверяет пароль для MySQL
func СheckMySQLPassword(query string) {
if err != nil {
tools.Logs_file(1, "MySQL", "Вывод MySQL (stdout/stderr):", "logs_mysql.log", true) AbsPathMySQL()
} else {
tools.Logs_file(0, "MySQL", "Команда выполнена успешно", "logs_mysql.log", true) if mysql_secure {
}
// В безопасном режиме подключаемся без пароля
} cmd := exec.Command(filepath.Join(binPathAbs, "mysql.exe"), "-u", "root", "-pRoot", "-e", query)
cmd.Dir = binPathAbs
}
// Захватываем вывод для логирования
err := tools.Logs_console(cmd, false)
if err != nil {
tools.Logs_file(1, "MySQL", "Вывод MySQL (stdout/stderr):", "logs_mysql.log", true)
} else {
tools.Logs_file(0, "MySQL", "Команда выполнена успешно", "logs_mysql.log", true)
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,162 +1,162 @@
<script setup> <script setup>
const { t } = useI18n() const { t } = useI18n()
const configStore = useConfigStore() const configStore = useConfigStore()
const servicesStore = useServicesStore() const servicesStore = useServicesStore()
const { success } = useNotification() const { success } = useNotification()
const form = reactive({ const form = reactive({
mysqlHost: '', mysqlHost: '',
mysqlPort: 3306, mysqlPort: 3306,
phpHost: '', phpHost: '',
phpPort: 8000, phpPort: 8000,
proxyEnabled: false, proxyEnabled: false,
acmeEnabled: false, acmeEnabled: false,
}) })
const saving = ref(false) const saving = ref(false)
onMounted(async () => { onMounted(async () => {
await configStore.load() await configStore.load()
const s = configStore.softSettings const s = configStore.softSettings
form.mysqlHost = s.mysql_host || '127.0.0.1' form.mysqlHost = s.mysql_host || '127.0.0.1'
form.mysqlPort = s.mysql_port || 3306 form.mysqlPort = s.mysql_port || 3306
form.phpHost = s.php_host || 'localhost' form.phpHost = s.php_host || 'localhost'
form.phpPort = s.php_port || 8000 form.phpPort = s.php_port || 8000
form.proxyEnabled = s.proxy_enabled || false form.proxyEnabled = s.proxy_enabled || false
form.acmeEnabled = s.ACME_enabled || false form.acmeEnabled = s.ACME_enabled || false
}) })
const saveSettings = async () => { const saveSettings = async () => {
saving.value = true saving.value = true
const configData = { const configData = {
...configStore.data, ...configStore.data,
Soft_Settings: { Soft_Settings: {
mysql_host: form.mysqlHost, mysql_host: form.mysqlHost,
mysql_port: Number(form.mysqlPort), mysql_port: Number(form.mysqlPort),
php_host: form.phpHost, php_host: form.phpHost,
php_port: Number(form.phpPort), php_port: Number(form.phpPort),
proxy_enabled: form.proxyEnabled, proxy_enabled: form.proxyEnabled,
ACME_enabled: form.acmeEnabled, ACME_enabled: form.acmeEnabled,
}, },
} }
await configStore.save(configData) await configStore.save(configData)
await servicesStore.restartAll() await servicesStore.restartAll()
saving.value = false saving.value = false
success(t('notify.settingsSaved')) success(t('notify.settingsSaved'))
} }
const toggleProxy = async () => { const toggleProxy = async () => {
form.proxyEnabled = !form.proxyEnabled form.proxyEnabled = !form.proxyEnabled
if (form.proxyEnabled) await servicesStore.enableProxy() if (form.proxyEnabled) await servicesStore.enableProxy()
else await servicesStore.disableProxy() else await servicesStore.disableProxy()
success(form.proxyEnabled ? t('notify.proxyEnabled') : t('notify.proxyDisabled')) success(form.proxyEnabled ? t('notify.proxyEnabled') : t('notify.proxyDisabled'))
} }
const toggleAcme = async () => { const toggleAcme = async () => {
form.acmeEnabled = !form.acmeEnabled form.acmeEnabled = !form.acmeEnabled
if (form.acmeEnabled) await servicesStore.enableACME() if (form.acmeEnabled) await servicesStore.enableACME()
else await servicesStore.disableACME() else await servicesStore.disableACME()
success(form.acmeEnabled ? t('notify.certManagerEnabled') : t('notify.certManagerDisabled')) success(form.acmeEnabled ? t('notify.certManagerEnabled') : t('notify.certManagerDisabled'))
} }
</script> </script>
<template> <template>
<div class="settings-view"> <div class="settings-view">
<div class="settings-header"> <div class="settings-header">
<VSectionHeader :title="t('settings.title')" /> <VSectionHeader :title="t('settings.title')" />
<VButton variant="success" icon="fas fa-save" :loading="saving" @click="saveSettings"> <VButton variant="success" icon="fas fa-save" :loading="saving" @click="saveSettings">
{{ saving ? t('settings.saving') : t('settings.save') }} {{ saving ? t('settings.saving') : t('settings.save') }}
</VButton> </VButton>
</div> </div>
<div class="settings-grid"> <div class="settings-grid">
<div class="settings-card"> <div class="settings-card">
<h3 class="settings-card-title"><i class="fas fa-database"></i> {{ t('settings.mysql') }}</h3> <h3 class="settings-card-title"><i class="fas fa-database"></i> {{ t('settings.mysql') }}</h3>
<div class="settings-form"> <div class="settings-form">
<VInput v-model="form.mysqlHost" :label="t('settings.hostAddr')" placeholder="127.0.0.1" /> <VInput v-model="form.mysqlHost" :label="t('settings.hostAddr')" placeholder="127.0.0.1, 192.168.1.9" />
<VInput v-model="form.mysqlPort" :label="t('settings.port')" type="number" placeholder="3306" /> <VInput v-model="form.mysqlPort" :label="t('settings.port')" type="number" placeholder="3306" />
</div> </div>
</div> </div>
<div class="settings-card"> <div class="settings-card">
<h3 class="settings-card-title"><i class="fab fa-php"></i> {{ t('settings.php') }}</h3> <h3 class="settings-card-title"><i class="fab fa-php"></i> {{ t('settings.php') }}</h3>
<div class="settings-form"> <div class="settings-form">
<VInput v-model="form.phpHost" :label="t('settings.hostAddr')" placeholder="localhost" /> <VInput v-model="form.phpHost" :label="t('settings.hostAddr')" placeholder="localhost" />
<VInput v-model="form.phpPort" :label="t('settings.port')" type="number" placeholder="8000" /> <VInput v-model="form.phpPort" :label="t('settings.port')" type="number" placeholder="8000" />
</div> </div>
</div> </div>
<div class="settings-card"> <div class="settings-card">
<h3 class="settings-card-title"> <h3 class="settings-card-title">
<VTooltip :text="t('settings.proxyHint')" /> <VTooltip :text="t('settings.proxyHint')" />
<i class="fas fa-network-wired"></i> {{ t('settings.proxyManager') }} <i class="fas fa-network-wired"></i> {{ t('settings.proxyManager') }}
</h3> </h3>
<div class="settings-form"> <div class="settings-form">
<VToggle v-model="form.proxyEnabled" :label="t('settings.proxyManager')" @update:model-value="toggleProxy" /> <VToggle v-model="form.proxyEnabled" :label="t('settings.proxyManager')" @update:model-value="toggleProxy" />
</div> </div>
</div> </div>
<div class="settings-card"> <div class="settings-card">
<h3 class="settings-card-title"> <h3 class="settings-card-title">
<VTooltip :text="t('settings.certHint')" /> <VTooltip :text="t('settings.certHint')" />
<i class="fas fa-certificate"></i> {{ t('settings.certManager') }} <i class="fas fa-certificate"></i> {{ t('settings.certManager') }}
</h3> </h3>
<div class="settings-form"> <div class="settings-form">
<VToggle v-model="form.acmeEnabled" :label="t('settings.certManager')" @update:model-value="toggleAcme" /> <VToggle v-model="form.acmeEnabled" :label="t('settings.certManager')" @update:model-value="toggleAcme" />
</div> </div>
</div> </div>
</div> </div>
</div> </div>
</template> </template>
<style> <style>
.settings-view { .settings-view {
animation: fadeIn var(--transition-slow); animation: fadeIn var(--transition-slow);
} }
.settings-header { .settings-header {
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
align-items: center; align-items: center;
margin-bottom: var(--space-lg); margin-bottom: var(--space-lg);
} }
.settings-grid { .settings-grid {
display: grid; display: grid;
grid-template-columns: repeat(2, 1fr); grid-template-columns: repeat(2, 1fr);
gap: var(--space-lg); gap: var(--space-lg);
} }
.settings-card { .settings-card {
background: rgba(var(--accent-rgb), 0.02); background: rgba(var(--accent-rgb), 0.02);
border: 1px solid var(--glass-border); border: 1px solid var(--glass-border);
border-radius: var(--radius); border-radius: var(--radius);
padding: var(--space-lg); padding: var(--space-lg);
transition: all var(--transition-base); transition: all var(--transition-base);
} }
.settings-card:hover { .settings-card:hover {
background: rgba(var(--accent-rgb), 0.04); background: rgba(var(--accent-rgb), 0.04);
border-color: rgba(var(--accent-rgb), 0.2); border-color: rgba(var(--accent-rgb), 0.2);
} }
.settings-card-title { .settings-card-title {
font-size: var(--text-md); font-size: var(--text-md);
font-weight: var(--font-semibold); font-weight: var(--font-semibold);
color: var(--text-primary); color: var(--text-primary);
margin: 0 0 20px 0; margin: 0 0 20px 0;
padding-bottom: 12px; padding-bottom: 12px;
border-bottom: 1px solid rgba(var(--accent-rgb), 0.1); border-bottom: 1px solid rgba(var(--accent-rgb), 0.1);
display: flex; display: flex;
align-items: center; align-items: center;
gap: var(--space-sm); gap: var(--space-sm);
} }
.settings-card-title i { .settings-card-title i {
color: var(--accent-purple-light); color: var(--accent-purple-light);
} }
@media (max-width: 900px) { @media (max-width: 900px) {
.settings-grid { grid-template-columns: 1fr; } .settings-grid { grid-template-columns: 1fr; }
} }
</style> </style>