whoisport 0.0.0-stage → 0.5.2
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/LICENSE +21 -0
- package/README.md +115 -2
- package/bin/whoisport.js +33 -0
- package/package.json +35 -4
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Kaitlyn Bassford
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,3 +1,116 @@
|
|
|
1
|
-
#
|
|
1
|
+
# whoisport
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
[](https://crates.io/crates/whoisport)
|
|
4
|
+
[](https://github.com/dpologdvinity/whoisport/actions/workflows/ci.yml)
|
|
5
|
+
|
|
6
|
+
Find out what is listening on a TCP or UDP port, and optionally kill it.
|
|
7
|
+
|
|
8
|
+

|
|
9
|
+
|
|
10
|
+
```console
|
|
11
|
+
$ whoisport 3000
|
|
12
|
+
port 3000
|
|
13
|
+
pid 373232
|
|
14
|
+
parent 373230
|
|
15
|
+
user kaitlyn
|
|
16
|
+
cmd node node_modules/.bin/vite --port 3000
|
|
17
|
+
cwd /home/kaitlyn/site
|
|
18
|
+
uptime 4m 12s
|
|
19
|
+
|
|
20
|
+
$ whoisport 3000 --kill
|
|
21
|
+
...
|
|
22
|
+
pid 373232: exited after SIGTERM
|
|
23
|
+
|
|
24
|
+
$ whoisport
|
|
25
|
+
PORT PID USER CMD
|
|
26
|
+
3000 373232 kaitlyn node node_modules/.bin/vite --port 3000
|
|
27
|
+
5432 ? ? ?
|
|
28
|
+
8080 41120 kaitlyn python3 -m http.server 8080
|
|
29
|
+
ports marked ? are owned by another user; run with sudo to see it
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
`lsof -i :3000` gives you a PID and a wall of columns. `whoisport` gives you the
|
|
33
|
+
command line, the directory it was started from, who owns it and how long it has
|
|
34
|
+
been running, which is usually what you need to decide whether to kill it.
|
|
35
|
+
|
|
36
|
+
## Install
|
|
37
|
+
|
|
38
|
+
```sh
|
|
39
|
+
cargo binstall whoisport # prebuilt binary, no compiling
|
|
40
|
+
cargo install whoisport # build from source
|
|
41
|
+
pipx install whoisport # or: uvx whoisport, pip install whoisport
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
macOS or Linux, with [Homebrew](https://brew.sh):
|
|
45
|
+
|
|
46
|
+
```sh
|
|
47
|
+
brew install dpologdvinity/tap/whoisport
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
Debian/Ubuntu or Fedora/RHEL: download the `.deb` or `.rpm` for your architecture
|
|
51
|
+
from the [Releases page](https://github.com/dpologdvinity/whoisport/releases), then
|
|
52
|
+
|
|
53
|
+
```sh
|
|
54
|
+
sudo apt install ./whoisport_*.deb # Debian, Ubuntu
|
|
55
|
+
sudo dnf install ./whoisport-*.rpm # Fedora, RHEL
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
Windows, with [Scoop](https://scoop.sh):
|
|
59
|
+
|
|
60
|
+
```powershell
|
|
61
|
+
scoop bucket add whoisport https://github.com/dpologdvinity/whoisport
|
|
62
|
+
scoop install whoisport
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
Or download a binary from the
|
|
66
|
+
[Releases page](https://github.com/dpologdvinity/whoisport/releases): Linux (static,
|
|
67
|
+
x86_64 and aarch64), macOS (Apple Silicon and Intel) and Windows (x86_64).
|
|
68
|
+
|
|
69
|
+
Works on **Linux** (reads `/proc` directly, no runtime dependencies), **macOS**
|
|
70
|
+
(uses the built-in `lsof`) and **Windows 10/11**.
|
|
71
|
+
|
|
72
|
+
## Usage
|
|
73
|
+
|
|
74
|
+
```
|
|
75
|
+
whoisport # list every listening port
|
|
76
|
+
whoisport <PORT>... # details for one or more ports
|
|
77
|
+
whoisport <PORT>... --kill [--force]
|
|
78
|
+
whoisport [<PORT>...] --json # machine-readable output
|
|
79
|
+
whoisport [<PORT>...] --udp # UDP instead of TCP
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
| Flag | Effect |
|
|
83
|
+
|-----------|---------------------------------------------------------------------|
|
|
84
|
+
| `--kill` | Ask the process to exit and wait up to 3 seconds. |
|
|
85
|
+
| `--force` | With `--kill`: forcibly terminate it if asking did not work. |
|
|
86
|
+
| `--json` | Print a JSON array with `port`, `proto`, `pid`, `ppid`, `user`, `cmd`, `cwd`, `uptime_secs`, `container`, `image`. |
|
|
87
|
+
| `--udp` | Look at UDP sockets instead of TCP. UDP has no listening state, so any bound socket without a remote peer counts. Windows doesn't report UDP peers, so there every bound UDP socket is listed, including short-lived client ones. |
|
|
88
|
+
|
|
89
|
+
Docker: when a port is published by a container, whoisport shows the container
|
|
90
|
+
name and image (`docker web (nginx:alpine)`), even when the `docker-proxy`
|
|
91
|
+
process itself is owned by root. It asks `docker ps` only in that case.
|
|
92
|
+
|
|
93
|
+
`--kill` always needs explicit ports; it never kills everything.
|
|
94
|
+
|
|
95
|
+
How `--kill` asks, per platform:
|
|
96
|
+
|
|
97
|
+
| Platform | `--kill` | `--force` |
|
|
98
|
+
|----------|-----------------------------------------------------------------|--------------------|
|
|
99
|
+
| Linux, macOS | `SIGTERM` | `SIGKILL` |
|
|
100
|
+
| Windows | Ctrl+C in the process's console, and `WM_CLOSE` to its windows | `TerminateProcess` |
|
|
101
|
+
|
|
102
|
+
On Windows, Ctrl+C reaches every program attached to a console, so whoisport only
|
|
103
|
+
sends it when the target's console holds nothing but the target, its child
|
|
104
|
+
processes and a shell. Otherwise it says so and leaves the choice of `--force` to you.
|
|
105
|
+
|
|
106
|
+
Exit codes: `0` success, `1` a requested port had nothing listening (or nothing
|
|
107
|
+
is listening at all), `2` invalid arguments, `3` a kill failed.
|
|
108
|
+
|
|
109
|
+
Checks IPv4 and IPv6 TCP sockets in the LISTEN state. On Linux, processes owned
|
|
110
|
+
by other users can't be inspected without `sudo`; they show up as `?`. On
|
|
111
|
+
Windows, details of system services need an elevated terminal. On macOS,
|
|
112
|
+
other users' listeners only appear when run with `sudo`.
|
|
113
|
+
|
|
114
|
+
## License
|
|
115
|
+
|
|
116
|
+
MIT
|
package/bin/whoisport.js
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
// Runs the prebuilt whoisport binary from the platform package that npm (or pnpm,
|
|
4
|
+
// yarn, bun) installed as an optional dependency.
|
|
5
|
+
const { spawnSync } = require("node:child_process");
|
|
6
|
+
|
|
7
|
+
const packages = {
|
|
8
|
+
"linux x64": "whoisport-linux-x64",
|
|
9
|
+
"linux arm64": "whoisport-linux-arm64",
|
|
10
|
+
"darwin x64": "whoisport-darwin-x64",
|
|
11
|
+
"darwin arm64": "whoisport-darwin-arm64",
|
|
12
|
+
"win32 x64": "whoisport-win32-x64",
|
|
13
|
+
};
|
|
14
|
+
const name = packages[`${process.platform} ${process.arch}`];
|
|
15
|
+
if (!name) {
|
|
16
|
+
console.error(`whoisport: no prebuilt binary for ${process.platform}-${process.arch}`);
|
|
17
|
+
process.exit(1);
|
|
18
|
+
}
|
|
19
|
+
const exe = process.platform === "win32" ? "whoisport.exe" : "whoisport";
|
|
20
|
+
let bin;
|
|
21
|
+
try {
|
|
22
|
+
bin = require.resolve(`${name}/bin/${exe}`);
|
|
23
|
+
} catch {
|
|
24
|
+
console.error(`whoisport: ${name} is not installed (optional dependencies skipped?)`);
|
|
25
|
+
process.exit(1);
|
|
26
|
+
}
|
|
27
|
+
const result = spawnSync(bin, process.argv.slice(2), { stdio: "inherit" });
|
|
28
|
+
if (result.error) {
|
|
29
|
+
console.error(`whoisport: ${result.error.message}`);
|
|
30
|
+
process.exit(1);
|
|
31
|
+
}
|
|
32
|
+
if (result.signal) process.kill(process.pid, result.signal);
|
|
33
|
+
process.exit(result.status ?? 1);
|
package/package.json
CHANGED
|
@@ -1,6 +1,37 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "whoisport",
|
|
3
|
-
"
|
|
4
|
-
"
|
|
5
|
-
"
|
|
6
|
-
|
|
3
|
+
"description": "Show what is listening on a TCP or UDP port, and optionally kill it",
|
|
4
|
+
"version": "0.5.2",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"repository": {
|
|
7
|
+
"type": "git",
|
|
8
|
+
"url": "git+https://github.com/dpologdvinity/whoisport.git"
|
|
9
|
+
},
|
|
10
|
+
"homepage": "https://github.com/dpologdvinity/whoisport",
|
|
11
|
+
"keywords": [
|
|
12
|
+
"port",
|
|
13
|
+
"process",
|
|
14
|
+
"cli",
|
|
15
|
+
"lsof",
|
|
16
|
+
"devtools",
|
|
17
|
+
"kill-port"
|
|
18
|
+
],
|
|
19
|
+
"bin": {
|
|
20
|
+
"whoisport": "bin/whoisport.js"
|
|
21
|
+
},
|
|
22
|
+
"files": [
|
|
23
|
+
"bin/",
|
|
24
|
+
"README.md",
|
|
25
|
+
"LICENSE"
|
|
26
|
+
],
|
|
27
|
+
"engines": {
|
|
28
|
+
"node": ">=16"
|
|
29
|
+
},
|
|
30
|
+
"optionalDependencies": {
|
|
31
|
+
"whoisport-linux-x64": "0.5.2",
|
|
32
|
+
"whoisport-linux-arm64": "0.5.2",
|
|
33
|
+
"whoisport-darwin-x64": "0.5.2",
|
|
34
|
+
"whoisport-darwin-arm64": "0.5.2",
|
|
35
|
+
"whoisport-win32-x64": "0.5.2"
|
|
36
|
+
}
|
|
37
|
+
}
|