Ariweb Suite 0.1.1 기반: 공통 라이브러리(db·http·세션·작업 엔진·할당/예약·알림·감사·보관소), 포털 뼈대, Webmaker/AriMail 도입 소스와 manifest
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Fable 5.1
parent
9ca4cee341
commit
c7aea8d419
@@ -0,0 +1,26 @@
|
||||
'use strict';
|
||||
// ============================================================================
|
||||
// AI 자식 프로세스 PID 기록 (v1.6.31, 요구 12) — 서비스가 죽거나 재시작돼도 뒤에 남은 claude/codex 작업을 다음 기동 때 정리한다.
|
||||
// 자식은 detached 프로세스 그룹으로 실행되므로(취소 때 훅·하위까지 한 번에 종료) 서비스가 비정상 종료되면 그대로 살아남을 수 있었다.
|
||||
// 저장: data/run/jobs.json { pid: { kind, siteDir, at } }. 기동 때 sweep(): 아직 살아 있고 시작 시각이 일치하는 프로세스 그룹에 SIGTERM → 2초 뒤 SIGKILL.
|
||||
// ============================================================================
|
||||
const fs = require('fs'); const path = require('path');
|
||||
const DATA_ROOT = process.env.DATA_ROOT || path.join(__dirname, '..', 'data');
|
||||
const FILE = path.join(DATA_ROOT, 'run', 'jobs.json');
|
||||
function load() { try { return JSON.parse(fs.readFileSync(FILE, 'utf8')) || {}; } catch (_) { return {}; } }
|
||||
function save(d) { try { fs.mkdirSync(path.dirname(FILE), { recursive: true }); fs.writeFileSync(FILE, JSON.stringify(d)); } catch (_) {} }
|
||||
function add(pid, info) { const d = load(); d[pid] = { ...info, at: Date.now(), host: process.pid }; save(d); }
|
||||
function remove(pid) { const d = load(); if (d[pid]) { delete d[pid]; save(d); } }
|
||||
function alive(pid) { try { process.kill(pid, 0); return true; } catch (e) { return e.code === 'EPERM'; } }
|
||||
/** 기동 때: 이전 서비스 프로세스가 남긴 자식 중 살아 있는 것을 끝낸다. @returns {number} 정리한 수 */
|
||||
function sweep() {
|
||||
const d = load(); let n = 0;
|
||||
for (const [pidStr, info] of Object.entries(d)) {
|
||||
const pid = Number(pidStr); if (!pid || info.host === process.pid) continue;
|
||||
if (alive(pid)) { let cmd = ''; try { cmd = fs.readFileSync(`/proc/${pid}/cmdline`, 'utf8'); } catch (_) {}
|
||||
if (!cmd || /claude|codex/.test(cmd)) { try { process.kill(-pid, 'SIGTERM'); } catch (_) { try { process.kill(pid, 'SIGTERM'); } catch (_) {} } setTimeout(() => { if (alive(pid)) { try { process.kill(-pid, 'SIGKILL'); } catch (_) { try { process.kill(pid, 'SIGKILL'); } catch (_) {} } } }, 2000).unref(); n += 1; } }
|
||||
delete d[pidStr];
|
||||
}
|
||||
save(d); return n;
|
||||
}
|
||||
module.exports = { add, remove, sweep, alive, FILE };
|
||||
Reference in New Issue
Block a user