fix(tunnel): install cronie, start crond, killall watchdog; add tunnel-status endpoint

- opkg install now includes cronie so crond is actually present
- /opt/etc/init.d/S10crond start runs after install so cron watchdog fires
- cron watchdog switches from pgrep (not always in PATH) to killall -0 autossh
- killall autossh instead of pkill before re-launching (works in BusyBox)
- GET /api/routers/{rid}/tunnel-status: checks if tunnel port is listening on VPS localhost
- "⟳ Проверить связь" button in tunnel modal calls the new endpoint

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Андрей Бобырев
2026-04-27 21:54:34 +03:00
parent d48b7b2023
commit cc31234e91
2 changed files with 44 additions and 5 deletions

View File

@@ -163,6 +163,7 @@
<div style="display:flex;gap:8px;flex-wrap:wrap;margin-top:14px">
<button class="btn btn-b" onclick="applyTunnelUrl()">✓ Применить URL автоматически</button>
<button class="btn btn-d" onclick="closeTunnelModal()">Закрыть</button>
<button class="btn" style="background:#0f2;color:#000;font-size:11px;padding:6px 12px" onclick="checkTunnelStatus()">⟳ Проверить связь</button>
<button class="btn" style="background:#7c3aed22;color:#a78bfa;border:1px solid #7c3aed44;margin-left:auto;font-size:11px;padding:6px 12px" onclick="removeTunnel()">✕ Сбросить тоннель</button>
</div>
<div id="tunnel-msg" style="margin-top:10px;font-size:12px;display:none"></div>
@@ -453,6 +454,19 @@ async function applyTunnelUrl(){
msg.style.color='var(--er)';msg.textContent='Ошибка: '+(j.detail||r.statusText);msg.style.display='block';
}
}
async function checkTunnelStatus(){
if(!_tunnelRouterId)return;
const msg=document.getElementById('tunnel-msg');
msg.style.color='var(--mu)';msg.textContent='Проверяю порт…';msg.style.display='block';
const r=await fetch(`/api/routers/${encodeURIComponent(_tunnelRouterId)}/tunnel-status`,{headers:hdr()});
if(r.status===401){logout();return;}
const j=await r.json().catch(()=>({}));
if(j.active){
msg.style.color='var(--ok)';msg.textContent=`✓ Тоннель активен — порт ${j.tunnel_port} слушает`;
} else {
msg.style.color='var(--er)';msg.textContent=`✗ Порт ${j.tunnel_port||'?'} не отвечает — запусти команду на роутере`;
}
}
async function removeTunnel(){
if(!_tunnelRouterId)return;
const msg=document.getElementById('tunnel-msg');