78 lines
2.8 KiB
PowerShell
78 lines
2.8 KiB
PowerShell
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"
|