refactor: establish standalone application boundary
This commit is contained in:
@@ -0,0 +1,77 @@
|
||||
param(
|
||||
[int]$Port = 8797,
|
||||
[string]$BindAddress = "127.0.0.1"
|
||||
)
|
||||
|
||||
$ErrorActionPreference = "Stop"
|
||||
$root = Split-Path -Parent $PSScriptRoot
|
||||
$runtime = Join-Path $root "runtime"
|
||||
$logs = Join-Path $runtime "logs"
|
||||
$cache = Join-Path $runtime "cache\python"
|
||||
New-Item -ItemType Directory -Force -Path $logs, $cache | Out-Null
|
||||
|
||||
$launcher = Get-Command py -ErrorAction SilentlyContinue
|
||||
if (-not $launcher) {
|
||||
$launcher = Get-Command python -ErrorAction Stop
|
||||
}
|
||||
|
||||
# PowerShell 5.1 cannot start a child process when the host supplies both
|
||||
# Windows' canonical "Path" key and an additional case-variant "PATH" key.
|
||||
$environmentKeys = @([Environment]::GetEnvironmentVariables().Keys)
|
||||
if (($environmentKeys -ccontains "Path") -and ($environmentKeys -ccontains "PATH")) {
|
||||
[Environment]::SetEnvironmentVariable("PATH", $null, [EnvironmentVariableTarget]::Process)
|
||||
}
|
||||
|
||||
$env:PYTHONPYCACHEPREFIX = $cache
|
||||
$stdout = Join-Path $logs "server-$Port.log"
|
||||
$stderr = Join-Path $logs "server-$Port.err.log"
|
||||
|
||||
function Get-ListeningProcessId {
|
||||
param([int]$LocalPort)
|
||||
|
||||
$pattern = "^\s*TCP\s+\S+:$LocalPort\s+\S+\s+LISTENING\s+(\d+)\s*$"
|
||||
$match = netstat -ano -p TCP | Select-String -Pattern $pattern | Select-Object -First 1
|
||||
if ($match) {
|
||||
return [int]$match.Matches[0].Groups[1].Value
|
||||
}
|
||||
return $null
|
||||
}
|
||||
|
||||
$pidFile = Join-Path $runtime "server-$Port.pid"
|
||||
$serverProcessId = Get-ListeningProcessId -LocalPort $Port
|
||||
if ($serverProcessId) {
|
||||
Set-Content -LiteralPath $pidFile -Value $serverProcessId -Encoding ascii
|
||||
Write-Output "Already running PID ${serverProcessId}: http://${BindAddress}:$Port/"
|
||||
Write-Output "Logs: $stdout"
|
||||
exit 0
|
||||
}
|
||||
|
||||
$childCommand = "& '$($launcher.Source.Replace("'", "''"))' -u server.py --host '$($BindAddress.Replace("'", "''"))' --port $Port 1> '$($stdout.Replace("'", "''"))' 2> '$($stderr.Replace("'", "''"))'"
|
||||
$encodedCommand = [Convert]::ToBase64String([Text.Encoding]::Unicode.GetBytes($childCommand))
|
||||
$process = Start-Process `
|
||||
-FilePath (Join-Path $PSHOME "powershell.exe") `
|
||||
-ArgumentList @("-NoProfile", "-ExecutionPolicy", "Bypass", "-EncodedCommand", $encodedCommand) `
|
||||
-WorkingDirectory $root `
|
||||
-WindowStyle Hidden `
|
||||
-PassThru
|
||||
|
||||
$serverProcessId = $null
|
||||
for ($attempt = 0; $attempt -lt 100; $attempt++) {
|
||||
$listeningProcessId = Get-ListeningProcessId -LocalPort $Port
|
||||
if ($listeningProcessId) {
|
||||
$serverProcessId = $listeningProcessId
|
||||
break
|
||||
}
|
||||
if ($process.HasExited) {
|
||||
break
|
||||
}
|
||||
Start-Sleep -Milliseconds 100
|
||||
}
|
||||
if (-not $serverProcessId) {
|
||||
$detail = Get-Content -LiteralPath $stderr -Raw -ErrorAction SilentlyContinue
|
||||
throw "Server did not listen on port $Port. $detail"
|
||||
}
|
||||
|
||||
Set-Content -LiteralPath $pidFile -Value $serverProcessId -Encoding ascii
|
||||
Write-Output "Started PID ${serverProcessId}: http://${BindAddress}:$Port/"
|
||||
Write-Output "Logs: $stdout"
|
||||
Reference in New Issue
Block a user