UNPKG

monex

Version:

Execute one or multiple scripts, interactively or in daemon mode, and restart them whenever they crash or a watched file changes.

91 lines (90 loc) 2.63 kB
/* IMPORT */ import process from 'node:process'; import pidtree from 'pidtree'; import pidusage from 'pidusage'; /* MAIN */ const PID = { /* TREE API */ tree: { get: async (pid) => { try { if (!pid) return []; return await pidtree(pid, { root: true }); } catch { return; } }, kill: async (pid, treeFallback = [pid]) => { if (!pid) return; const pids = await PID.tree.get(pid) || treeFallback; await Promise.all(pids.map(PID.kill)); }, usage: async (pid, treeFallback = [pid]) => { if (!pid) return; const pids = await PID.tree.get(pid) || treeFallback; const usages = (await Promise.all(pids.map(PID.usage))).filter(usage => usage); //TSC if (!usages.length) return; return usages.reduce((acc, usage) => ({ cpu: acc.cpu + usage.cpu, memory: acc.memory + usage.memory, birthtime: acc.birthtime, uptime: acc.uptime }), usages[0]); } }, /* API */ exists: (pid) => { try { return process.kill(pid, 0); } catch (error) { return (error instanceof Error) && ('code' in error) && (error.code === 'EPERM'); } }, kill: async (pid) => { if (!pid) return; return new Promise(async (resolve) => { PID.signal(pid, 'SIGTERM'); // Some patience const timeoutId = setTimeout(() => { PID.signal(pid, 'SIGKILL'); PID.signal(pid, 'SIGKILL'); PID.signal(pid, 'SIGKILL'); }, 3000); const intervalId = setInterval(async () => { if (PID.exists(pid)) return; clearTimeout(timeoutId); clearInterval(intervalId); resolve(); }, 50); }); }, signal: (pid, signal) => { try { return process.kill(pid, signal); } catch { return false; } }, usage: async (pid) => { if (!pid) return; try { const { cpu, memory, elapsed: uptime } = await pidusage(pid); const birthtime = Date.now() - uptime; return { cpu, memory, birthtime, uptime }; } catch { return; } } }; /* EXPORT */ export default PID;