196 lines
8.1 KiB
PowerShell
196 lines
8.1 KiB
PowerShell
# 本机 YTD-MySQL:用 skip-grant-tables + skip-networking 短暂维护窗口,
|
||
# 重置 root、创建空库 inquiry_robot + 用户,然后恢复服务。
|
||
# 不打印口令。不碰 10.206.0.14 / jeecg-boot。
|
||
$ErrorActionPreference = "Stop"
|
||
$mysqlBin = "C:\yutongda\tools\mysql-8.0.39-winx64\bin"
|
||
$mysql = Join-Path $mysqlBin "mysql.exe"
|
||
$mysqld = Join-Path $mysqlBin "mysqld.exe"
|
||
$ini = "C:\yutongda\tools\mysql-8.0.39-winx64\my.ini"
|
||
$datadir = "C:\yutongda\data\mysql"
|
||
$ops = "E:\wwwroot\ops"
|
||
$secrets = Get-Content (Join-Path $ops "inquiry_robot_db_secrets.json") -Raw | ConvertFrom-Json
|
||
$psql = "C:\yutongda\tools\pgsql\bin\psql.exe"
|
||
|
||
function New-Secret([int]$len = 48) {
|
||
$bytes = New-Object byte[] $len
|
||
[System.Security.Cryptography.RandomNumberGenerator]::Create().GetBytes($bytes)
|
||
return ([Convert]::ToBase64String($bytes) -replace '[+/=]', 'x').Substring(0, [Math]::Min(64, $len))
|
||
}
|
||
|
||
function Test-AppMysql([string]$pass) {
|
||
$out = & $mysql -h127.0.0.1 -P3306 -uinquiry_robot "-p$pass" --connect-timeout=8 --batch -N inquiry_robot -e "SELECT 1" 2>&1
|
||
$text = ($out | ForEach-Object {"$_"}) -join "`n"
|
||
if ($text -match "ERROR\s+\d+") { return $false }
|
||
$lines = $out | ForEach-Object {"$_".Trim()} | Where-Object { $_ -ne "" -and $_ -notmatch "Warning" }
|
||
return ($lines -contains "1")
|
||
}
|
||
|
||
Write-Output "=== preflight: established on 3306? ==="
|
||
$est = @(Get-NetTCPConnection -LocalPort 3306 -State Established -EA SilentlyContinue)
|
||
Write-Output ("established=" + $est.Count)
|
||
if ($est.Count -gt 0) {
|
||
$est | Select-Object -First 5 | ForEach-Object {
|
||
"remote=$($_.RemoteAddress) pid=$($_.OwningProcess)"
|
||
}
|
||
throw "refuse skip-grant: active clients on local 3306"
|
||
}
|
||
|
||
# 生成/复用 root 新口令(仅存 ops,不进 Git)
|
||
$rootStash = Join-Path $ops "local_mysql_root_secret.json"
|
||
if (Test-Path $rootStash) {
|
||
$rootObj = Get-Content $rootStash -Raw | ConvertFrom-Json
|
||
$rootPass = [string]$rootObj.root_password
|
||
} else {
|
||
$rootPass = New-Secret 48
|
||
@{ root_password = $rootPass; createdAt = (Get-Date).ToString("o"); note = "local YTD-MySQL root on app server only" } |
|
||
ConvertTo-Json | Set-Content $rootStash -Encoding UTF8
|
||
}
|
||
$mysqlPass = [string]$secrets.mysql_password
|
||
if ([string]::IsNullOrWhiteSpace($mysqlPass)) { throw "missing secrets.mysql_password" }
|
||
|
||
Write-Output "=== stop YTD-MySQL service ==="
|
||
$svc = Get-Service YTD-MySQL -EA Stop
|
||
if ($svc.Status -ne "Stopped") {
|
||
Stop-Service YTD-MySQL -Force -ErrorAction Stop
|
||
}
|
||
# 确保进程退出
|
||
Start-Sleep -Seconds 2
|
||
Get-Process mysqld -EA SilentlyContinue | ForEach-Object {
|
||
Write-Output ("kill leftover mysqld pid=" + $_.Id)
|
||
Stop-Process -Id $_.Id -Force -EA SilentlyContinue
|
||
}
|
||
Start-Sleep -Seconds 2
|
||
if (Get-Process mysqld -EA SilentlyContinue) { throw "mysqld still running" }
|
||
Write-Output "STOPPED"
|
||
|
||
Write-Output "=== start mysqld skip-grant + skip-networking ==="
|
||
$errLog = Join-Path $ops "mysql-skip-grant.err"
|
||
if (Test-Path $errLog) { Remove-Item $errLog -Force }
|
||
$args = @(
|
||
"--defaults-file=$ini",
|
||
"--datadir=$datadir",
|
||
"--skip-grant-tables",
|
||
"--skip-networking",
|
||
"--shared-memory",
|
||
"--log-error=$errLog"
|
||
)
|
||
$p = Start-Process -FilePath $mysqld -ArgumentList $args -PassThru -WindowStyle Hidden
|
||
Write-Output ("maint_pid=" + $p.Id)
|
||
|
||
# 等可连(shared memory / named pipe,无 TCP)
|
||
$ready = $false
|
||
for ($i = 0; $i -lt 30; $i++) {
|
||
Start-Sleep -Seconds 1
|
||
if ($p.HasExited) {
|
||
Get-Content $errLog -Tail 20 -EA SilentlyContinue
|
||
throw "maint mysqld exited early code=$($p.ExitCode)"
|
||
}
|
||
$out = & $mysql -u root --batch -N -e "SELECT 1" 2>&1
|
||
$lines = $out | ForEach-Object {"$_".Trim()} | Where-Object { $_ -ne "" -and $_ -notmatch "Warning|ERROR" }
|
||
if ($lines -contains "1") { $ready = $true; break }
|
||
}
|
||
if (-not $ready) {
|
||
Get-Content $errLog -Tail 30 -EA SilentlyContinue
|
||
throw "maint mysqld not ready"
|
||
}
|
||
Write-Output "MAINT_READY"
|
||
|
||
Write-Output "=== flush privileges + reset root + create DB ==="
|
||
# skip-grant-tables 下需先 FLUSH PRIVILEGES 才能 ALTER USER
|
||
$sql = @"
|
||
FLUSH PRIVILEGES;
|
||
ALTER USER 'root'@'localhost' IDENTIFIED BY '$rootPass';
|
||
CREATE USER IF NOT EXISTS 'root'@'127.0.0.1' IDENTIFIED BY '$rootPass';
|
||
ALTER USER 'root'@'127.0.0.1' IDENTIFIED BY '$rootPass';
|
||
GRANT ALL PRIVILEGES ON *.* TO 'root'@'localhost' WITH GRANT OPTION;
|
||
GRANT ALL PRIVILEGES ON *.* TO 'root'@'127.0.0.1' WITH GRANT OPTION;
|
||
CREATE DATABASE IF NOT EXISTS ``inquiry_robot`` DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
|
||
CREATE USER IF NOT EXISTS 'inquiry_robot'@'localhost' IDENTIFIED BY '$mysqlPass';
|
||
CREATE USER IF NOT EXISTS 'inquiry_robot'@'127.0.0.1' IDENTIFIED BY '$mysqlPass';
|
||
CREATE USER IF NOT EXISTS 'inquiry_robot'@'%' IDENTIFIED BY '$mysqlPass';
|
||
ALTER USER 'inquiry_robot'@'localhost' IDENTIFIED BY '$mysqlPass';
|
||
ALTER USER 'inquiry_robot'@'127.0.0.1' IDENTIFIED BY '$mysqlPass';
|
||
ALTER USER 'inquiry_robot'@'%' IDENTIFIED BY '$mysqlPass';
|
||
GRANT ALL PRIVILEGES ON ``inquiry_robot``.* TO 'inquiry_robot'@'localhost';
|
||
GRANT ALL PRIVILEGES ON ``inquiry_robot``.* TO 'inquiry_robot'@'127.0.0.1';
|
||
GRANT ALL PRIVILEGES ON ``inquiry_robot``.* TO 'inquiry_robot'@'%';
|
||
FLUSH PRIVILEGES;
|
||
SELECT 'maint_ok' AS s;
|
||
"@
|
||
$sqlPath = Join-Path $ops "sql\_maint_create_inquiry_robot.sql"
|
||
Set-Content $sqlPath -Value $sql -Encoding ascii
|
||
$mout = & $mysql -u root -e "source $($sqlPath -replace '\\','/')" 2>&1 | Out-String
|
||
$mout -split "`r?`n" | ForEach-Object {
|
||
if ($_ -match 'password|IDENTIFIED BY') { return }
|
||
$_
|
||
}
|
||
if ($mout -notmatch "maint_ok") { throw "maint SQL failed" }
|
||
Write-Output "SQL_OK"
|
||
|
||
Write-Output "=== stop maint mysqld ==="
|
||
Stop-Process -Id $p.Id -Force -EA SilentlyContinue
|
||
Start-Sleep -Seconds 2
|
||
# 若仍在,再杀
|
||
Get-Process -Id $p.Id -EA SilentlyContinue | Stop-Process -Force
|
||
Start-Sleep -Seconds 2
|
||
Get-Process mysqld -EA SilentlyContinue | Stop-Process -Force -EA SilentlyContinue
|
||
Start-Sleep -Seconds 2
|
||
if (Get-Process mysqld -EA SilentlyContinue) { throw "could not stop maint mysqld" }
|
||
|
||
Write-Output "=== start YTD-MySQL service ==="
|
||
Start-Service YTD-MySQL
|
||
$okSvc = $false
|
||
for ($i = 0; $i -lt 30; $i++) {
|
||
Start-Sleep -Seconds 1
|
||
$s = (Get-Service YTD-MySQL).Status
|
||
if ($s -eq "Running" -and (Test-AppMysql $mysqlPass)) { $okSvc = $true; break }
|
||
}
|
||
if (-not $okSvc) {
|
||
Write-Output ("service=" + (Get-Service YTD-MySQL).Status)
|
||
throw "service up but app smoke failed"
|
||
}
|
||
Write-Output "MYSQL_CREATED_OK"
|
||
|
||
# 清理含口令临时 SQL
|
||
Remove-Item $sqlPath -Force -EA SilentlyContinue
|
||
Set-Content (Join-Path $ops ".mysql_root_stash.tmp") -Value $rootPass -Encoding ascii -NoNewline
|
||
|
||
Write-Output "=== confirm PG + patch .env ==="
|
||
$env:PGPASSWORD = [string]$secrets.pg_password
|
||
$pgSmoke = & $psql -h 127.0.0.1 -p 5432 -U inquiry_robot_runtime -d inquiry_robot_runtime -tAc "SELECT 'pg_app_ok'" 2>&1
|
||
Write-Output ("PG=" + (($pgSmoke | ForEach-Object {"$_"}) -join " "))
|
||
if (($pgSmoke | Out-String) -notmatch "pg_app_ok") { throw "pg smoke failed" }
|
||
Remove-Item Env:PGPASSWORD -EA SilentlyContinue
|
||
|
||
$envPath = "E:\wwwroot\.env"
|
||
$lines = Get-Content $envPath
|
||
$out = foreach ($line in $lines) {
|
||
if ($line -match '^MYSQL_HOST=') { 'MYSQL_HOST=127.0.0.1' }
|
||
elseif ($line -match '^PG_HOST=') { 'PG_HOST=127.0.0.1' }
|
||
elseif ($line -match '^YTD_MYSQL_URL=') {
|
||
'YTD_MYSQL_URL=jdbc:mysql://127.0.0.1:3306/inquiry_robot?characterEncoding=UTF-8&useUnicode=true&useSSL=false&allowPublicKeyRetrieval=true&tinyInt1isBit=false&serverTimezone=Asia/Shanghai'
|
||
}
|
||
elseif ($line -match '^MYSQL_PASSWORD=') { "MYSQL_PASSWORD=$mysqlPass" }
|
||
elseif ($line -match '^PG_PASSWORD=') { "PG_PASSWORD=$($secrets.pg_password)" }
|
||
else { $line }
|
||
}
|
||
Set-Content $envPath -Value $out -Encoding UTF8
|
||
if (Test-Path "E:\wwwroot\agent\current") {
|
||
Copy-Item $envPath "E:\wwwroot\agent\current\.env" -Force
|
||
}
|
||
|
||
$status = @{
|
||
mysqlHost = "127.0.0.1"
|
||
mysqlDb = "inquiry_robot"
|
||
mysqlCreated = $true
|
||
pgHost = "127.0.0.1"
|
||
pgDb = "inquiry_robot_runtime"
|
||
pgCreated = $true
|
||
note = "Empty DBs on APP-SERVER local instances. MySQL via skip-grant maintenance; root secret in ops/local_mysql_root_secret.json. Not 10.206.0.14."
|
||
updatedAt = (Get-Date).ToString("o")
|
||
needDba = $false
|
||
} | ConvertTo-Json
|
||
Set-Content (Join-Path $ops "data-plane-status.json") -Value $status -Encoding UTF8
|
||
Write-Output $status
|
||
Write-Output "CREATE_ALL_DONE"
|