修复了引擎运行时读取log的多余的tail进程
This commit is contained in:
parent
cc042dc497
commit
2b39135c63
Binary file not shown.
@ -635,6 +635,15 @@ class RunSimulation extends HTMLElement {
|
|||||||
// 关闭SSE连接
|
// 关闭SSE连接
|
||||||
closeEventSource() {
|
closeEventSource() {
|
||||||
if (this.eventSource) {
|
if (this.eventSource) {
|
||||||
|
// 通知后端清理tail进程
|
||||||
|
if (this.currentSimulationId) {
|
||||||
|
fetch(`/api/cleanup-simulation/${this.currentSimulationId}`, {
|
||||||
|
method: 'POST'
|
||||||
|
}).catch(error => {
|
||||||
|
console.error('清理仿真资源失败:', error);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
this.eventSource.close();
|
this.eventSource.close();
|
||||||
this.eventSource = null;
|
this.eventSource = null;
|
||||||
}
|
}
|
||||||
@ -1052,6 +1061,20 @@ class RunSimulation extends HTMLElement {
|
|||||||
this.resetUIAfterCompletion();
|
this.resetUIAfterCompletion();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 添加组件销毁时的清理方法
|
||||||
|
disconnectedCallback() {
|
||||||
|
// 清理SSE连接和相关资源
|
||||||
|
this.closeEventSource();
|
||||||
|
|
||||||
|
// 重置所有状态
|
||||||
|
this.currentSimulationId = null;
|
||||||
|
this.reconnectAttempts = 0;
|
||||||
|
this.scenarioFiles = [];
|
||||||
|
this.currentScenario = null;
|
||||||
|
this.modelGroups = [];
|
||||||
|
this.services = [];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
customElements.define('run-simulation', RunSimulation);
|
customElements.define('run-simulation', RunSimulation);
|
@ -123,26 +123,27 @@ router.get('/simulation-output/:id', async (req, res) => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// 将进程添加到runningSimulations
|
// 将进程添加到runningSimulations
|
||||||
runningSimulations.set(simulationId, {
|
const simulation = runningSimulations.get(simulationId) || {
|
||||||
pid: processInfo.pid,
|
pid: processInfo.pid,
|
||||||
startTime: new Date(processInfo.start_time).getTime(),
|
startTime: new Date(processInfo.start_time).getTime(),
|
||||||
output: '',
|
output: '',
|
||||||
errorOutput: '',
|
errorOutput: '',
|
||||||
logFile: processInfo.log_file
|
logFile: processInfo.log_file
|
||||||
});
|
};
|
||||||
|
runningSimulations.set(simulationId, simulation);
|
||||||
|
|
||||||
// 使用tail命令来跟踪日志文件
|
// 使用tail命令来跟踪日志文件
|
||||||
const tailProcess = spawn('tail', ['-f', processInfo.log_file], {
|
const tailProcess = spawn('tail', ['-f', processInfo.log_file], {
|
||||||
stdio: ['ignore', 'pipe', 'pipe']
|
stdio: ['ignore', 'pipe', 'pipe']
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// 保存tail进程引用
|
||||||
|
simulation.tailProcess = tailProcess;
|
||||||
|
|
||||||
// 收集标准输出
|
// 收集标准输出
|
||||||
tailProcess.stdout.on('data', (data) => {
|
tailProcess.stdout.on('data', (data) => {
|
||||||
const chunk = data.toString('utf8');
|
const chunk = data.toString('utf8');
|
||||||
const simulation = runningSimulations.get(simulationId);
|
simulation.output += chunk;
|
||||||
if (simulation) {
|
|
||||||
simulation.output += chunk;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 推送到SSE客户端
|
// 推送到SSE客户端
|
||||||
sendSSEMessage(simulationId, 'output', {
|
sendSSEMessage(simulationId, 'output', {
|
||||||
@ -153,11 +154,17 @@ router.get('/simulation-output/:id', async (req, res) => {
|
|||||||
|
|
||||||
// 当客户端断开连接时清理
|
// 当客户端断开连接时清理
|
||||||
req.on('close', () => {
|
req.on('close', () => {
|
||||||
tailProcess.kill();
|
if (simulation.tailProcess) {
|
||||||
|
simulation.tailProcess.kill();
|
||||||
|
simulation.tailProcess = null;
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// 当tail进程结束时
|
// 当tail进程结束时
|
||||||
tailProcess.on('close', (code) => {
|
tailProcess.on('close', (code) => {
|
||||||
|
if (simulation.tailProcess === tailProcess) {
|
||||||
|
simulation.tailProcess = null;
|
||||||
|
}
|
||||||
runningSimulations.delete(simulationId);
|
runningSimulations.delete(simulationId);
|
||||||
sendSSEMessage(simulationId, 'status', {
|
sendSSEMessage(simulationId, 'status', {
|
||||||
running: false,
|
running: false,
|
||||||
@ -316,7 +323,7 @@ router.post('/run-simulation', async (req, res) => {
|
|||||||
scenario_file: args[0]
|
scenario_file: args[0]
|
||||||
});
|
});
|
||||||
|
|
||||||
// 保存到运行中的仿真Map
|
// 保存到运行中的仿真Map,但不启动tail进程
|
||||||
runningSimulations.set(simulationId, {
|
runningSimulations.set(simulationId, {
|
||||||
pid: processId,
|
pid: processId,
|
||||||
startTime: Date.now(),
|
startTime: Date.now(),
|
||||||
@ -332,37 +339,6 @@ router.post('/run-simulation', async (req, res) => {
|
|||||||
simulationId: processId.toString(),
|
simulationId: processId.toString(),
|
||||||
scenarioFile: args[0]
|
scenarioFile: args[0]
|
||||||
});
|
});
|
||||||
|
|
||||||
// 启动一个后台任务来监控日志文件
|
|
||||||
const tailProcess = spawn('tail', ['-f', logFile], {
|
|
||||||
stdio: ['ignore', 'pipe', 'pipe']
|
|
||||||
});
|
|
||||||
|
|
||||||
// 收集输出
|
|
||||||
tailProcess.stdout.on('data', (data) => {
|
|
||||||
const chunk = data.toString('utf8');
|
|
||||||
const simulation = runningSimulations.get(simulationId);
|
|
||||||
if (simulation) {
|
|
||||||
simulation.output += chunk;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 推送到SSE客户端
|
|
||||||
sendSSEMessage(simulationId, 'output', {
|
|
||||||
type: 'stdout',
|
|
||||||
data: chunk
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
// 当tail进程结束时
|
|
||||||
tailProcess.on('close', (code) => {
|
|
||||||
runningSimulations.delete(simulationId);
|
|
||||||
// 删除数据库中的进程记录
|
|
||||||
deleteXNEngineProcess(processId);
|
|
||||||
sendSSEMessage(simulationId, 'status', {
|
|
||||||
running: false,
|
|
||||||
message: '仿真进程已结束'
|
|
||||||
});
|
|
||||||
});
|
|
||||||
} else {
|
} else {
|
||||||
// 进程启动失败或不是XNEngine进程
|
// 进程启动失败或不是XNEngine进程
|
||||||
await deleteXNEngineProcess(processId);
|
await deleteXNEngineProcess(processId);
|
||||||
@ -500,4 +476,27 @@ router.get('/check-xnengine', async (req, res) => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// 添加清理仿真资源的接口
|
||||||
|
router.post('/cleanup-simulation/:id', (req, res) => {
|
||||||
|
const simulationId = req.params.id;
|
||||||
|
|
||||||
|
// 清理该仿真ID对应的所有资源
|
||||||
|
if (runningSimulations.has(simulationId)) {
|
||||||
|
// 清理tail进程
|
||||||
|
const simulation = runningSimulations.get(simulationId);
|
||||||
|
if (simulation.tailProcess) {
|
||||||
|
try {
|
||||||
|
simulation.tailProcess.kill();
|
||||||
|
} catch (error) {
|
||||||
|
console.error('清理tail进程失败:', error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 清理其他资源
|
||||||
|
runningSimulations.delete(simulationId);
|
||||||
|
}
|
||||||
|
|
||||||
|
res.json({ success: true, message: '仿真资源已清理' });
|
||||||
|
});
|
||||||
|
|
||||||
module.exports = router;
|
module.exports = router;
|
Loading…
x
Reference in New Issue
Block a user