Merge agent-watchdog 79b80c89 into master (gate: green on 56157f5d, recorded by tools/ci/pre-push.sh; landed on the box mirror)
This commit is contained in:
commit
03a13ceaa4
4 changed files with 76 additions and 7 deletions
|
|
@ -1,6 +1,6 @@
|
|||
# The relay agent as a logon task (IgneumRelayService, registered by install-agent.ps1 from IgneumRelayService.xml).
|
||||
# This loop keeps igneum-agent.ps1 running with no window: the Task Scheduler restarts this loop on failure (PT1M, 999
|
||||
# times), and the loop restarts the agent 15 s after any exit, so the agent outlives the app, a crash of its own, and a
|
||||
# times), and the loop restarts the agent 10 s after any exit, so the agent outlives the app, a crash of its own, and a
|
||||
# reboot (the task fires at logon; the PC signs in by itself). MF-11, 7 October 2026: PC 2's agent had been dead since
|
||||
# 6 October and its one-shot logon task exited at every boot, so neither a signed job nor a relay task could start the app.
|
||||
# Output goes to %LOCALAPPDATA%\igneum-relay\logs\agent-service.log (5 MB, one rotation); the idle line is left out.
|
||||
|
|
@ -19,7 +19,7 @@ while ($true) {
|
|||
# one Add-Content per line, so the file is never held open: a reader (a job's Get-Content -Tail) is refused while a
|
||||
# pipeline holds it (PC 2, 7 October 2026, 15:38 local: "being used by another process")
|
||||
& powershell.exe -NoProfile -ExecutionPolicy Bypass -File $Agent 2>&1 | ForEach-Object { "$_" } | Where-Object { $_ -notmatch 'idle as ' } | ForEach-Object { Add-Content -Path $log -Value $_ }
|
||||
Note ('agent exited with code ' + $LASTEXITCODE + '; again in 15 s')
|
||||
} catch { Note ('agent failed to start: ' + $_.Exception.Message + '; again in 15 s') }
|
||||
Start-Sleep -Seconds 15
|
||||
Note ('agent exited with code ' + $LASTEXITCODE + '; again in 10 s')
|
||||
} catch { Note ('agent failed to start: ' + $_.Exception.Message + '; again in 10 s') }
|
||||
Start-Sleep -Seconds 10
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,8 +6,13 @@
|
|||
# the task. Every IgneumRelayAgent* task (the one-shot reboot arms of X25) and the RunOnce key go first: on PC 2 a stale
|
||||
# one pointed at a path that was not there and popped "Windows cannot find 'igneum-agent'" at every boot (7 October 2026).
|
||||
# A failure here is a line on stdout and an exit code, never a dialog.
|
||||
# powershell -ExecutionPolicy Bypass -File install-agent.ps1 [-Highest] [-Remove]
|
||||
param([switch]$Highest, [switch]$Remove)
|
||||
# The watchdog (watchdog.ps1 beside this file; 9 October 2026, the founder's rule that no machine needs a hand to
|
||||
# recover): two more tasks, IgneumRelayWatchdog every 5 minutes and IgneumRelayWatchdogLogon a minute after logon, start
|
||||
# the service task when the agent's pid is dead (the logon one as a loop checking every 10 s, so the agent is back within
|
||||
# 15 s) and register it again when it is missing, so the agent outlives the
|
||||
# engine's update, restart, quit and a reboot. -NoWatchdog skips them (the watchdog itself calls this script with it).
|
||||
# powershell -ExecutionPolicy Bypass -File install-agent.ps1 [-Highest] [-Remove] [-NoWatchdog]
|
||||
param([switch]$Highest, [switch]$Remove, [switch]$NoWatchdog)
|
||||
$ErrorActionPreference = 'Continue'
|
||||
$Here = Split-Path -Parent $MyInvocation.MyCommand.Path
|
||||
$TaskName = 'IgneumRelayService'
|
||||
|
|
@ -30,11 +35,19 @@ try {
|
|||
if ((Test-Path $k) -and ((Get-ItemProperty -Path $k -ErrorAction SilentlyContinue).PSObject.Properties.Name -contains 'IgneumRelayAgent')) { Remove-ItemProperty -Path $k -Name 'IgneumRelayAgent' -ErrorAction SilentlyContinue; Write-Host 'removed the RunOnce key IgneumRelayAgent' }
|
||||
} catch { }
|
||||
if ($Remove) {
|
||||
foreach ($w in @('IgneumRelayWatchdog', 'IgneumRelayWatchdogLogon')) { & schtasks.exe /Delete /F /TN $w 2>&1 | Out-Null }
|
||||
& schtasks.exe /End /TN $TaskName 2>&1 | Out-Null
|
||||
& schtasks.exe /Delete /F /TN $TaskName 2>&1 | Out-Null
|
||||
Write-Host ('removed the ' + $TaskName + ' task (an agent window started by hand is not touched)')
|
||||
exit 0
|
||||
}
|
||||
# A stale lock (9 October 2026, both PCs at 09:0x UK): an agent copy that holds the mutex but no longer polls (it sat waiting
|
||||
# on an app a task had relaunched) made the bat refuse a second copy, and a hand was needed. Every shell running
|
||||
# igneum-agent.ps1 or its service loop is ended here BY PID before the task is registered, so the install always starts
|
||||
# clean; nothing of the Miner is touched (the engine and its workers are not powershell shells of ours).
|
||||
$stale = @(Get-CimInstance Win32_Process | Where-Object { $_.Name -match '^(powershell|pwsh)\.exe$' -and $_.CommandLine -match 'igneum-agent(-service)?\.ps1' -and $_.ProcessId -ne $PID })
|
||||
foreach ($p in $stale) { Stop-Process -Id $p.ProcessId -Force -ErrorAction SilentlyContinue; Write-Host ('ended the old agent shell pid ' + $p.ProcessId + ' (it held the lock)') }
|
||||
if ($stale.Count -gt 0) { Start-Sleep -Seconds 2 }
|
||||
foreach ($f in @('IgneumRelayService.xml', 'igneum-agent-service.ps1', 'igneum-agent.ps1', 'machine-secret.txt')) {
|
||||
if (-not (Test-Path (Join-Path $Here $f))) { Write-Host ('missing ' + $f + ' beside this script (unzip the whole client zip from make-clients.sh --machine <name>)'); exit 2 }
|
||||
}
|
||||
|
|
@ -53,6 +66,16 @@ try {
|
|||
Write-Host ('registered ' + $TaskName + ' for ' + $user + ' at ' + $level + ' from ' + $Here)
|
||||
} finally { Remove-Item -Path $tmp -Force -ErrorAction SilentlyContinue }
|
||||
& schtasks.exe /Run /TN $TaskName 2>&1 | ForEach-Object { "$_" } | Write-Host
|
||||
if (-not $NoWatchdog) {
|
||||
$wd = Join-Path $Here 'watchdog.ps1'
|
||||
if (Test-Path $wd) {
|
||||
$tr = 'powershell.exe -NoProfile -ExecutionPolicy Bypass -WindowStyle Hidden -File "' + $wd + '"'
|
||||
$w1 = & schtasks.exe /Create /F /TN 'IgneumRelayWatchdog' /SC MINUTE /MO 5 /RL LIMITED /TR $tr 2>&1 | ForEach-Object { "$_" }
|
||||
$w2 = & schtasks.exe /Create /F /TN 'IgneumRelayWatchdogLogon' /SC ONLOGON /DELAY 0001:00 /RL LIMITED /TR ($tr + ' -Loop') 2>&1 | ForEach-Object { "$_" }
|
||||
Write-Host ('watchdog tasks: ' + (($w1 + $w2) -join ' | '))
|
||||
& schtasks.exe /Run /TN 'IgneumRelayWatchdogLogon' 2>&1 | Out-Null
|
||||
} else { Write-Host ('no watchdog.ps1 beside this script; the watchdog tasks are not registered') }
|
||||
}
|
||||
Start-Sleep -Seconds 3
|
||||
& schtasks.exe /Query /TN $TaskName /V /FO LIST 2>&1 | ForEach-Object { "$_" } | Where-Object { $_ -match '^(TaskName|Status|Logon Mode|Last Run Time|Last Result|Task To Run|Run As User|Schedule Type):' } | Write-Host
|
||||
Write-Host 'the agent now runs under the task; close any igneum-agent.bat window (the task copy exits while that one holds the mutex, and comes back 15 s after it closes)'
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@ fi
|
|||
mkdir -p "$OUT"
|
||||
NAME="igneum-relay-clients${MACHINE:+-$MACHINE}"
|
||||
STAGE="$(mktemp -d)/$NAME"; mkdir -p "$STAGE"; umask 077
|
||||
for f in send.bat send.ps1 send.sh igneum-agent.bat igneum-agent.ps1 igneum-agent-service.ps1 install-agent.ps1 IgneumRelayService.xml agent.sh CLAUDE-PC.md; do
|
||||
for f in send.bat send.ps1 send.sh igneum-agent.bat igneum-agent.ps1 igneum-agent-service.ps1 install-agent.ps1 watchdog.ps1 IgneumRelayService.xml agent.sh CLAUDE-PC.md; do
|
||||
sed -e "s#__RELAY_URL__#$URL#g" -e "s#__RELAY_KEY__#$KEY#g" -e "s#__RELAY_TOKEN__#$TOKEN#g" -e "s#__DL_BASE__#$DL_BASE#g" "$HERE/$f" > "$STAGE/$f"
|
||||
done
|
||||
[ -n "$SECRET" ] && printf '%s\n' "$SECRET" > "$STAGE/machine-secret.txt"
|
||||
|
|
|
|||
46
relay/clients/watchdog.ps1
Normal file
46
relay/clients/watchdog.ps1
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
# Relay agent watchdog (9 October 2026, the founder's standing rule: no machine needs a hand to recover). Registered by
|
||||
# install-agent.ps1 as two scheduled tasks beside IgneumRelayService: IgneumRelayWatchdog every 5 minutes and
|
||||
# IgneumRelayWatchdogLogon one minute after this user's logon. When the agent's pid file names no live process and no
|
||||
# igneum-agent.ps1 shell runs, it starts the IgneumRelayService task; when that task is missing, it registers it again
|
||||
# with install-agent.ps1 from this folder. The agent is only ever started by the task scheduler, never by a job of the
|
||||
# engine (an agent started under a job died with the engine's update on PC 1, 9 October 09:08 UK). It ends nothing.
|
||||
# watchdog.ps1 one check (the five-minute task): the agent, then the loop below when none runs
|
||||
# watchdog.ps1 -Loop the loop (the logon task): one check every 10 s for 55 minutes, so a dead agent is back within
|
||||
# 15 s (the founder's bar); it exits after 55 minutes and the five-minute task starts it again
|
||||
param([switch]$Loop)
|
||||
$ErrorActionPreference = 'Continue'
|
||||
$Here = Split-Path -Parent $MyInvocation.MyCommand.Path
|
||||
$state = Join-Path $env:LOCALAPPDATA 'igneum-relay'
|
||||
New-Item -ItemType Directory -Force -Path $state | Out-Null
|
||||
$log = Join-Path $state 'watchdog.log'
|
||||
function L($s) { Add-Content -Path $log -Value ((Get-Date).ToUniversalTime().ToString('yyyy-MM-ddTHH:mm:ssZ') + ' ' + $s) }
|
||||
$live = Join-Path $state 'agent.live'
|
||||
function Agent-Alive {
|
||||
if (Test-Path -LiteralPath $live) { try { $t = (Get-Content -LiteralPath $live -Raw).Trim(); if ($t -match '^\d+$' -and (Get-Process -Id ([int]$t) -ErrorAction SilentlyContinue)) { return $true } } catch { } }
|
||||
return [bool](Get-CimInstance Win32_Process | Where-Object { $_.Name -match '^(powershell|pwsh)\.exe$' -and $_.CommandLine -match 'igneum-agent\.ps1' } | Select-Object -First 1)
|
||||
}
|
||||
function Check {
|
||||
if (Agent-Alive) { return }
|
||||
$q = & schtasks.exe /Query /TN 'IgneumRelayService' 2>&1 | Out-String
|
||||
if ($q -match 'IgneumRelayService') {
|
||||
& schtasks.exe /Run /TN 'IgneumRelayService' 2>&1 | Out-Null
|
||||
L 'agent not running: IgneumRelayService task started'
|
||||
} else {
|
||||
$inst = Join-Path $Here 'install-agent.ps1'
|
||||
if (Test-Path -LiteralPath $inst) { & powershell.exe -NoProfile -ExecutionPolicy Bypass -File $inst -NoWatchdog 2>&1 | Out-Null; L ('IgneumRelayService task missing: registered again from ' + $inst) } else { L ('IgneumRelayService task missing and no install-agent.ps1 beside ' + $Here + '; nothing done') }
|
||||
}
|
||||
}
|
||||
if ($Loop) {
|
||||
# one loop at a time: a second one exits
|
||||
$mine = $PID
|
||||
$other = Get-CimInstance Win32_Process | Where-Object { $_.ProcessId -ne $mine -and $_.Name -match '^(powershell|pwsh)\.exe$' -and $_.CommandLine -match 'watchdog\.ps1' -and $_.CommandLine -match '-Loop' } | Select-Object -First 1
|
||||
if ($other) { exit 0 }
|
||||
$until = (Get-Date).AddMinutes(55)
|
||||
while ((Get-Date) -lt $until) { Check; Start-Sleep -Seconds 10 }
|
||||
exit 0
|
||||
}
|
||||
Check
|
||||
# the loop itself: started here when none runs (after a logon it is the logon task's; after 55 minutes it is this task's)
|
||||
$loopUp = Get-CimInstance Win32_Process | Where-Object { $_.Name -match '^(powershell|pwsh)\.exe$' -and $_.CommandLine -match 'watchdog\.ps1' -and $_.CommandLine -match '-Loop' } | Select-Object -First 1
|
||||
if (-not $loopUp) { & schtasks.exe /Run /TN 'IgneumRelayWatchdogLogon' 2>&1 | Out-Null; L 'watchdog loop not running: IgneumRelayWatchdogLogon task started' }
|
||||
exit 0
|
||||
Loading…
Reference in a new issue