pyre-cli 4.13.0 → 4.15.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +42 -5
- package/package.json +1 -1
- package/src/index.ts +45 -0
- package/src/monitors/collectors.ts +13 -14
package/dist/index.js
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
// src/index.ts
|
|
4
4
|
import fs4 from "fs";
|
|
5
|
+
import os from "os";
|
|
5
6
|
import readline2 from "readline";
|
|
6
7
|
import { Command } from "commander";
|
|
7
8
|
import chalk9 from "chalk";
|
|
@@ -504,15 +505,14 @@ async function collectProcesses(limit) {
|
|
|
504
505
|
try {
|
|
505
506
|
const isMac = process.platform === "darwin";
|
|
506
507
|
const sortArg = isMac ? "-r" : "--sort=-pcpu";
|
|
507
|
-
const threadsArg = isMac ? "threads" : "nlwp";
|
|
508
508
|
const headClause = limit && limit > 0 ? ` | head -n ${limit + 1}` : "";
|
|
509
|
-
const raw = (await run(`ps -eo pid,ppid,user,pcpu,pmem,state
|
|
509
|
+
const raw = (await run(`ps -eo pid,ppid,user,pcpu,pmem,state,time,comm ${sortArg}${headClause}`)).trim();
|
|
510
510
|
const lines = raw.split("\n").slice(1);
|
|
511
511
|
return lines.map((line) => {
|
|
512
|
-
const parts = line.match(/\s*(\d+)\s+(\d+)\s+(\S+)\s+([\d.]+)\s+([\d.]+)\s+(\S+)\s+(
|
|
512
|
+
const parts = line.match(/\s*(\d+)\s+(\d+)\s+(\S+)\s+([\d.]+)\s+([\d.]+)\s+(\S+)\s+([\d:.]+)\s+(.+)/);
|
|
513
513
|
if (!parts) return null;
|
|
514
|
-
const runtimeSec = parts[
|
|
515
|
-
return { pid: parseInt(parts[1]), ppid: parseInt(parts[2]), user: parts[3], cpu: parseFloat(parts[4]), mem: parseFloat(parts[5]), state: parts[6], threads:
|
|
514
|
+
const runtimeSec = parts[7].split(":").reduce((acc, val, idx) => acc + parseInt(val) * Math.pow(60, 2 - idx), 0);
|
|
515
|
+
return { pid: parseInt(parts[1]), ppid: parseInt(parts[2]), user: parts[3], cpu: parseFloat(parts[4]), mem: parseFloat(parts[5]), state: parts[6], threads: 0, runtime: runtimeSec, command: parts[8] };
|
|
516
516
|
}).filter((p) => p !== null && p.pid > 0);
|
|
517
517
|
} catch {
|
|
518
518
|
return [];
|
|
@@ -3222,8 +3222,45 @@ function stripAnsi(s) {
|
|
|
3222
3222
|
function sanitizeHost2(host) {
|
|
3223
3223
|
return host.trim().replace(/%$/, "");
|
|
3224
3224
|
}
|
|
3225
|
+
function detectLocalIP() {
|
|
3226
|
+
const ifaces = os.networkInterfaces();
|
|
3227
|
+
for (const [, addrs] of Object.entries(ifaces)) {
|
|
3228
|
+
if (!addrs) continue;
|
|
3229
|
+
for (const addr of addrs) {
|
|
3230
|
+
if (addr.family === "IPv4" && !addr.internal) {
|
|
3231
|
+
return addr.address;
|
|
3232
|
+
}
|
|
3233
|
+
}
|
|
3234
|
+
}
|
|
3235
|
+
return null;
|
|
3236
|
+
}
|
|
3237
|
+
async function runServerCommand() {
|
|
3238
|
+
const ip = detectLocalIP();
|
|
3239
|
+
if (!ip) {
|
|
3240
|
+
console.log(chalk9.red("Could not detect a non-loopback IP address. Connect to a network first."));
|
|
3241
|
+
process.exit(1);
|
|
3242
|
+
}
|
|
3243
|
+
const port = 9876;
|
|
3244
|
+
const password = "mysecret";
|
|
3245
|
+
console.log(chalk9.bold(`
|
|
3246
|
+
pyre server`));
|
|
3247
|
+
console.log(chalk9.dim(` Detected IP: ${ip}`));
|
|
3248
|
+
console.log(chalk9.dim(` Port: ${port}`));
|
|
3249
|
+
console.log(chalk9.dim(` Password: ${password}`));
|
|
3250
|
+
console.log();
|
|
3251
|
+
console.log(chalk9.bold("Run this on THIS machine (server):"));
|
|
3252
|
+
console.log(chalk9.hex("#ff6a39")(`pyre p2p server --p2p-host 0.0.0.0 --p2p-port ${port} --p2p-password ${password}`));
|
|
3253
|
+
console.log();
|
|
3254
|
+
console.log(chalk9.bold("Run this on the OTHER machine (client):"));
|
|
3255
|
+
console.log(chalk9.hex("#ff6a39")(`pyre p2p connect --p2p-host ${ip} --p2p-port ${port} --p2p-password ${password}`));
|
|
3256
|
+
console.log();
|
|
3257
|
+
}
|
|
3225
3258
|
async function main() {
|
|
3226
3259
|
const cmd = program.args[0];
|
|
3260
|
+
if (cmd === "server") {
|
|
3261
|
+
await runServerCommand();
|
|
3262
|
+
return;
|
|
3263
|
+
}
|
|
3227
3264
|
if (cmd === "live" || !isExportMode() && !opts.once && cmd !== "p2p") {
|
|
3228
3265
|
if (cmd === "live") {
|
|
3229
3266
|
program.args.shift();
|
package/package.json
CHANGED
package/src/index.ts
CHANGED
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
* P2P mode enables live data streaming between two systems over TCP.
|
|
8
8
|
*/
|
|
9
9
|
import fs from 'node:fs';
|
|
10
|
+
import os from 'node:os';
|
|
10
11
|
import readline from 'node:readline';
|
|
11
12
|
import { Command } from 'commander';
|
|
12
13
|
import chalk from 'chalk';
|
|
@@ -69,9 +70,53 @@ function sanitizeHost(host: string): string {
|
|
|
69
70
|
return host.trim().replace(/%$/, '');
|
|
70
71
|
}
|
|
71
72
|
|
|
73
|
+
function detectLocalIP(): string | null {
|
|
74
|
+
const ifaces = os.networkInterfaces();
|
|
75
|
+
for (const [, addrs] of Object.entries(ifaces)) {
|
|
76
|
+
if (!addrs) continue;
|
|
77
|
+
for (const addr of addrs) {
|
|
78
|
+
if (addr.family === 'IPv4' && !addr.internal) {
|
|
79
|
+
return addr.address;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
return null;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
async function runServerCommand(): Promise<void> {
|
|
87
|
+
const ip = detectLocalIP();
|
|
88
|
+
|
|
89
|
+
if (!ip) {
|
|
90
|
+
console.log(chalk.red('Could not detect a non-loopback IP address. Connect to a network first.'));
|
|
91
|
+
process.exit(1);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
const port = 9876;
|
|
95
|
+
const password = 'mysecret';
|
|
96
|
+
|
|
97
|
+
console.log(chalk.bold(`\n pyre server`));
|
|
98
|
+
console.log(chalk.dim(` Detected IP: ${ip}`));
|
|
99
|
+
console.log(chalk.dim(` Port: ${port}`));
|
|
100
|
+
console.log(chalk.dim(` Password: ${password}`));
|
|
101
|
+
console.log();
|
|
102
|
+
|
|
103
|
+
console.log(chalk.bold('Run this on THIS machine (server):'));
|
|
104
|
+
console.log(chalk.hex('#ff6a39')(`pyre p2p server --p2p-host 0.0.0.0 --p2p-port ${port} --p2p-password ${password}`));
|
|
105
|
+
console.log();
|
|
106
|
+
|
|
107
|
+
console.log(chalk.bold('Run this on the OTHER machine (client):'));
|
|
108
|
+
console.log(chalk.hex('#ff6a39')(`pyre p2p connect --p2p-host ${ip} --p2p-port ${port} --p2p-password ${password}`));
|
|
109
|
+
console.log();
|
|
110
|
+
}
|
|
111
|
+
|
|
72
112
|
async function main() {
|
|
73
113
|
const cmd = program.args[0];
|
|
74
114
|
|
|
115
|
+
if (cmd === 'server') {
|
|
116
|
+
await runServerCommand();
|
|
117
|
+
return;
|
|
118
|
+
}
|
|
119
|
+
|
|
75
120
|
if (cmd === 'live' || (!isExportMode() && !opts.once && cmd !== 'p2p')) {
|
|
76
121
|
if (cmd === 'live') {
|
|
77
122
|
program.args.shift();
|
|
@@ -606,20 +606,19 @@ export async function collectNetwork(): Promise<NetworkData> {
|
|
|
606
606
|
|
|
607
607
|
export async function collectProcesses(limit?: number): Promise<ProcessData[]> {
|
|
608
608
|
try {
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
.filter((p): p is ProcessData => p !== null && p.pid > 0);
|
|
609
|
+
const isMac = process.platform === 'darwin';
|
|
610
|
+
const sortArg = isMac ? '-r' : '--sort=-pcpu';
|
|
611
|
+
const headClause = limit && limit > 0 ? ` | head -n ${limit + 1}` : '';
|
|
612
|
+
const raw = (await run(`ps -eo pid,ppid,user,pcpu,pmem,state,time,comm ${sortArg}${headClause}`)).trim();
|
|
613
|
+
const lines = raw.split('\n').slice(1);
|
|
614
|
+
return lines
|
|
615
|
+
.map(line => {
|
|
616
|
+
const parts = line.match(/\s*(\d+)\s+(\d+)\s+(\S+)\s+([\d.]+)\s+([\d.]+)\s+(\S+)\s+([\d:.]+)\s+(.+)/);
|
|
617
|
+
if (!parts) return null;
|
|
618
|
+
const runtimeSec = parts[7].split(':').reduce((acc, val, idx) => acc + parseInt(val) * Math.pow(60, 2 - idx), 0);
|
|
619
|
+
return { pid: parseInt(parts[1]), ppid: parseInt(parts[2]), user: parts[3], cpu: parseFloat(parts[4]), mem: parseFloat(parts[5]), state: parts[6], threads: 0, runtime: runtimeSec, command: parts[8] };
|
|
620
|
+
})
|
|
621
|
+
.filter((p): p is ProcessData => p !== null && p.pid > 0);
|
|
623
622
|
} catch {
|
|
624
623
|
return [];
|
|
625
624
|
}
|