From 38de5a305f652828341b7143b535d037373c1062 Mon Sep 17 00:00:00 2001 From: oliver Date: Sat, 9 May 2026 11:41:24 +0800 Subject: [PATCH] fix(scripts): resolve repo root by searching oclaw.json Make start/stop scripts robust to directory renames, and improve stop hints when process termination is denied. Co-authored-by: Cursor --- runtime/operations/scripts/start_all.ps1 | 23 +++++++++- runtime/operations/scripts/start_gateway.ps1 | 23 +++++++++- runtime/operations/scripts/start_ops.ps1 | 23 +++++++++- runtime/operations/scripts/stop_desktop.ps1 | 13 +++++- runtime/operations/scripts/stop_gateway.ps1 | 46 ++++++++++++++++--- runtime/operations/scripts/stop_ops.ps1 | 23 +++++++++- .../operations/scripts/stop_wiki_worker.ps1 | 16 +++++++ 7 files changed, 155 insertions(+), 12 deletions(-) diff --git a/runtime/operations/scripts/start_all.ps1 b/runtime/operations/scripts/start_all.ps1 index 12585d29..45eff2e8 100644 --- a/runtime/operations/scripts/start_all.ps1 +++ b/runtime/operations/scripts/start_all.ps1 @@ -21,7 +21,28 @@ function Warn([string]$msg) { Write-Host "[WARN] $msg" -ForegroundColor Yellow } -$repoRoot = Split-Path -Parent (Split-Path -Parent (Split-Path -Parent $PSScriptRoot)) +$repoRoot = $null +function Resolve-RepoRoot([string]$fromDir) { + $cur = (Resolve-Path $fromDir).Path + for ($i = 0; $i -lt 12; $i++) { + $cfg = Join-Path $cur "oclaw.json" + if (Test-Path $cfg) { + return $cur + } + $parent = Split-Path -Parent $cur + if (-not $parent -or $parent -eq $cur) { + break + } + $cur = $parent + } + return $null +} + +$repoRoot = Resolve-RepoRoot $PSScriptRoot +if (-not $repoRoot) { + # Fallback: old relative layout assumption + $repoRoot = Split-Path -Parent (Split-Path -Parent (Split-Path -Parent $PSScriptRoot)) +} $repoParent = Split-Path -Parent $repoRoot Set-Location $repoRoot $env:PYTHONPATH = $repoParent diff --git a/runtime/operations/scripts/start_gateway.ps1 b/runtime/operations/scripts/start_gateway.ps1 index 98d1dd57..ecc6ace1 100644 --- a/runtime/operations/scripts/start_gateway.ps1 +++ b/runtime/operations/scripts/start_gateway.ps1 @@ -17,7 +17,28 @@ function Fail([string]$msg) { exit 1 } -$repoRoot = Split-Path -Parent (Split-Path -Parent (Split-Path -Parent $PSScriptRoot)) +$repoRoot = $null +function Resolve-RepoRoot([string]$fromDir) { + $cur = (Resolve-Path $fromDir).Path + for ($i = 0; $i -lt 12; $i++) { + $cfg = Join-Path $cur "oclaw.json" + if (Test-Path $cfg) { + return $cur + } + $parent = Split-Path -Parent $cur + if (-not $parent -or $parent -eq $cur) { + break + } + $cur = $parent + } + return $null +} + +$repoRoot = Resolve-RepoRoot $PSScriptRoot +if (-not $repoRoot) { + # Fallback: old relative layout assumption + $repoRoot = Split-Path -Parent (Split-Path -Parent (Split-Path -Parent $PSScriptRoot)) +} $repoParent = Split-Path -Parent $repoRoot Set-Location $repoRoot diff --git a/runtime/operations/scripts/start_ops.ps1 b/runtime/operations/scripts/start_ops.ps1 index ca2ab14f..5dab38b4 100644 --- a/runtime/operations/scripts/start_ops.ps1 +++ b/runtime/operations/scripts/start_ops.ps1 @@ -15,7 +15,28 @@ function Fail([string]$msg) { exit 1 } -$repoRoot = Split-Path -Parent (Split-Path -Parent (Split-Path -Parent $PSScriptRoot)) +$repoRoot = $null +function Resolve-RepoRoot([string]$fromDir) { + $cur = (Resolve-Path $fromDir).Path + for ($i = 0; $i -lt 12; $i++) { + $cfg = Join-Path $cur "oclaw.json" + if (Test-Path $cfg) { + return $cur + } + $parent = Split-Path -Parent $cur + if (-not $parent -or $parent -eq $cur) { + break + } + $cur = $parent + } + return $null +} + +$repoRoot = Resolve-RepoRoot $PSScriptRoot +if (-not $repoRoot) { + # Fallback: old relative layout assumption + $repoRoot = Split-Path -Parent (Split-Path -Parent (Split-Path -Parent $PSScriptRoot)) +} $repoParent = Split-Path -Parent $repoRoot Set-Location $repoRoot diff --git a/runtime/operations/scripts/stop_desktop.ps1 b/runtime/operations/scripts/stop_desktop.ps1 index 0c7fa0cf..da2bb9ad 100644 --- a/runtime/operations/scripts/stop_desktop.ps1 +++ b/runtime/operations/scripts/stop_desktop.ps1 @@ -12,6 +12,11 @@ function Warn([string]$msg) { Write-Host "[WARN] $msg" -ForegroundColor Yellow } +function Warn-AccessHint([string]$contextMsg) { + Warn $contextMsg + Write-Host " Hint: If you see 'Access is denied', re-run this terminal as Administrator." -ForegroundColor Yellow +} + $runDir = Join-Path $PSScriptRoot ".run" $pidFile = Join-Path $runDir "desktop.pid" @@ -45,7 +50,13 @@ try { Remove-Item $pidFile -Force -ErrorAction SilentlyContinue exit 0 } catch { - Warn "Failed to stop PID=$procId : $($_.Exception.Message)" + $msg = "$($_.Exception.Message)" + if ($msg -match "denied|Access is denied|0x80070005|拒绝访问|拒绝") { + Warn-AccessHint "Failed to stop PID=$procId : $msg" + } else { + Warn "Failed to stop PID=$procId : $msg" + Write-Host " Hint: If the process cannot be stopped due to permissions, re-run as Administrator." -ForegroundColor Yellow + } if (-not $Force) { exit 1 } exit 0 } diff --git a/runtime/operations/scripts/stop_gateway.ps1 b/runtime/operations/scripts/stop_gateway.ps1 index cf088fd6..cfcda1f7 100644 --- a/runtime/operations/scripts/stop_gateway.ps1 +++ b/runtime/operations/scripts/stop_gateway.ps1 @@ -13,7 +13,12 @@ function Warn([string]$msg) { Write-Host "[WARN] $msg" -ForegroundColor Yellow } -function Kill-ProcId([int]$procId) { +function Warn-AccessHint([string]$contextMsg) { + Warn $contextMsg + Write-Host " Hint: If you see 'Access is denied', re-run this terminal as Administrator." -ForegroundColor Yellow +} + +function Kill-ProcId([int]$procId, [bool]$forceKill) { $exists = $null try { $exists = Get-Process -Id $procId -ErrorAction SilentlyContinue @@ -25,11 +30,24 @@ function Kill-ProcId([int]$procId) { return $true } try { - Stop-Process -Id $procId -Force + Stop-Process -Id $procId -Force:$forceKill Write-Host "Stopped PID=$procId" -ForegroundColor Green return $true } catch { - Warn "Failed to stop PID=$procId : $($_.Exception.Message)" + $ex = $_.Exception + $msg = "$($ex.Message)" + $hresult = $null + try { $hresult = $ex.HResult } catch { $hresult = $null } + $isAccessDenied = $false + if ($msg -match "denied|Access is denied|0x80070005") { $isAccessDenied = $true } + if ($hresult -eq -2147024891) { $isAccessDenied = $true } # 0x80070005 Access is denied + + if ($isAccessDenied) { + Warn-AccessHint "Failed to stop PID=$procId : $msg" + } else { + Warn "Failed to stop PID=$procId : $msg" + Write-Host " Hint: If the process cannot be stopped due to permissions, re-run as Administrator." -ForegroundColor Yellow + } return $false } } @@ -44,7 +62,8 @@ if (Test-Path $pidFile) { $procId = 0 [void][int]::TryParse([string]$raw, [ref]$procId) if ($procId -gt 0) { - $ok = Kill-ProcId -procId $procId + Write-Step "Attempting to stop by PID file: $pidFile (PID=$procId)" + $ok = Kill-ProcId -procId $procId -forceKill ([bool]$Force) if ($ok) { Remove-Item $pidFile -Force -ErrorAction SilentlyContinue # Keep going to also clean up any orphan listeners on $Port. @@ -59,7 +78,7 @@ if (Test-Path $pidFile) { } } -Write-Step "No PID file; attempting to stop by port $Port" +Write-Step "Attempting to stop by port $Port" try { $conns = Get-NetTCPConnection -LocalPort $Port -State Listen -ErrorAction SilentlyContinue if (-not $conns) { @@ -68,11 +87,24 @@ try { } $pids = $conns | Select-Object -ExpandProperty OwningProcess -Unique foreach ($p in $pids) { - if ($p -gt 0) { [void](Kill-ProcId -procId $p) } + if ($p -gt 0) { [void](Kill-ProcId -procId $p -forceKill ([bool]$Force)) } } exit 0 } catch { - Warn "Stop by port failed: $($_.Exception.Message)" + $ex = $_.Exception + $msg = "$($ex.Message)" + $hresult = $null + try { $hresult = $ex.HResult } catch { $hresult = $null } + $isAccessDenied = $false + if ($msg -match "denied|Access is denied|0x80070005") { $isAccessDenied = $true } + if ($hresult -eq -2147024891) { $isAccessDenied = $true } # 0x80070005 Access is denied + + if ($isAccessDenied) { + Warn-AccessHint "Stop by port failed: $msg" + } else { + Warn "Stop by port failed: $msg" + Write-Host " Hint: If the listener cannot be stopped due to permissions, re-run as Administrator." -ForegroundColor Yellow + } if (-not $Force) { exit 1 } } diff --git a/runtime/operations/scripts/stop_ops.ps1 b/runtime/operations/scripts/stop_ops.ps1 index bf7ee510..ea8030b9 100644 --- a/runtime/operations/scripts/stop_ops.ps1 +++ b/runtime/operations/scripts/stop_ops.ps1 @@ -8,7 +8,28 @@ function Write-Step([string]$msg) { Write-Host "==> $msg" -ForegroundColor Cyan } -$repoRoot = Split-Path -Parent (Split-Path -Parent (Split-Path -Parent $PSScriptRoot)) +$repoRoot = $null +function Resolve-RepoRoot([string]$fromDir) { + $cur = (Resolve-Path $fromDir).Path + for ($i = 0; $i -lt 12; $i++) { + $cfg = Join-Path $cur "oclaw.json" + if (Test-Path $cfg) { + return $cur + } + $parent = Split-Path -Parent $cur + if (-not $parent -or $parent -eq $cur) { + break + } + $cur = $parent + } + return $null +} + +$repoRoot = Resolve-RepoRoot $PSScriptRoot +if (-not $repoRoot) { + # Fallback: old relative layout assumption + $repoRoot = Split-Path -Parent (Split-Path -Parent (Split-Path -Parent $PSScriptRoot)) +} $repoParent = Split-Path -Parent $repoRoot Set-Location $repoRoot $env:PYTHONPATH = $repoParent diff --git a/runtime/operations/scripts/stop_wiki_worker.ps1 b/runtime/operations/scripts/stop_wiki_worker.ps1 index 80eef716..8856a191 100644 --- a/runtime/operations/scripts/stop_wiki_worker.ps1 +++ b/runtime/operations/scripts/stop_wiki_worker.ps1 @@ -6,6 +6,15 @@ $ErrorActionPreference = "Stop" $runDir = Join-Path $PSScriptRoot ".run" $pidFile = Join-Path $runDir "wiki_worker.pid" +function Warn([string]$msg) { + Write-Host "[WARN] $msg" -ForegroundColor Yellow +} + +function Warn-AccessHint([string]$contextMsg) { + Warn $contextMsg + Write-Host " Hint: If you see 'Access is denied', re-run this terminal as Administrator." -ForegroundColor Yellow +} + if (-not (Test-Path $pidFile)) { Write-Host "[ok] not running (no pid file)" exit 0 @@ -25,6 +34,13 @@ try { taskkill.exe /PID $procId /T | Out-Null } } catch { + $msg = "$($_.Exception.Message)" + if ($msg -match "denied|Access is denied|0x80070005|拒绝访问|拒绝") { + Warn-AccessHint "Failed to stop wiki worker pid=$procId : $msg" + } else { + Warn "Failed to stop wiki worker pid=$procId : $msg" + Write-Host " Hint: If the process cannot be stopped due to permissions, re-run as Administrator." -ForegroundColor Yellow + } } Remove-Item -Force $pidFile -ErrorAction SilentlyContinue