mirror of https://github.com/certd/certd
209 lines
5.8 KiB
TypeScript
209 lines
5.8 KiB
TypeScript
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
|
||
}
|
||
}
|