chore: linux 网络测试命令验证

This commit is contained in:
xiaojunnuo
2025-09-30 18:01:49 +00:00
parent 2bef608e07
commit b364313297
10 changed files with 304 additions and 463 deletions
+4
View File
@@ -1,2 +1,6 @@
link-workspace-packages=deep link-workspace-packages=deep
prefer-workspace-packages=true prefer-workspace-packages=true
better_sqlite3_binary_host=https://registry.npmmirror.com/-/binary/better-sqlite3
better_sqlite3_binary_host_mirror=https://registry.npmmirror.com/-/binary/better-sqlite3
better-sqlite3_binary_host=https://registry.npmmirror.com/-/binary/better-sqlite3
better-sqlite3_binary_host_mirror=https://registry.npmmirror.com/-/binary/better-sqlite3
+4 -4
View File
@@ -10,8 +10,8 @@
"type": "node", "type": "node",
"request": "launch", "request": "launch",
"cwd": "${workspaceFolder}/packages/ui/certd-client", "cwd": "${workspaceFolder}/packages/ui/certd-client",
"runtimeExecutable": "npm", "runtimeExecutable": "pnpm",
"runtimeArgs": ["run", "dev"], "runtimeArgs": ["dev"],
"console": "integratedTerminal", "console": "integratedTerminal",
"internalConsoleOptions": "neverOpen" "internalConsoleOptions": "neverOpen"
}, },
@@ -20,8 +20,8 @@
"type": "node", "type": "node",
"request": "launch", "request": "launch",
"cwd": "${workspaceFolder}/packages/ui/certd-server", "cwd": "${workspaceFolder}/packages/ui/certd-server",
"runtimeExecutable": "npm", "runtimeExecutable": "pnpm",
"runtimeArgs": ["run", "dev"], "runtimeArgs": ["dev"],
"console": "integratedTerminal", "console": "integratedTerminal",
"internalConsoleOptions": "neverOpen" "internalConsoleOptions": "neverOpen"
}, },
+3
View File
@@ -11,9 +11,12 @@
git clone https://github.com/certd/certd --depth=1 git clone https://github.com/certd/certd --depth=1
# git checkout v1.x.x # 当v2主干分支代码无法正常启动时,可以尝试此命令,1.x.x换成最新版本号 # git checkout v1.x.x # 当v2主干分支代码无法正常启动时,可以尝试此命令,1.x.x换成最新版本号
cd certd cd certd
# 启动服务 # 启动服务
./start.sh ./start.sh
``` ```
>如果是windows,请先安装`git for windows` ,然后右键,选择`open git bash here`打开终端,再执行`./start.sh`命令 >如果是windows,请先安装`git for windows` ,然后右键,选择`open git bash here`打开终端,再执行`./start.sh`命令
+19 -5
View File
@@ -1,7 +1,9 @@
//转换为import //转换为import
//@ts-ignore
import childProcess from "child_process"; import childProcess from "child_process";
import { safePromise } from "./util.promise.js"; import { safePromise } from "./util.promise.js";
import { ILogger, logger } from "./util.log.js"; import { ILogger, logger } from "./util.log.js";
//@ts-ignore
import iconv from "iconv-lite"; import iconv from "iconv-lite";
export type ExecOption = { export type ExecOption = {
cmd: string | string[]; cmd: string | string[];
@@ -28,12 +30,13 @@ async function exec(opts: ExecOption): Promise<string> {
cmd, cmd,
{ {
env: { env: {
//@ts-ignore
...process.env, ...process.env,
...opts.env, ...opts.env,
}, },
...opts.options, ...opts.options,
}, },
(error, stdout, stderr) => { (error: any, stdout: { toString: (arg0: string) => any }, stderr: any) => {
if (error) { if (error) {
log.error(`exec error: ${error}`); log.error(`exec error: ${error}`);
reject(error); reject(error);
@@ -57,6 +60,7 @@ export type SpawnOption = {
}; };
function isWindows() { function isWindows() {
// @ts-ignore
return process.platform === "win32"; return process.platform === "win32";
} }
function convert(buffer: any) { function convert(buffer: any) {
@@ -94,31 +98,41 @@ async function spawn(opts: SpawnOption): Promise<string> {
const ls = childProcess.spawn(cmd, { const ls = childProcess.spawn(cmd, {
shell: true, shell: true,
env: { env: {
//@ts-ignore
...process.env, ...process.env,
...opts.env, ...opts.env,
}, },
...opts.options, ...opts.options,
}); });
ls.stdout.on("data", data => { ls.stdout.on("data", (data: string) => {
data = convert(data); data = convert(data);
log.info(`stdout: ${data}`); log.info(`stdout: ${data}`);
stdout += data; stdout += data;
}); });
ls.stderr.on("data", data => { ls.stderr.on("data", (data: string) => {
data = convert(data); data = convert(data);
log.warn(`stderr: ${data}`); log.warn(`stderr: ${data}`);
stderr += data; stderr += data;
}); });
ls.on("error", error => { ls.on("error", (error: any) => {
log.error(`child process error: ${error}`); log.error(`child process error: ${error}`);
//@ts-ignore
error.stderr = stderr;
//@ts-ignore
error.stdout = stdout;
reject(error); reject(error);
}); });
ls.on("close", (code: number) => { ls.on("close", (code: number) => {
if (code !== 0) { if (code !== 0) {
log.error(`child process exited with code ${code}`); log.error(`child process exited with code ${code}`);
reject(new Error(stderr)); const e = new Error(stderr || "return " + code);
//@ts-ignore
error.stderr = stderr;
//@ts-ignore
error.stdout = stdout;
reject(e);
} else { } else {
resolve(stdout); resolve(stdout);
} }
+2 -1
View File
@@ -36,7 +36,8 @@
"socks-proxy-agent": "^8.0.4", "socks-proxy-agent": "^8.0.4",
"ssh2": "^1.15.0", "ssh2": "^1.15.0",
"strip-ansi": "^7.1.0", "strip-ansi": "^7.1.0",
"tencentcloud-sdk-nodejs": "^4.0.1005" "tencentcloud-sdk-nodejs": "^4.0.1005",
"psl": "^1.9.0"
}, },
"devDependencies": { "devDependencies": {
"@types/chai": "^4.3.3", "@types/chai": "^4.3.3",
@@ -19,14 +19,8 @@
<!-- 本地IP --> <!-- 本地IP -->
<div class="info-item"> <div class="info-item">
<div class="info-label">本地IP:</div> <div class="info-label">本地IP:</div>
<div v-if="serverInfo.localIP" class="info-value"> <div v-if="serverInfo.localIP && serverInfo.localIP.length > 0" class="info-value">
<a-list item-layout="horizontal" :data-source="serverInfo.localIP"> <a-tag v-for="ip in serverInfo.localIP" :key="ip" type="info" color="blue">{{ ip }}</a-tag>
<template #renderItem="{ item }">
<a-list-item>
<a-list-item-meta description="{{ item }}" />
</a-list-item>
</template>
</a-list>
</div> </div>
<div v-else class="info-empty">暂无信息</div> <div v-else class="info-empty">暂无信息</div>
</div> </div>
@@ -34,8 +28,8 @@
<!-- 外网IP --> <!-- 外网IP -->
<div class="info-item"> <div class="info-item">
<div class="info-label">外网IP:</div> <div class="info-label">外网IP:</div>
<div v-if="serverInfo.publicIP" class="info-value"> <div v-if="serverInfo.publicIP && serverInfo.publicIP.length > 0" class="info-value">
{{ serverInfo.publicIP }} <a-tag v-for="ip in serverInfo.publicIP" :key="ip" type="info" color="green">{{ ip }}</a-tag>
</div> </div>
<div v-else class="info-empty">暂无信息</div> <div v-else class="info-empty">暂无信息</div>
</div> </div>
@@ -44,7 +38,7 @@
<div class="info-item"> <div class="info-item">
<div class="info-label">DNS服务器:</div> <div class="info-label">DNS服务器:</div>
<div v-if="serverInfo.dnsServers && serverInfo.dnsServers.length > 0" class="info-value"> <div v-if="serverInfo.dnsServers && serverInfo.dnsServers.length > 0" class="info-value">
{{ serverInfo.dnsServers.join(", ") }} <a-tag v-for="dns in serverInfo.dnsServers" :key="dns" type="info" color="cyan">{{ dns }}</a-tag>
</div> </div>
<div v-else class="info-empty">暂无信息</div> <div v-else class="info-empty">暂无信息</div>
</div> </div>
@@ -60,7 +54,7 @@ import { GetServerInfo } from "./api";
// 服务器信息类型 // 服务器信息类型
interface ServerInfo { interface ServerInfo {
localIP?: string[]; localIP?: string[];
publicIP?: string; publicIP?: string[];
dnsServers?: string[]; dnsServers?: string[];
} }
@@ -6,7 +6,7 @@
<div class="nettest-container"> <div class="nettest-container">
<!-- 服务端信息 --> <!-- 服务端信息 -->
<server-info-card /> <server-info-card />
<!-- 测试区域 --> <!-- 测试区域 -->
<div class="test-areas"> <div class="test-areas">
<!-- 用户输入域名测试 --> <!-- 用户输入域名测试 -->
+1
View File
@@ -84,6 +84,7 @@ export default ({ command, mode }) => {
host: "0.0.0.0", host: "0.0.0.0",
port: 3008, port: 3008,
fs: devServerFs, fs: devServerFs,
allowedHosts: ["localhost", "127.0.0.1", "yfy.docmirror.cn"],
proxy: { proxy: {
// with options // with options
"/api": { "/api": {
@@ -42,7 +42,7 @@ export class NetTestService {
// 判断测试是否成功 // 判断测试是否成功
const success = this.isWindows() const success = this.isWindows()
? output.includes('端口连接成功') ? output.includes('端口连接成功')
: output.includes('succeeded') || output.includes('open'); : output.includes('Connected to');
// 处理结果 // 处理结果
return { return {
@@ -55,8 +55,8 @@ export class NetTestService {
return { return {
success: false, success: false,
message: 'Telnet测试执行失败', message: 'Telnet测试执行失败',
testLog: error instanceof Error ? error.message : String(error), testLog: error.stdout || error.stderr || error?.message || String(error),
error: error instanceof Error ? error.message : String(error) error: error.stderr || error?.message || String(error),
}; };
} }
} }
@@ -133,7 +133,7 @@ export class NetTestService {
}); });
// 判断测试是否成功 // 判断测试是否成功
const success = output.includes('Address:') || output.includes('IN A') || const success = output.includes('Address:') || output.includes('IN A') || output.includes('IN AAAA') ||
(this.isWindows() && output.includes('Name:')); (this.isWindows() && output.includes('Name:'));
return { return {
@@ -153,27 +153,29 @@ export class NetTestService {
} }
async getLocalIP(): Promise<string> { async getLocalIP(): Promise<string[]> {
try { try {
const output = await utils.sp.spawn({ const output = await utils.sp.spawn({
cmd: 'bash -c "ip a | grep \'inet \' | grep -v \'127.0.0.1\' | awk \'{print $2}\' | cut -d/ -f1"', cmd: 'bash -c "ip a | grep \'inet \' | grep -v \'127.0.0.1\' | awk \'{print $2}\' | cut -d/ -f1"',
logger: undefined logger: undefined
}); });
return output.trim(); // 去除 inet 前缀
let ips = output.trim().replace(/inet /g, '');
return ips.split('\n').filter(ip => ip.length > 0);
} catch (error) { } catch (error) {
return error instanceof Error ? error.message : String(error); return [error instanceof Error ? error.message : String(error)];
} }
} }
async getPublicIP(): Promise<string> { async getPublicIP(): Promise<string[]> {
try { try {
const res = await http.request({ const res = await http.request({
url:"https://ipinfo.io/ip", url:"https://ipinfo.io/ip",
method:"GET", method:"GET",
}) })
return res return[res]
} catch (error) { } catch (error) {
return error instanceof Error ? error.message : String(error); return [error instanceof Error ? error.message : String(error)]
} }
} }
@@ -195,8 +197,8 @@ export class NetTestService {
async serverInfo(): Promise<any> { async serverInfo(): Promise<any> {
const res = { const res = {
localIP: '', localIP: [],
publicIP: '', publicIP: [],
dnsServers: [], dnsServers: [],
} }
+250 -428
View File
File diff suppressed because it is too large Load Diff