mirror of
https://github.com/andrey271192/keenetic-dns-routes.git
synced 2026-09-20 14:42:01 +00:00
fix(tunnel): close stdin so autossh survives backgrounding; add quick "+ Тоннель" button
Background autossh died immediately because nohup left stdin attached to the closed curl pipe — autossh saw EOF and bailed. Add </dev/null and wrap in subshell so the process is fully detached from the install script's session. Also add an "+ Тоннель" button next to "+ Добавить": creates a router with a placeholder base URL and opens the tunnel modal in one click — for routers without a public IP that have nothing to put in the base URL field yet. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
15
app/main.py
15
app/main.py
@@ -414,9 +414,9 @@ chmod +x /opt/bin/kdns_tun
|
|||||||
cat > /opt/etc/init.d/S99kdns_tun <<'INITEOF'
|
cat > /opt/etc/init.d/S99kdns_tun <<'INITEOF'
|
||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
case "$1" in
|
case "$1" in
|
||||||
start) killall -0 autossh 2>/dev/null || nohup /opt/bin/kdns_tun >/dev/null 2>&1 & ;;
|
start) killall -0 autossh 2>/dev/null || ( nohup /opt/bin/kdns_tun </dev/null >/dev/null 2>&1 & ) ;;
|
||||||
stop) killall autossh 2>/dev/null ;;
|
stop) killall autossh 2>/dev/null ;;
|
||||||
restart) killall autossh 2>/dev/null; sleep 1; nohup /opt/bin/kdns_tun >/dev/null 2>&1 & ;;
|
restart) killall autossh 2>/dev/null; sleep 1; ( nohup /opt/bin/kdns_tun </dev/null >/dev/null 2>&1 & ) ;;
|
||||||
esac
|
esac
|
||||||
INITEOF
|
INITEOF
|
||||||
chmod +x /opt/etc/init.d/S99kdns_tun
|
chmod +x /opt/etc/init.d/S99kdns_tun
|
||||||
@@ -424,8 +424,10 @@ chmod +x /opt/etc/init.d/S99kdns_tun
|
|||||||
echo '[4/4] Запуск...'
|
echo '[4/4] Запуск...'
|
||||||
killall autossh 2>/dev/null || true
|
killall autossh 2>/dev/null || true
|
||||||
sleep 1
|
sleep 1
|
||||||
nohup /opt/bin/kdns_tun >/dev/null 2>&1 &
|
# stdin=/dev/null обязательно: иначе autossh ловит EOF от закрытой curl-трубы и сразу выходит.
|
||||||
sleep 3
|
# subshell ( ... ) полностью отрывает процесс от родительского sh.
|
||||||
|
( nohup /opt/bin/kdns_tun </dev/null >/dev/null 2>&1 & )
|
||||||
|
sleep 4
|
||||||
if killall -0 autossh 2>/dev/null; then
|
if killall -0 autossh 2>/dev/null; then
|
||||||
echo
|
echo
|
||||||
echo '=== OK ==='
|
echo '=== OK ==='
|
||||||
@@ -433,8 +435,9 @@ if killall -0 autossh 2>/dev/null; then
|
|||||||
echo 'Возвращайся в браузер и жми "Проверить связь"'
|
echo 'Возвращайся в браузер и жми "Проверить связь"'
|
||||||
else
|
else
|
||||||
echo
|
echo
|
||||||
echo '=== ОШИБКА: autossh не запустился ==='
|
echo '=== ОШИБКА: autossh не запустился в фоне ==='
|
||||||
echo 'Тест вручную: /opt/bin/kdns_tun (Ctrl+C для выхода)'
|
echo 'Тест вручную (должно работать): /opt/bin/kdns_tun (Ctrl+C для выхода)'
|
||||||
|
echo 'Если вручную работает — попробуй: ( nohup /opt/bin/kdns_tun </dev/null >/dev/null 2>&1 & )'
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
"""
|
"""
|
||||||
|
|||||||
@@ -127,6 +127,7 @@
|
|||||||
<div style="min-width:100px"><label>Логин (если не .env)</label><input type="text" id="rl" placeholder="пусто = из .env"/></div>
|
<div style="min-width:100px"><label>Логин (если не .env)</label><input type="text" id="rl" placeholder="пусто = из .env"/></div>
|
||||||
<div style="min-width:120px"><label>Пароль (если не .env)</label><input type="password" id="rp" placeholder="пусто = из .env" autocomplete="new-password"/></div>
|
<div style="min-width:120px"><label>Пароль (если не .env)</label><input type="password" id="rp" placeholder="пусто = из .env" autocomplete="new-password"/></div>
|
||||||
<div><label> </label><button class="btn btn-b" onclick="addR()">+ Добавить</button></div>
|
<div><label> </label><button class="btn btn-b" onclick="addR()">+ Добавить</button></div>
|
||||||
|
<div><label> </label><button class="btn" style="background:#7c3aed;color:#fff" onclick="addAndTunnel()" title="Создать роутер с base URL=http://localhost:NNNN и сразу открыть модалку тоннеля. Удобно для роутеров без белого IP.">⇄ Тоннель</button></div>
|
||||||
</div>
|
</div>
|
||||||
<div style="overflow-x:auto">
|
<div style="overflow-x:auto">
|
||||||
<table class="tbl" id="rtbl"><thead><tr>
|
<table class="tbl" id="rtbl"><thead><tr>
|
||||||
@@ -359,6 +360,36 @@ async function addR(){
|
|||||||
document.getElementById('rl').value='';document.getElementById('rp').value='';
|
document.getElementById('rl').value='';document.getElementById('rp').value='';
|
||||||
await load();
|
await load();
|
||||||
}
|
}
|
||||||
|
async function addAndTunnel(){
|
||||||
|
// Создать роутер с placeholder base URL (заменится после "Применить URL автоматически")
|
||||||
|
// и сразу открыть модалку тоннеля.
|
||||||
|
let name=document.getElementById('rn').value.trim();
|
||||||
|
let keenetic_login=document.getElementById('rl').value.trim();
|
||||||
|
let keenetic_password=document.getElementById('rp').value;
|
||||||
|
if(!name){
|
||||||
|
name=prompt('Имя роутера (для тоннеля):','Роутер без IP');
|
||||||
|
if(!name)return;
|
||||||
|
}
|
||||||
|
if(!keenetic_login){keenetic_login='admin';}
|
||||||
|
if(!keenetic_password){
|
||||||
|
const p=prompt('Пароль Keenetic для RCI (поле «Пароль» пустое):');
|
||||||
|
if(p===null)return;
|
||||||
|
keenetic_password=p;
|
||||||
|
}
|
||||||
|
await saveServer({skipLoad:true});
|
||||||
|
// base URL — временный, реальный придёт из tunnel-cmd (http://localhost:NNNN)
|
||||||
|
const r=await fetch('/api/routers',{method:'POST',headers:hdr(),body:JSON.stringify({
|
||||||
|
name, rci_base_url:'http://localhost:1', keenetic_login, keenetic_password
|
||||||
|
})});
|
||||||
|
if(r.status===401){logout();return;}
|
||||||
|
if(!r.ok){alert(await r.text());return;}
|
||||||
|
const j=await r.json();
|
||||||
|
document.getElementById('rn').value='';document.getElementById('ru').value='';
|
||||||
|
document.getElementById('rl').value='';document.getElementById('rp').value='';
|
||||||
|
await load();
|
||||||
|
// Открыть модалку тоннеля для нового роутера
|
||||||
|
await tunnelR(j.id);
|
||||||
|
}
|
||||||
async function delR(id){
|
async function delR(id){
|
||||||
if(!confirm('Удалить?'))return;
|
if(!confirm('Удалить?'))return;
|
||||||
const r=await fetch('/api/routers/'+encodeURIComponent(id),{method:'DELETE',headers:hdr()});
|
const r=await fetch('/api/routers/'+encodeURIComponent(id),{method:'DELETE',headers:hdr()});
|
||||||
|
|||||||
Reference in New Issue
Block a user