certd/packages/ui/certd-server/src/modules/sys/nettest/nettest-service.ts

209 lines
5.8 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

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
}
}