elder-yudao-pro/deploy/local/common.ps1

78 lines
3.9 KiB
PowerShell

$ErrorActionPreference = 'Stop'
$repoPath = (Resolve-Path (Join-Path $PSScriptRoot '../..')).Path
$runtimePath = Join-Path $PSScriptRoot '.runtime'
function Read-LocalSettings {
param([string]$Path = (Join-Path $PSScriptRoot 'secrets.psd1'))
if (-not (Test-Path -LiteralPath $Path)) {
throw 'Copy secrets.example.psd1 to secrets.psd1 and fill in the local database password first.'
}
$settings = Import-PowerShellDataFile -LiteralPath $Path
if ($settings.DatabaseName -notmatch '^elder_yudao_[a-z0-9_]+$') {
throw 'Use a separate database named elder_yudao_*; existing application databases are not supported by this initializer.'
}
return $settings
}
function Resolve-LocalProgram {
param([string]$ConfiguredPath, [string]$CommandName, [string]$FallbackPath = '')
if ($ConfiguredPath) {
if (-not (Test-Path -LiteralPath $ConfiguredPath -PathType Leaf)) { throw "Program not found: $ConfiguredPath" }
return (Resolve-Path -LiteralPath $ConfiguredPath).Path
}
$program = Get-Command $CommandName -ErrorAction SilentlyContinue
if ($program) { return $program.Source }
if ($FallbackPath -and (Test-Path -LiteralPath $FallbackPath)) { return $FallbackPath }
throw "Program not found: $CommandName. Install it or set its path in secrets.psd1."
}
function Invoke-LocalMySql {
param([hashtable]$Settings, [string]$Query, [string]$Database = '')
$mysqlExe = Resolve-LocalProgram $Settings.MySqlExe 'mysql.exe' 'C:\Program Files\MySQL\MySQL Server 8.0\bin\mysql.exe'
$arguments = @('--protocol=TCP', "--host=$($Settings.DatabaseHost)", "--port=$($Settings.DatabasePort)",
"--user=$($Settings.DatabaseUser)", '--connect-timeout=5', '--default-character-set=utf8mb4', '--batch', '--skip-column-names')
if ($Database) { $arguments += "--database=$Database" }
$arguments += "--execute=$Query"
$previousPassword = $env:MYSQL_PWD
try {
$env:MYSQL_PWD = $Settings.DatabasePassword
$result = @(& $mysqlExe @arguments)
if ($LASTEXITCODE -ne 0) { throw 'MySQL command failed; see the error above. No password is printed by this script.' }
return $result
} finally {
if ($null -eq $previousPassword) { Remove-Item Env:\MYSQL_PWD -ErrorAction SilentlyContinue }
else { $env:MYSQL_PWD = $previousPassword }
}
}
function Get-LocalServerProcess {
$pidFile = Join-Path $runtimePath 'server.pid'
if (-not (Test-Path -LiteralPath $pidFile)) { return $null }
$serverPid = 0
if (-not [int]::TryParse((Get-Content -LiteralPath $pidFile -Raw).Trim(), [ref]$serverPid)) {
throw 'Invalid server.pid; inspect the runtime directory before continuing.'
}
$process = Get-CimInstance Win32_Process -Filter "ProcessId=$serverPid" -ErrorAction SilentlyContinue
if (-not $process) { return $null }
$jarPath = Join-Path $repoPath 'yudao-server/target/yudao-server.jar'
if ($process.Name -notmatch '^java(w)?\.exe$' -or -not $process.CommandLine.Contains($jarPath)) {
throw 'The recorded PID belongs to another process; refusing to operate on it.'
}
return $process
}
function Get-LocalUiProcess {
$pidFile = Join-Path $runtimePath 'ui.pid'
if (-not (Test-Path -LiteralPath $pidFile)) { return $null }
$uiPid = 0
if (-not [int]::TryParse((Get-Content -LiteralPath $pidFile -Raw).Trim(), [ref]$uiPid)) { throw 'Invalid ui.pid.' }
$process = Get-CimInstance Win32_Process -Filter "ProcessId=$uiPid" -ErrorAction SilentlyContinue
if (-not $process) { return $null }
$vitePaths = @((Join-Path $repoPath 'yudao-ui-admin-vue3/node_modules/vite/bin/vite.js'), (Join-Path $runtimePath 'ui-src/node_modules/vite/bin/vite.js'))
$matchesUiPath = @($vitePaths | Where-Object { $process.CommandLine.Contains($_) }).Count -gt 0
if ($process.Name -ne 'node.exe' -or -not $matchesUiPath) {
throw 'The recorded UI PID belongs to another process; refusing to operate on it.'
}
return $process
}