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

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
import (
"fmt"
"os/exec"
"path/filepath"
"syscall"
"time"
config "vServer/Backend/config"
tools "vServer/Backend/tools"
)
var mysqlProcess *exec.Cmd
var mysql_status bool = false
var mysql_secure bool = false
// GetMySQLStatus возвращает статус MySQL
func GetMySQLStatus() bool {
return mysql_status
}
var mysqldPath string
var configPath string
var dataDirAbs string
var binDirAbs string
var binPathAbs string
var mysql_port int
var mysql_ip string
var console_mysql bool = false
func AbsPathMySQL() {
var err error
mysqldPath, err = tools.AbsPath(filepath.Join("WebServer/soft/MySQL/bin", "mysqld.exe"))
tools.CheckError(err)
configPath, err = tools.AbsPath("WebServer/soft/MySQL/my.ini")
tools.CheckError(err)
dataDirAbs, err = tools.AbsPath("WebServer/soft/MySQL/bin/data")
tools.CheckError(err)
binDirAbs, err = tools.AbsPath("WebServer/soft/MySQL/bin")
tools.CheckError(err)
binPathAbs, err = tools.AbsPath("WebServer/soft/MySQL/bin")
tools.CheckError(err)
}
// config_patch возвращает путь к mysqld, аргументы и бинарную директорию
func config_patch(secures bool) (string, []string, string) {
// Получаем абсолютные пути
AbsPathMySQL()
// Объявляем args на уровне функции
var args []string
if secures {
args = []string{
"--defaults-file=" + configPath,
"--datadir=" + dataDirAbs,
"--shared-memory",
"--skip-grant-tables",
"--console",
}
} else {
args = []string{
"--defaults-file=" + configPath,
"--port=" + fmt.Sprintf("%d", mysql_port),
"--bind-address=" + mysql_ip,
"--datadir=" + dataDirAbs,
"--console",
}
}
return mysqldPath, args, binDirAbs
}
// StartMySQLServer запускает MySQL сервер
func StartMySQLServer(secure bool) {
mysql_port = config.ConfigData.Soft_Settings.Mysql_port
mysql_ip = config.ConfigData.Soft_Settings.Mysql_host
if mysql_status {
tools.Logs_file(1, "MySQL", "Сервер MySQL уже запущен", "logs_mysql.log", false)
return
}
// Настройка режима
mysql_secure = secure
mysqldPath, args, binDirAbs := config_patch(secure)
// Выбор сообщения
if secure {
tools.Logs_file(0, "MySQL", "Запуск сервера MySQL в режиме безопасности", "logs_mysql.log", false)
} else {
tools.Logs_file(0, "MySQL", "Запуск сервера MySQL в обычном режиме", "logs_mysql.log", false)
}
// Общая логика запуска
mysqlProcess = exec.Command(mysqldPath, args...)
mysqlProcess.Dir = binDirAbs
tools.Logs_console(mysqlProcess, console_mysql)
tools.Logs_file(0, "MySQL", fmt.Sprintf("Сервер MySQL запущен на %s:%d", mysql_ip, mysql_port), "logs_mysql.log", false)
mysql_status = true
}
// StopMySQLServer останавливает MySQL сервер
func StopMySQLServer() {
if !mysql_status {
return // Уже остановлен
}
// Сначала пробуем завершить процесс корректно
if mysqlProcess != nil && mysqlProcess.Process != nil {
mysqlProcess.Process.Kill()
mysqlProcess = nil
}
// Дополнительно убиваем все mysqld.exe процессы
cmd := exec.Command("taskkill", "/F", "/IM", "mysqld.exe")
// Скрываем окно taskkill
cmd.SysProcAttr = &syscall.SysProcAttr{
HideWindow: true,
CreationFlags: 0x08000000,
}
cmd.Run()
tools.Logs_file(0, "MySQL", "Сервер MySQL остановлен", "logs_mysql.log", false)
mysql_status = false
}
func ResetPasswordMySQL() {
NewPasswordMySQL := "root"
StopMySQLServer()
time.Sleep(2 * time.Second)
mysql_secure = true
StartMySQLServer(true)
time.Sleep(2 * time.Second)
query := "FLUSH PRIVILEGES; ALTER USER 'root'@'%' IDENTIFIED BY '" + NewPasswordMySQL + "';"
СheckMySQLPassword(query)
tools.Logs_file(0, "MySQL", "Новый пароль: "+NewPasswordMySQL, "logs_mysql.log", true)
println()
StopMySQLServer()
StartMySQLServer(false)
}
// СheckMySQLPassword проверяет пароль для MySQL
func СheckMySQLPassword(query string) {
AbsPathMySQL()
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)
}
}
}
package webserver
import (
"fmt"
"os/exec"
"path/filepath"
"strings"
"syscall"
"time"
config "vServer/Backend/config"
tools "vServer/Backend/tools"
)
var mysqlProcess *exec.Cmd
var mysql_status bool = false
var mysql_secure bool = false
// GetMySQLStatus возвращает статус MySQL
func GetMySQLStatus() bool {
return mysql_status
}
func normalizeBindAddress(host string) string {
parts := strings.Split(host, ",")
cleaned := make([]string, 0, len(parts))
for _, part := range parts {
if ip := strings.TrimSpace(part); ip != "" {
cleaned = append(cleaned, ip)
}
}
return strings.Join(cleaned, ",")
}
var mysqldPath string
var configPath string
var dataDirAbs string
var binDirAbs string
var binPathAbs string
var mysql_port int
var mysql_ip string
var console_mysql bool = false
func AbsPathMySQL() {
var err error
mysqldPath, err = tools.AbsPath(filepath.Join("WebServer/soft/MySQL/bin", "mysqld.exe"))
tools.CheckError(err)
configPath, err = tools.AbsPath("WebServer/soft/MySQL/my.ini")
tools.CheckError(err)
dataDirAbs, err = tools.AbsPath("WebServer/soft/MySQL/bin/data")
tools.CheckError(err)
binDirAbs, err = tools.AbsPath("WebServer/soft/MySQL/bin")
tools.CheckError(err)
binPathAbs, err = tools.AbsPath("WebServer/soft/MySQL/bin")
tools.CheckError(err)
}
// config_patch возвращает путь к mysqld, аргументы и бинарную директорию
func config_patch(secures bool) (string, []string, string) {
// Получаем абсолютные пути
AbsPathMySQL()
// Объявляем args на уровне функции
var args []string
if secures {
args = []string{
"--defaults-file=" + configPath,
"--datadir=" + dataDirAbs,
"--shared-memory",
"--skip-grant-tables",
"--console",
}
} else {
args = []string{
"--defaults-file=" + configPath,
"--port=" + fmt.Sprintf("%d", mysql_port),
"--bind-address=" + mysql_ip,
"--datadir=" + dataDirAbs,
"--console",
}
}
return mysqldPath, args, binDirAbs
}
// StartMySQLServer запускает MySQL сервер
func StartMySQLServer(secure bool) {
mysql_port = config.ConfigData.Soft_Settings.Mysql_port
mysql_ip = normalizeBindAddress(config.ConfigData.Soft_Settings.Mysql_host)
if mysql_status {
tools.Logs_file(1, "MySQL", "Сервер MySQL уже запущен", "logs_mysql.log", false)
return
}
// Настройка режима
mysql_secure = secure
mysqldPath, args, binDirAbs := config_patch(secure)
// Выбор сообщения
if secure {
tools.Logs_file(0, "MySQL", "Запуск сервера MySQL в режиме безопасности", "logs_mysql.log", false)
} else {
tools.Logs_file(0, "MySQL", "Запуск сервера MySQL в обычном режиме", "logs_mysql.log", false)
}
// Общая логика запуска
mysqlProcess = exec.Command(mysqldPath, args...)
mysqlProcess.Dir = binDirAbs
tools.Logs_console(mysqlProcess, console_mysql)
tools.Logs_file(0, "MySQL", fmt.Sprintf("Сервер MySQL запущен на %s:%d", mysql_ip, mysql_port), "logs_mysql.log", false)
mysql_status = true
}
// StopMySQLServer останавливает MySQL сервер
func StopMySQLServer() {
if !mysql_status {
return // Уже остановлен
}
// Сначала пробуем завершить процесс корректно
if mysqlProcess != nil && mysqlProcess.Process != nil {
mysqlProcess.Process.Kill()
mysqlProcess = nil
}
// Дополнительно убиваем все mysqld.exe процессы
cmd := exec.Command("taskkill", "/F", "/IM", "mysqld.exe")
// Скрываем окно taskkill
cmd.SysProcAttr = &syscall.SysProcAttr{
HideWindow: true,
CreationFlags: 0x08000000,
}
cmd.Run()
tools.Logs_file(0, "MySQL", "Сервер MySQL остановлен", "logs_mysql.log", false)
mysql_status = false
}
func ResetPasswordMySQL() {
NewPasswordMySQL := "root"
StopMySQLServer()
time.Sleep(2 * time.Second)
mysql_secure = true
StartMySQLServer(true)
time.Sleep(2 * time.Second)
query := "FLUSH PRIVILEGES; ALTER USER 'root'@'%' IDENTIFIED BY '" + NewPasswordMySQL + "';"
СheckMySQLPassword(query)
tools.Logs_file(0, "MySQL", "Новый пароль: "+NewPasswordMySQL, "logs_mysql.log", true)
println()
StopMySQLServer()
StartMySQLServer(false)
}
// СheckMySQLPassword проверяет пароль для MySQL
func СheckMySQLPassword(query string) {
AbsPathMySQL()
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>
const { t } = useI18n()
const configStore = useConfigStore()
const servicesStore = useServicesStore()
const { success } = useNotification()
const form = reactive({
mysqlHost: '',
mysqlPort: 3306,
phpHost: '',
phpPort: 8000,
proxyEnabled: false,
acmeEnabled: false,
})
const saving = ref(false)
onMounted(async () => {
await configStore.load()
const s = configStore.softSettings
form.mysqlHost = s.mysql_host || '127.0.0.1'
form.mysqlPort = s.mysql_port || 3306
form.phpHost = s.php_host || 'localhost'
form.phpPort = s.php_port || 8000
form.proxyEnabled = s.proxy_enabled || false
form.acmeEnabled = s.ACME_enabled || false
})
const saveSettings = async () => {
saving.value = true
const configData = {
...configStore.data,
Soft_Settings: {
mysql_host: form.mysqlHost,
mysql_port: Number(form.mysqlPort),
php_host: form.phpHost,
php_port: Number(form.phpPort),
proxy_enabled: form.proxyEnabled,
ACME_enabled: form.acmeEnabled,
},
}
await configStore.save(configData)
await servicesStore.restartAll()
saving.value = false
success(t('notify.settingsSaved'))
}
const toggleProxy = async () => {
form.proxyEnabled = !form.proxyEnabled
if (form.proxyEnabled) await servicesStore.enableProxy()
else await servicesStore.disableProxy()
success(form.proxyEnabled ? t('notify.proxyEnabled') : t('notify.proxyDisabled'))
}
const toggleAcme = async () => {
form.acmeEnabled = !form.acmeEnabled
if (form.acmeEnabled) await servicesStore.enableACME()
else await servicesStore.disableACME()
success(form.acmeEnabled ? t('notify.certManagerEnabled') : t('notify.certManagerDisabled'))
}
</script>
<template>
<div class="settings-view">
<div class="settings-header">
<VSectionHeader :title="t('settings.title')" />
<VButton variant="success" icon="fas fa-save" :loading="saving" @click="saveSettings">
{{ saving ? t('settings.saving') : t('settings.save') }}
</VButton>
</div>
<div class="settings-grid">
<div class="settings-card">
<h3 class="settings-card-title"><i class="fas fa-database"></i> {{ t('settings.mysql') }}</h3>
<div class="settings-form">
<VInput v-model="form.mysqlHost" :label="t('settings.hostAddr')" placeholder="127.0.0.1" />
<VInput v-model="form.mysqlPort" :label="t('settings.port')" type="number" placeholder="3306" />
</div>
</div>
<div class="settings-card">
<h3 class="settings-card-title"><i class="fab fa-php"></i> {{ t('settings.php') }}</h3>
<div class="settings-form">
<VInput v-model="form.phpHost" :label="t('settings.hostAddr')" placeholder="localhost" />
<VInput v-model="form.phpPort" :label="t('settings.port')" type="number" placeholder="8000" />
</div>
</div>
<div class="settings-card">
<h3 class="settings-card-title">
<VTooltip :text="t('settings.proxyHint')" />
<i class="fas fa-network-wired"></i> {{ t('settings.proxyManager') }}
</h3>
<div class="settings-form">
<VToggle v-model="form.proxyEnabled" :label="t('settings.proxyManager')" @update:model-value="toggleProxy" />
</div>
</div>
<div class="settings-card">
<h3 class="settings-card-title">
<VTooltip :text="t('settings.certHint')" />
<i class="fas fa-certificate"></i> {{ t('settings.certManager') }}
</h3>
<div class="settings-form">
<VToggle v-model="form.acmeEnabled" :label="t('settings.certManager')" @update:model-value="toggleAcme" />
</div>
</div>
</div>
</div>
</template>
<style>
.settings-view {
animation: fadeIn var(--transition-slow);
}
.settings-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: var(--space-lg);
}
.settings-grid {
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: var(--space-lg);
}
.settings-card {
background: rgba(var(--accent-rgb), 0.02);
border: 1px solid var(--glass-border);
border-radius: var(--radius);
padding: var(--space-lg);
transition: all var(--transition-base);
}
.settings-card:hover {
background: rgba(var(--accent-rgb), 0.04);
border-color: rgba(var(--accent-rgb), 0.2);
}
.settings-card-title {
font-size: var(--text-md);
font-weight: var(--font-semibold);
color: var(--text-primary);
margin: 0 0 20px 0;
padding-bottom: 12px;
border-bottom: 1px solid rgba(var(--accent-rgb), 0.1);
display: flex;
align-items: center;
gap: var(--space-sm);
}
.settings-card-title i {
color: var(--accent-purple-light);
}
@media (max-width: 900px) {
.settings-grid { grid-template-columns: 1fr; }
}
</style>
<script setup>
const { t } = useI18n()
const configStore = useConfigStore()
const servicesStore = useServicesStore()
const { success } = useNotification()
const form = reactive({
mysqlHost: '',
mysqlPort: 3306,
phpHost: '',
phpPort: 8000,
proxyEnabled: false,
acmeEnabled: false,
})
const saving = ref(false)
onMounted(async () => {
await configStore.load()
const s = configStore.softSettings
form.mysqlHost = s.mysql_host || '127.0.0.1'
form.mysqlPort = s.mysql_port || 3306
form.phpHost = s.php_host || 'localhost'
form.phpPort = s.php_port || 8000
form.proxyEnabled = s.proxy_enabled || false
form.acmeEnabled = s.ACME_enabled || false
})
const saveSettings = async () => {
saving.value = true
const configData = {
...configStore.data,
Soft_Settings: {
mysql_host: form.mysqlHost,
mysql_port: Number(form.mysqlPort),
php_host: form.phpHost,
php_port: Number(form.phpPort),
proxy_enabled: form.proxyEnabled,
ACME_enabled: form.acmeEnabled,
},
}
await configStore.save(configData)
await servicesStore.restartAll()
saving.value = false
success(t('notify.settingsSaved'))
}
const toggleProxy = async () => {
form.proxyEnabled = !form.proxyEnabled
if (form.proxyEnabled) await servicesStore.enableProxy()
else await servicesStore.disableProxy()
success(form.proxyEnabled ? t('notify.proxyEnabled') : t('notify.proxyDisabled'))
}
const toggleAcme = async () => {
form.acmeEnabled = !form.acmeEnabled
if (form.acmeEnabled) await servicesStore.enableACME()
else await servicesStore.disableACME()
success(form.acmeEnabled ? t('notify.certManagerEnabled') : t('notify.certManagerDisabled'))
}
</script>
<template>
<div class="settings-view">
<div class="settings-header">
<VSectionHeader :title="t('settings.title')" />
<VButton variant="success" icon="fas fa-save" :loading="saving" @click="saveSettings">
{{ saving ? t('settings.saving') : t('settings.save') }}
</VButton>
</div>
<div class="settings-grid">
<div class="settings-card">
<h3 class="settings-card-title"><i class="fas fa-database"></i> {{ t('settings.mysql') }}</h3>
<div class="settings-form">
<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" />
</div>
</div>
<div class="settings-card">
<h3 class="settings-card-title"><i class="fab fa-php"></i> {{ t('settings.php') }}</h3>
<div class="settings-form">
<VInput v-model="form.phpHost" :label="t('settings.hostAddr')" placeholder="localhost" />
<VInput v-model="form.phpPort" :label="t('settings.port')" type="number" placeholder="8000" />
</div>
</div>
<div class="settings-card">
<h3 class="settings-card-title">
<VTooltip :text="t('settings.proxyHint')" />
<i class="fas fa-network-wired"></i> {{ t('settings.proxyManager') }}
</h3>
<div class="settings-form">
<VToggle v-model="form.proxyEnabled" :label="t('settings.proxyManager')" @update:model-value="toggleProxy" />
</div>
</div>
<div class="settings-card">
<h3 class="settings-card-title">
<VTooltip :text="t('settings.certHint')" />
<i class="fas fa-certificate"></i> {{ t('settings.certManager') }}
</h3>
<div class="settings-form">
<VToggle v-model="form.acmeEnabled" :label="t('settings.certManager')" @update:model-value="toggleAcme" />
</div>
</div>
</div>
</div>
</template>
<style>
.settings-view {
animation: fadeIn var(--transition-slow);
}
.settings-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: var(--space-lg);
}
.settings-grid {
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: var(--space-lg);
}
.settings-card {
background: rgba(var(--accent-rgb), 0.02);
border: 1px solid var(--glass-border);
border-radius: var(--radius);
padding: var(--space-lg);
transition: all var(--transition-base);
}
.settings-card:hover {
background: rgba(var(--accent-rgb), 0.04);
border-color: rgba(var(--accent-rgb), 0.2);
}
.settings-card-title {
font-size: var(--text-md);
font-weight: var(--font-semibold);
color: var(--text-primary);
margin: 0 0 20px 0;
padding-bottom: 12px;
border-bottom: 1px solid rgba(var(--accent-rgb), 0.1);
display: flex;
align-items: center;
gap: var(--space-sm);
}
.settings-card-title i {
color: var(--accent-purple-light);
}
@media (max-width: 900px) {
.settings-grid { grid-template-columns: 1fr; }
}
</style>