Bug: Windows PowerShell 5.1 上 supervisor-windows.ps1 无法运行(Join-Path 三参数 + $pid 撞自动变量)
环境
- OS:Windows 10 Pro (10.0.19043)
- Shell:Windows PowerShell 5.1.19041.2364(系统自带)
- 调用方式:
bash scripts/daemon.sh <任意子命令>
现象
在 PS 5.1 上运行任意 daemon.sh 子命令(stop / status / logs / start …)都直接报错,无法管理 bridge。
错误 1(脚本加载阶段):
supervisor-windows.ps1 : A positional parameter cannot be found that accepts argument 'bridge.log'.
+ CategoryInfo : InvalidArgument: (:) [supervisor-windows.ps1], ParameterBindingException
+ FullyQualifiedErrorId : PositionalParameterNotFound,supervisor-windows.ps1
错误 2(修掉错误 1 后执行 stop/status):
supervisor-windows.ps1 : Cannot overwrite variable PID because the variable has been optimized.
+ CategoryInfo : WriteError: (PID:String) [supervisor-windows.ps1],
SessionStateUnauthorizedAccessException
+ FullyQualifiedErrorId : VariableNotWritable,supervisor-windows.ps1
根因
① Join-Path 在 PS 5.1 只支持 2 个位置参数
# scripts/supervisor-windows.ps1:36-37
$LogFile = Join-Path $CtiHome 'logs' 'bridge.log' # 3 个位置参数
$DaemonMjs = Join-Path $SkillDir 'dist' 'daemon.mjs' # 3 个位置参数
PowerShell 7+ 才支持 -AdditionalChildPath / 多个位置参数。PS 5.1 的 Join-Path 仅接受 -Path + -ChildPath,第三个参数无法绑定,脚本在全局赋值阶段就直接抛错,导致所有子命令在加载时即失败。
② $pid 与 PowerShell 自动只读变量 $PID 冲突
function Test-PidAlive {
param([string]$Pid) # 参数名撞 $PID
...
}
# stop / status / start-fallback 分支
$pid = Read-Pid # 给只读自动变量赋值
$PID 是 PowerShell 内置的只读自动变量(当前进程 PID)。PS 变量名不区分大小写,所以 $pid 和 $Pid 都指向它,赋值时抛 VariableNotWritable。
注:脚本里同时存在的 $PidFile(完整名 PidFile)与 $PID 不冲突,可保留。
修复(diff)
--- a/scripts/supervisor-windows.ps1
+++ b/scripts/supervisor-windows.ps1
@@ -33,8 +33,8 @@
$PidFile = Join-Path $RuntimeDir 'bridge.pid'
$StatusFile = Join-Path $RuntimeDir 'status.json'
-$LogFile = Join-Path $CtiHome 'logs' 'bridge.log'
-$DaemonMjs = Join-Path $SkillDir 'dist' 'daemon.mjs'
+$LogFile = Join-Path (Join-Path $CtiHome 'logs') 'bridge.log'
+$DaemonMjs = Join-Path (Join-Path $SkillDir 'dist') 'daemon.mjs'
@@ -74,9 +74,9 @@
function Test-PidAlive {
- param([string]$Pid)
- if (-not $Pid) { return $false }
- try { $null = Get-Process -Id ([int]$Pid) -ErrorAction Stop; return $true }
+ param([string]$ProcId)
+ if (-not $ProcId) { return $false }
+ try { $null = Get-Process -Id ([int]$ProcId) -ErrorAction Stop; return $true }
catch { return $false }
}
@@ -270,1 +270,1 @@
- $pid = Start-Fallback
+ $bridgePid = Start-Fallback
@@ -297,5 +297,5 @@
- $pid = Read-Pid
- if (-not $pid) { Write-Host "No bridge running"; exit 0 }
- if (Test-PidAlive $pid) {
- Stop-Process -Id ([int]$pid) -Force
+ $bridgePid = Read-Pid
+ if (-not $bridgePid) { Write-Host "No bridge running"; exit 0 }
+ if (Test-PidAlive $bridgePid) {
+ Stop-Process -Id ([int]$bridgePid) -Force
@@ -310,3 +310,3 @@
- $pid = Read-Pid
+ $bridgePid = Read-Pid
@@ -318,2 +318,2 @@
- if ($pid -and (Test-PidAlive $pid)) {
- Write-Host "Bridge process is running (PID: $pid)"
+ if ($bridgePid -and (Test-PidAlive $bridgePid)) {
+ Write-Host "Bridge process is running (PID: $bridgePid)"
验证
修复后:
$ bash ~/.claude/skills/claude-to-im/scripts/daemon.sh stop
Windows detected. Delegating to supervisor-windows.ps1...
Bridge stopped
额外建议
- CI 上跑一遍 Windows PowerShell 5.1(GitHub Actions
windows-2019 runner 默认就是 5.1),可以提前发现 PS7-only 语法。
- 仓库里其他脚本(如
doctor.ps1 等未检查全部)可能也有同类问题,建议统一 grep:
rg 'Join-Path\s+\S+\s+\S+\s+\S+' scripts/
rg '\$pid\b' scripts/
- 或者在 daemon 脚本头加版本检查:
if ($PSVersionTable.PSVersion.Major -lt 7) {
Write-Warning "Detected PS $($PSVersionTable.PSVersion). Some features require PowerShell 7+."
}
Bug: Windows PowerShell 5.1 上
supervisor-windows.ps1无法运行(Join-Path三参数 +$pid撞自动变量)环境
bash scripts/daemon.sh <任意子命令>现象
在 PS 5.1 上运行任意
daemon.sh子命令(stop/status/logs/start…)都直接报错,无法管理 bridge。错误 1(脚本加载阶段):
错误 2(修掉错误 1 后执行 stop/status):
根因
①
Join-Path在 PS 5.1 只支持 2 个位置参数PowerShell 7+ 才支持
-AdditionalChildPath/ 多个位置参数。PS 5.1 的Join-Path仅接受-Path+-ChildPath,第三个参数无法绑定,脚本在全局赋值阶段就直接抛错,导致所有子命令在加载时即失败。②
$pid与 PowerShell 自动只读变量$PID冲突$PID是 PowerShell 内置的只读自动变量(当前进程 PID)。PS 变量名不区分大小写,所以$pid和$Pid都指向它,赋值时抛VariableNotWritable。注:脚本里同时存在的
$PidFile(完整名PidFile)与$PID不冲突,可保留。修复(diff)
验证
修复后:
额外建议
windows-2019runner 默认就是 5.1),可以提前发现 PS7-only 语法。doctor.ps1等未检查全部)可能也有同类问题,建议统一 grep: