refactor(PingServices): refine interface selection logic for ping operations, accommodating home routers without gateways
Publish Fast Tabler Docker image / build-and-push-fast (push) Successful in 1m38s

This commit is contained in:
2026-02-16 23:53:54 +07:00
parent c0d35c2e51
commit 21bd829979
+29 -29
View File
@@ -309,8 +309,9 @@ async function runPingViaRouter(serverId, gatewayIp, target, count = 5, interfac
} }
const client = createRosClient(creds); const client = createRosClient(creds);
let ifaceName = interfaceName || null; let ifaceName = interfaceName || null;
const isHomeNoGateway = server.type === 'home' && !gatewayIp && !interfaceName;
if (!ifaceName && gatewayIp) { if (!ifaceName && gatewayIp) {
const config = await loadNetworkConfig(); const config = await loadNetworkConfig();
const tunnelIfaces = Array.isArray(config.tunnelInterfaces) ? config.tunnelInterfaces : []; const tunnelIfaces = Array.isArray(config.tunnelInterfaces) ? config.tunnelInterfaces : [];
@@ -385,38 +386,37 @@ async function runPingViaRouter(serverId, gatewayIp, target, count = 5, interfac
// чтобы не ломать сам ping. // чтобы не ломать сам ping.
} }
} }
} }
// 4) Последний фоллбек: если ifaceName до сих пор не определён, // 4) Последний фоллбек (только для jumphost или home с указанным шлюзом): ether1/ether2.
// пробуем взять первый физический порт ether1/ether2 (если есть), // Для home без шлюза интерфейс не задаём — пинг идёт по маршруту по умолчанию.
// иначе любой интерфейс с префиксом "ether". if (!ifaceName && !isHomeNoGateway) {
if (!ifaceName) { try {
try { const ifRes = await client.command('interface/print', {
const ifRes = await client.command('interface/print', { '.proplist': ['name'],
'.proplist': ['name'], });
}); const data = ifRes?.data;
const data = ifRes?.data; const interfaces = Array.isArray(data) ? data : (data ? [data] : []);
const interfaces = Array.isArray(data) ? data : (data ? [data] : []); const names = interfaces
const names = interfaces .map((it) => (typeof it.name === 'string' ? it.name : null))
.map((it) => (typeof it.name === 'string' ? it.name : null)) .filter(Boolean);
.filter(Boolean);
let candidate = null; let candidate = null;
if (names.includes('ether1')) candidate = 'ether1'; if (names.includes('ether1')) candidate = 'ether1';
else if (names.includes('ether2')) candidate = 'ether2'; else if (names.includes('ether2')) candidate = 'ether2';
else { else {
candidate = names.find((n) => n.toLowerCase().startsWith('ether')) || null; candidate = names.find((n) => n.toLowerCase().startsWith('ether')) || null;
}
if (candidate) {
ifaceName = candidate;
}
} catch (_) {
// Если не получилось прочитать интерфейсы — просто продолжаем без interface.
} }
}
const body = {}; if (candidate) {
ifaceName = candidate;
}
} catch (_) {
// Если не получилось прочитать интерфейсы — просто продолжаем без interface.
}
}
const body = {};
body.address = target; body.address = target;
body.count = Number(count) > 0 ? Number(count) : 5; body.count = Number(count) > 0 ? Number(count) : 5;
if (ifaceName) body.interface = ifaceName; if (ifaceName) body.interface = ifaceName;