mirror of
https://github.com/certd/certd.git
synced 2026-04-15 13:32:37 +08:00
perf: 支持网络测试
This commit is contained in:
@@ -0,0 +1,47 @@
|
||||
import { BaseController } from '@certd/lib-server';
|
||||
import { ALL, Body, Controller, Inject, Post, Provide } from '@midwayjs/core';
|
||||
import { NetTestService } from '../../../modules/sys/nettest/nettest-service.js';
|
||||
|
||||
|
||||
@Provide()
|
||||
@Controller('/api/sys/nettest/')
|
||||
export class SysNetTestController extends BaseController {
|
||||
|
||||
@Inject()
|
||||
netTestService: NetTestService;
|
||||
|
||||
|
||||
@Post('/domainResolve', { summary: 'sys:settings:view' })
|
||||
public async domainResolve(@Body(ALL) body: { domain: string }) {
|
||||
|
||||
const { domain } = body;
|
||||
const result = await this.netTestService.domainResolve(domain);
|
||||
return this.ok(result);
|
||||
}
|
||||
|
||||
// ping
|
||||
@Post('/ping', { summary: 'sys:settings:view' })
|
||||
public async ping(@Body(ALL) body: { domain: string }) {
|
||||
|
||||
const { domain } = body;
|
||||
const result = await this.netTestService.ping(domain);
|
||||
return this.ok(result);
|
||||
}
|
||||
|
||||
// telnet
|
||||
@Post('/telnet', { summary: 'sys:settings:view' })
|
||||
public async telnet(@Body(ALL) body: { domain: string, port: number }) {
|
||||
|
||||
const { domain, port } = body;
|
||||
const result = await this.netTestService.telnet(domain, port);
|
||||
return this.ok(result);
|
||||
}
|
||||
|
||||
// telnet
|
||||
@Post('/serverInfo', { summary: 'sys:settings:view' })
|
||||
public async serverInfo() {
|
||||
|
||||
const result = await this.netTestService.serverInfo();
|
||||
return this.ok(result);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,208 @@
|
||||
import { Provide, Scope, ScopeEnum } from '@midwayjs/core';
|
||||
import { http, utils } from '@certd/basic';
|
||||
|
||||
// 使用@certd/basic包中已有的utils.sp.spawn函数替代自定义的asyncExec
|
||||
// 该函数已经内置了Windows系统编码问题的解决方案
|
||||
|
||||
export type NetTestResult = {
|
||||
success: boolean; //是否成功
|
||||
message: string; //结果
|
||||
testLog: string; //测试日志
|
||||
error?: string; //执行错误信息
|
||||
}
|
||||
|
||||
@Provide('nettestService')
|
||||
@Scope(ScopeEnum.Request, { allowDowngrade: true })
|
||||
export class NetTestService {
|
||||
/**
|
||||
* 执行Telnet测试
|
||||
* @param domain 域名
|
||||
* @param port 端口
|
||||
* @returns 测试结果
|
||||
*/
|
||||
async telnet(domain: string, port: number): Promise<NetTestResult> {
|
||||
try {
|
||||
let command = '';
|
||||
|
||||
if (this.isWindows()) {
|
||||
// Windows系统使用PowerShell执行测试,避免输入重定向问题
|
||||
// 使用PowerShell的Test-NetConnection命令进行端口测试
|
||||
command = `powershell -Command "& { $result = Test-NetConnection -ComputerName ${domain} -Port ${port} -InformationLevel Quiet; if ($result) { Write-Host '端口连接成功' } else { Write-Host '端口连接失败' } }"`;
|
||||
} else {
|
||||
// Linux系统使用nc命令进行端口测试
|
||||
command = `nc -zv -w 5 ${domain} ${port} 2>&1`;
|
||||
}
|
||||
|
||||
// 使用utils.sp.spawn执行命令,它会自动处理Windows编码问题
|
||||
const output = await utils.sp.spawn({
|
||||
cmd: command,
|
||||
logger: undefined // 可以根据需要传入logger
|
||||
});
|
||||
|
||||
// 判断测试是否成功
|
||||
const success = this.isWindows()
|
||||
? output.includes('端口连接成功')
|
||||
: output.includes('succeeded') || output.includes('open');
|
||||
|
||||
// 处理结果
|
||||
return {
|
||||
success,
|
||||
message: success ? '端口连接测试成功' : '端口连接测试失败',
|
||||
testLog: output,
|
||||
};
|
||||
|
||||
} catch (error) {
|
||||
return {
|
||||
success: false,
|
||||
message: 'Telnet测试执行失败',
|
||||
testLog: error instanceof Error ? error.message : String(error),
|
||||
error: error instanceof Error ? error.message : String(error)
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 执行Ping测试
|
||||
* @param domain 域名
|
||||
* @returns 测试结果
|
||||
*/
|
||||
async ping(domain: string): Promise<NetTestResult> {
|
||||
try {
|
||||
let command = '';
|
||||
|
||||
if (this.isWindows()) {
|
||||
// Windows系统ping命令,发送4个包
|
||||
command = `ping -n 4 ${domain}`;
|
||||
} else {
|
||||
// Linux系统ping命令,发送4个包
|
||||
command = `ping -c 4 ${domain}`;
|
||||
}
|
||||
|
||||
// 使用utils.sp.spawn执行命令
|
||||
const output = await utils.sp.spawn({
|
||||
cmd: command,
|
||||
logger: undefined
|
||||
});
|
||||
|
||||
// 判断测试是否成功
|
||||
const success = this.isWindows()
|
||||
? output.includes('TTL=')
|
||||
: output.includes('0% packet loss');
|
||||
|
||||
return {
|
||||
success,
|
||||
message: success ? 'Ping测试成功' : 'Ping测试失败',
|
||||
testLog: output,
|
||||
};
|
||||
|
||||
} catch (error) {
|
||||
const errorMessage = error instanceof Error ? error.message : String(error);
|
||||
return {
|
||||
success: false,
|
||||
message: 'Ping测试执行失败',
|
||||
testLog: errorMessage,
|
||||
error: errorMessage
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
private isWindows() {
|
||||
return process.platform === 'win32';
|
||||
}
|
||||
|
||||
/**
|
||||
* 执行域名解析测试
|
||||
* @param domain 域名
|
||||
* @returns 解析结果
|
||||
*/
|
||||
async domainResolve(domain: string): Promise<NetTestResult> {
|
||||
try {
|
||||
let command = '';
|
||||
if (this.isWindows()) {
|
||||
// Windows系统使用nslookup命令
|
||||
command = `nslookup ${domain}`;
|
||||
} else {
|
||||
// Linux系统优先使用dig命令,如果没有则回退到nslookup
|
||||
command = `which dig > /dev/null && dig ${domain} || nslookup ${domain}`;
|
||||
}
|
||||
|
||||
// 使用utils.sp.spawn执行命令
|
||||
const output = await utils.sp.spawn({
|
||||
cmd: command,
|
||||
logger: undefined
|
||||
});
|
||||
|
||||
// 判断测试是否成功
|
||||
const success = output.includes('Address:') || output.includes('IN A') ||
|
||||
(this.isWindows() && output.includes('Name:'));
|
||||
|
||||
return {
|
||||
success,
|
||||
message: success ? '域名解析测试成功' : '域名解析测试失败',
|
||||
testLog: output,
|
||||
};
|
||||
} catch (error) {
|
||||
const errorMessage = error instanceof Error ? error.message : String(error);
|
||||
return {
|
||||
success: false,
|
||||
message: '域名解析测试执行失败',
|
||||
testLog: errorMessage,
|
||||
error: errorMessage
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
async getLocalIP(): Promise<string> {
|
||||
try {
|
||||
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"',
|
||||
logger: undefined
|
||||
});
|
||||
return output.trim();
|
||||
} catch (error) {
|
||||
return error instanceof Error ? error.message : String(error);
|
||||
}
|
||||
}
|
||||
|
||||
async getPublicIP(): Promise<string> {
|
||||
try {
|
||||
const res = await http.request({
|
||||
url:"https://ipinfo.io/ip",
|
||||
method:"GET",
|
||||
})
|
||||
return res
|
||||
} catch (error) {
|
||||
return error instanceof Error ? error.message : String(error);
|
||||
}
|
||||
}
|
||||
|
||||
async getDNSservers(): Promise<string[]> {
|
||||
try {
|
||||
const output = await utils.sp.spawn({
|
||||
cmd: 'cat /etc/resolv.conf | grep nameserver | awk \'{print $2}\'',
|
||||
logger: undefined
|
||||
});
|
||||
return output.trim().split('\n');
|
||||
} catch (error) {
|
||||
return [error instanceof Error ? error.message : String(error)];
|
||||
}
|
||||
}
|
||||
/**
|
||||
* 获取服务器信息(包括本地IP、外网IP和DNS服务器)
|
||||
* @returns 服务器信息
|
||||
*/
|
||||
async serverInfo(): Promise<any> {
|
||||
|
||||
const res = {
|
||||
localIP: '',
|
||||
publicIP: '',
|
||||
dnsServers: [],
|
||||
}
|
||||
|
||||
res.localIP = await this.getLocalIP();
|
||||
res.publicIP = await this.getPublicIP();
|
||||
res.dnsServers = await this.getDNSservers();
|
||||
return res
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user