Files
ts-scripts/single-scripts/list-ports.ts

71 lines
2.0 KiB
TypeScript
Executable File

#!/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<string>();
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}`
);
}