diff --git a/script-meta-v2.json b/script-meta-v2.json index 03b15a4..03393fa 100644 --- a/script-meta-v2.json +++ b/script-meta-v2.json @@ -223,6 +223,15 @@ "publish_time": 1737272626141, "update_time": 1750472965160 }, + "list-ports.ts": { + "script_name": "list-ports.ts", + "script_length": 2072, + "script_sha256": "2033072a42dd8b05576eaac9f41fa97deff5010726861ac217a1c74478a7ae6e", + "script_full_url": "https://git.hatter.ink/hatter/ts-scripts/raw/branch/main/single-scripts/list-ports.ts", + "single_script_file": true, + "publish_time": 1776516833640, + "update_time": 1776516833640 + }, "lower.ts": { "script_name": "lower.ts", "script_length": 390, diff --git a/single-scripts/list-ports.ts b/single-scripts/list-ports.ts new file mode 100755 index 0000000..8850457 --- /dev/null +++ b/single-scripts/list-ports.ts @@ -0,0 +1,70 @@ +#!/usr/bin/env -S deno run --allow-all + +const ttyProc = await Deno.run({ + cmd: ["tput", "cols"], + stdout: "piped", + stderr: "piped", +}); +const ttyOutput = new TextDecoder().decode(await ttyProc.output()).trim(); +const terminalWidth = parseInt(ttyOutput) || 120; + +const netstatProc = await Deno.run({ + cmd: ["netstat", "-an"], + stdout: "piped", + stderr: "piped", +}); + +const output = await netstatProc.output(); +const decoded = new TextDecoder().decode(output); +const lines = decoded.split("\n"); + +const localWidth = 20; + +console.log("Active Internet connections (only servers)"); +console.log(`Proto Recv-Q Send-Q Local Address${" ".repeat(localWidth - 13)}Foreign Address State PID/Program name`); + +const listeningLines = lines.filter((line) => line.includes("LISTEN")); + +const seen = new Set(); +for (const line of listeningLines) { + const parts = line.trim().split(/\s+/); + if (parts.length < 5) continue; + + const proto = parts[0]; + const localAddr = parts[3]; + const state = parts[4]; + + const key = `${proto}:${localAddr}`; + if (seen.has(key)) continue; + seen.add(key); + + const port = localAddr.includes(".") + ? localAddr.split(".").pop() + : localAddr.split(":").pop(); + + const pidCmd = await Deno.run({ + cmd: ["lsof", "-i", `:${port}`, "-t"], + stdout: "piped", + stderr: "piped", + }); + const pidOutput = new TextDecoder().decode(await pidCmd.output()).trim(); + let pidInfo = "-"; + if (pidOutput) { + const pid = pidOutput.split("\n")[0]; + const nameCmd = await Deno.run({ + cmd: ["ps", "-p", pid, "-o", "args="], + stdout: "piped", + stderr: "piped", + }); + const nameOutput = new TextDecoder().decode(await nameCmd.output()).trim(); + pidInfo = nameOutput; + } + + const displayState = state === "*.*" ? "LISTEN" : state; + const localFormatted = localAddr.padEnd(localWidth); + const recvQ = "0".padStart(3); + const sendQ = "0".padStart(6); + console.log( + `${proto.padEnd(8)} ${recvQ} ${sendQ} ${localFormatted} ${"0.0.0.0:*".padEnd(22)} ${displayState.padEnd(11)} ${pidInfo}` + ); +}