diff --git a/apps/cli/package.json b/apps/cli/package.json index f701f429..a2bd0de5 100644 --- a/apps/cli/package.json +++ b/apps/cli/package.json @@ -34,12 +34,14 @@ "homepage": "https://github.com/msgbyte/tailchat-cli#readme", "dependencies": { "@types/dockerode": "^3.3.10", + "@types/pidusage": "^2.0.2", "as-table": "^1.0.55", "chalk": "4.1.2", "crypto-random-string": "3.3.1", "dockerode": "^3.3.4", "dotenv": "^16.0.0", "filesize": "^8.0.7", + "find-process": "^1.4.7", "fs-extra": "^10.1.0", "got": "11.8.5", "ink": "^3.2.0", @@ -51,6 +53,7 @@ "ora": "5.4.1", "p-all": "2.1.0", "p-series": "2.1.0", + "pidusage": "^3.0.2", "plop": "^3.0.5", "pretty-ms": "7.0.1", "react": "18.2.0", diff --git a/apps/cli/src/commands/usage.ts b/apps/cli/src/commands/usage.ts new file mode 100644 index 00000000..005e278d --- /dev/null +++ b/apps/cli/src/commands/usage.ts @@ -0,0 +1,54 @@ +import { CommandModule } from 'yargs'; +import path from 'path'; +import inquirer from 'inquirer'; +import find from 'find-process'; +import pidusage from 'pidusage'; +import _ from 'lodash'; + +export const usageCommand: CommandModule = { + command: 'usage [pid]', + describe: '查看 Tailchat 进程用量', + builder: (yargs) => + yargs.positional('pid', { + demandOption: false, + description: '进程ID', + type: 'number', + }), + async handler(args) { + let pidList: number[] = []; + + if (!args.pid) { + const list = await find('name', 'tailchat'); + + const processList = list.filter((item) => item.pid !== process.pid); + + const res = await inquirer.prompt([ + { + type: 'checkbox', + name: 'process', + message: '选择需要查看的进程', + choices: processList.map((item) => ({ + name: `(${item.pid})${item.cmd}`, + value: item.pid, + })), + }, + ]); + + pidList = res.process; + } else { + if (Array.isArray(args.pid)) { + pidList = args.pid; + } else { + pidList = [args.pid as number]; + } + } + + const stats = await pidusage(pidList); + const res = Object.entries(stats).map(([pid, info]) => ({ + pid, + cpu: info.cpu, + memory: `${info.memory / 1024 / 1024} MB`, + })); + console.table(res); + }, +}; diff --git a/apps/cli/src/index.ts b/apps/cli/src/index.ts index 3f76002e..fb1abecc 100644 --- a/apps/cli/src/index.ts +++ b/apps/cli/src/index.ts @@ -6,6 +6,7 @@ import { appCommand } from './commands/app'; import { declarationCommand } from './commands/declaration'; import { benchCommand } from './commands/bench'; import { dockerCommand } from './commands/docker'; +import { usageCommand } from './commands/usage'; yargs .demandCommand() @@ -15,6 +16,7 @@ yargs .command(benchCommand) .command(declarationCommand) .command(dockerCommand) + .command(usageCommand) .alias('h', 'help') .scriptName('tailchat') .parse(); diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 7036716c..6a077a45 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -65,6 +65,7 @@ importers: '@types/inquirer': ^8.2.1 '@types/lodash': ^4.14.170 '@types/node': 16.11.7 + '@types/pidusage': ^2.0.2 '@types/react': 18.0.20 '@types/spinnies': ^0.5.0 '@types/update-notifier': ^6.0.1 @@ -76,6 +77,7 @@ importers: dockerode: ^3.3.4 dotenv: ^16.0.0 filesize: ^8.0.7 + find-process: ^1.4.7 fs-extra: ^10.1.0 got: 11.8.5 ink: ^3.2.0 @@ -87,6 +89,7 @@ importers: ora: 5.4.1 p-all: 2.1.0 p-series: 2.1.0 + pidusage: ^3.0.2 plop: ^3.0.5 pretty-ms: 7.0.1 react: 18.2.0 @@ -100,12 +103,14 @@ importers: yargs: ^17.4.0 dependencies: '@types/dockerode': 3.3.10 + '@types/pidusage': 2.0.2 as-table: 1.0.55 chalk: 4.1.2 crypto-random-string: 3.3.1 dockerode: 3.3.4 dotenv: 16.0.2 filesize: 8.0.7 + find-process: 1.4.7 fs-extra: 10.1.0 got: 11.8.5 ink: 3.2.0_w5j4k42lgipnm43s3brx6h3c34 @@ -117,6 +122,7 @@ importers: ora: 5.4.1 p-all: 2.1.0 p-series: 2.1.0 + pidusage: 3.0.2 plop: 3.1.1 pretty-ms: 7.0.1 react: 18.2.0 @@ -13345,6 +13351,10 @@ packages: '@types/express': 4.17.15 dev: false + /@types/pidusage/2.0.2: + resolution: {integrity: sha512-lHgpGZjXDfjggZDLkgp4zQTYkvXq4S7RxjBjrDcPe1MBU72hESWxubutx8+AM4QkJdRxAhrQyxSA6pzHKJKlsQ==} + dev: false + /@types/pino-http/5.8.1: resolution: {integrity: sha512-A9MW6VCnx5ii7s+Fs5aFIw+aSZcBCpsZ/atpxamu8tTsvWFacxSf2Hrn1Ohn1jkVRB/LiPGOapRXcFawDBnDnA==} dependencies: @@ -21287,6 +21297,17 @@ packages: make-dir: 3.1.0 pkg-dir: 4.2.0 + /find-process/1.4.7: + resolution: {integrity: sha512-/U4CYp1214Xrp3u3Fqr9yNynUrr5Le4y0SsJh2lMDDSbpwYSz3M2SMWQC+wqcx79cN8PQtHQIL8KnuY9M66fdg==} + hasBin: true + dependencies: + chalk: 4.1.2 + commander: 5.1.0 + debug: 4.3.4 + transitivePeerDependencies: + - supports-color + dev: false + /find-root/1.1.0: resolution: {integrity: sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng==} dev: false @@ -29207,6 +29228,13 @@ packages: hasBin: true dev: true + /pidusage/3.0.2: + resolution: {integrity: sha512-g0VU+y08pKw5M8EZ2rIGiEBaB8wrQMjYGFfW2QVIfyT8V+fq8YFLkvlz4bz5ljvFDJYNFCWT3PWqcRr2FKO81w==} + engines: {node: '>=10'} + dependencies: + safe-buffer: 5.2.1 + dev: false + /pify/2.3.0: resolution: {integrity: sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==} engines: {node: '>=0.10.0'}