fix(autostart): wait for the VNC server before starting web-vnc

autostart-run.bat checked 5900 once at startup; at boot the UltraVNC service may
not be up yet, so web-vnc either spawned a 2nd VNC server (conflict) or started
serving on :8080 before the VNC server was ready, breaking browser connections.

Now autostart-run.bat polls 127.0.0.1:5900 for up to ~30s (one PowerShell loop:
TcpClient + Start-Sleep 1, exits on first accepted connection) and only then
launches web-vnc.exe -- without --spawn when 5900 already listens, or spawning a
local server (portable vnc\winvnc.exe / tvnserver.exe, else auto-detect) if it
never came up. Docs (AGENTS.md, README.md) updated.
This commit is contained in:
Codex
2026-08-05 16:14:39 +03:00
parent 9b8ee94dd5
commit f315618bfc
3 changed files with 43 additions and 21 deletions
+10 -7
View File
@@ -70,7 +70,7 @@ open-firewall.bat открыть порт 8080 в Windows Firewall (о
webvnc.conf создаётся set-password.bat; содержит HASH=<pbkdf2-хэш> и VNC_PASSWORD=<тот же пароль для noVNC>; читается run.bat и scripts/autostart-run.bat; в git не коммитится (.gitignore). webvnc.conf создаётся set-password.bat; содержит HASH=<pbkdf2-хэш> и VNC_PASSWORD=<тот же пароль для noVNC>; читается run.bat и scripts/autostart-run.bat; в git не коммитится (.gitignore).
Внутренние помощники (вызываются другими скриптами, не пользователем) — в scripts/: Внутренние помощники (вызываются другими скриптами, не пользователем) — в scripts/:
scripts/autostart-run.bat НЕинтерактивный launcher для автостарта (нет пауз/запросов): читает webvnc.conf, ищет только ЛОКАЛЬНЫЙ VNC-сервер (ничего не качает), запускает web-vnc.exe в foreground. Вызывается плановым заданием из install-autostart.bat. scripts/autostart-run.bat НЕинтерактивный launcher для автостарта (нет пауз/запросов): читает webvnc.conf, ПОЛЛИТ 127.0.0.1:5900 до ~30 c (UltraVNC-сервис может ещё подниматься при загрузке) и только потом запускает web-vnc.exe — без --spawn если 5900 уже слушает, иначе спавнит локальный VNC-сервер (portable vnc\\winvnc.exe/tvnserver.exe или авто-детект). Ничего не качает на старте. Вызывается плановым заданием из install-autostart.bat.
scripts/ensure-vnc-password.ps1 синхронизирует VNC-пароль UltraVNC с введённым (пишет только при несовпадении; UAC только при смене) — вызывается из set-password.bat. scripts/ensure-vnc-password.ps1 синхронизирует VNC-пароль UltraVNC с введённым (пишет только при несовпадении; UAC только при смене) — вызывается из set-password.bat.
scripts/get-novnc.{ps1,sh} скачать noVNC scripts/get-novnc.{ps1,sh} скачать noVNC
scripts/get-vnc.ps1 скачать портативный UltraVNC в vnc/ (с верификацией zip) scripts/get-vnc.ps1 скачать портативный UltraVNC в vnc/ (с верификацией zip)
@@ -138,12 +138,15 @@ scripts/list-ips.ps1 список IPv4 машины (использует
плановое задание `web-vnc` через `schtasks /Create /SC ONSTART /RU SYSTEM /RL HIGHEST`, плановое задание `web-vnc` через `schtasks /Create /SC ONSTART /RU SYSTEM /RL HIGHEST`,
которое при загрузке ОС запускает `scripts/autostart-run.bat`. которое при загрузке ОС запускает `scripts/autostart-run.bat`.
3. `scripts/autostart-run.bat`**неинтерактивный** launcher: читает `webvnc.conf`, 3. `scripts/autostart-run.bat`**неинтерактивный** launcher: читает `webvnc.conf`,
при необходимости собирает `web-vnc.exe` (если есть Go), ищет только **локальный** при необходимости собирает `web-vnc.exe` (если есть Go), затем **опрашивает
VNC-сервер (ничего не качает — на старте сети/интернета может не быть), и запускает `127.0.0.1:5900` до ~30 c** (один PowerShell-проект крутит цикл try/TcpClient +
`web-vnc.exe --password-hash <HASH> --listen :8080` в foreground (задание держит `Start-Sleep 1`; выходит сразу, как только порт принял соединение) — UltraVNC-сервис
процесс живым). Если `127.0.0.1:5900` уже слушает (сервис UltraVNC) — запускает при загрузке может ещё подниматься. Если `5900` слушает — запускает
**без** `--spawn` и **без** `--spawn-command`, подключаясь к существующему серверу `web-vnc.exe --password-hash <HASH> --listen :8080` **без** `--spawn` (подключается
(иначе попытка породить второй VNC-сервер конфликтовала бы с сервисом). к существующему серверу, не плодя второй). Если за ~30 c не поднялось — спавнит
локальный VNC-сервер (`--spawn-command "vnc\winvnc.exe -run"` если есть portable,
иначе `--spawn` с авто-детектом) и запускает web-vnc. На старте ничего не качает.
Задание держит процесс живым в foreground.
4. Снять автостарт: `uninstall-autostart.bat` (от админа) — `schtasks /Delete`. 4. Снять автостарт: `uninstall-autostart.bat` (от админа) — `schtasks /Delete`.
Замечания: Замечания:
+1 -1
View File
@@ -218,7 +218,7 @@ open-firewall.bat открыть порт 8080 в Windows Firewall (о
webvnc.conf секрет: HASH= + VNC_PASSWORD= (создаётся set-password.bat, gitignored) webvnc.conf секрет: HASH= + VNC_PASSWORD= (создаётся set-password.bat, gitignored)
Внутренние помощники — в scripts/ (вызываются другими скриптами): Внутренние помощники — в scripts/ (вызываются другими скриптами):
scripts/autostart-run.bat неинтерактивный launcher для автостарта (читает webvnc.conf) scripts/autostart-run.bat неинтерактивный launcher для автостарта: читает webvnc.conf, ждёт 5900 до ~30 c, затем запускает web-vnc (без --spawn, если VNC уже слушает)
scripts/ensure-vnc-password.ps1 синхронизирует VNC-пароль UltraVNC (вызывается из set-password.bat) scripts/ensure-vnc-password.ps1 синхронизирует VNC-пароль UltraVNC (вызывается из set-password.bat)
scripts/get-novnc.{ps1,sh} скачать noVNC во встроенную статику scripts/get-novnc.{ps1,sh} скачать noVNC во встроенную статику
scripts/get-vnc.ps1 скачать портативный VNC-сервер (UltraVNC) в папку vnc/ scripts/get-vnc.ps1 скачать портативный VNC-сервер (UltraVNC) в папку vnc/
+32 -13
View File
@@ -2,10 +2,12 @@
REM ============================================================ REM ============================================================
REM autostart-run.bat - non-interactive launcher used by the REM autostart-run.bat - non-interactive launcher used by the
REM scheduled task created by install-autostart.bat. REM scheduled task created by install-autostart.bat.
REM Reads the password from webvnc.conf, finds a LOCAL VNC server REM Reads the password from webvnc.conf, WAITS for the VNC server
REM (does NOT download anything), and starts web-vnc.exe in the REM on 127.0.0.1:5900 (the UltraVNC service may still be starting
REM foreground. The task keeps the process alive and restarts it REM at boot), and only then starts web-vnc.exe in the foreground.
REM on next boot. REM If no VNC server comes up, it spawns a local one (portable
REM vnc\winvnc.exe / tvnserver.exe, or auto-detected) so web-vnc
REM does not serve before the VNC server is ready.
REM Exit codes: 0 = server ran and stopped; 1 = no binary; REM Exit codes: 0 = server ran and stopped; 1 = no binary;
REM 2 = password not configured; other = web-vnc error. REM 2 = password not configured; other = web-vnc error.
REM ============================================================ REM ============================================================
@@ -33,20 +35,37 @@ if "%VNC_PW%"=="" exit /b 2
set "WEBVNC_VNC_PASSWORD=%VNC_PW%" set "WEBVNC_VNC_PASSWORD=%VNC_PW%"
set "VNC_PW=" set "VNC_PW="
REM --- 3. VNC server (detect local only; never download at boot) --- REM --- 3. Wait for the VNC server on 127.0.0.1:5900 ---
set "SPAWNARGS=" REM At boot the UltraVNC service (uvnc_service) may still be starting.
REM Poll up to ~30 s (one PowerShell process loops internally) so we do
REM NOT spawn a 2nd server and do NOT serve before the VNC server is
REM ready. Exits 0 as soon as 5900 accepts a connection, 1 on timeout.
echo Waiting for VNC server on 127.0.0.1:5900 (up to 30 s) ...
powershell -NoProfile -Command "for($i=0;$i -lt 30;$i++){try{$c=New-Object Net.Sockets.TcpClient('127.0.0.1',5900);$c.Close();exit 0}catch{};Start-Sleep -Seconds 1};exit 1"
if not errorlevel 1 goto vnc_up
:vnc_down
echo VNC server is not up after the wait.
set "SPAWN_CMD=" set "SPAWN_CMD="
if exist "vnc\winvnc.exe" set "SPAWN_CMD=vnc\winvnc.exe -run" if exist "vnc\winvnc.exe" set "SPAWN_CMD=vnc\winvnc.exe -run"
if exist "vnc\tvnserver.exe" if not defined SPAWN_CMD set "SPAWN_CMD=vnc\tvnserver.exe -run" if exist "vnc\tvnserver.exe" if not defined SPAWN_CMD set "SPAWN_CMD=vnc\tvnserver.exe -run"
if defined SPAWN_CMD set "SPAWNARGS=--spawn-command "%SPAWN_CMD%"" if defined SPAWN_CMD goto have_spawn
set "SPAWNARGS="
set "SPAWNFLAG=--spawn" set "SPAWNFLAG=--spawn"
powershell -NoProfile -Command "try{$c=New-Object Net.Sockets.TcpClient('127.0.0.1',5900);$c.Close();exit 0}catch{exit 1}" echo No local VNC server; web-vnc will auto-detect and spawn one.
if not errorlevel 1 ( goto launch
set "SPAWNFLAG=" :have_spawn
set "SPAWNARGS=" set "SPAWNARGS=--spawn-command "%SPAWN_CMD%""
) set "SPAWNFLAG=--spawn"
echo Starting local VNC server: %SPAWN_CMD%
goto launch
:vnc_up
echo VNC server is up - connecting to it without --spawn.
set "SPAWNARGS="
set "SPAWNFLAG="
:launch
REM --- 4. Launch (foreground; the task host keeps it alive) --- REM --- 4. Launch (foreground; the task host keeps it alive) ---
web-vnc.exe --password-hash "%HASH%" %SPAWNARGS% %SPAWNFLAG% --listen :8080 web-vnc.exe --password-hash "%HASH%" %SPAWNARGS% %SPAWNFLAG% --listen :8080
exit /b %errorlevel% exit /b %errorlevel%