kport 1.0.0__py3-none-any.whl

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.
@@ -0,0 +1,361 @@
1
+ Metadata-Version: 2.4
2
+ Name: kport
3
+ Version: 1.0.0
4
+ Summary: A cross-platform command-line tool to inspect and kill processes using specific ports
5
+ Home-page: https://github.com/farman20ali/port-killer
6
+ Author: Farman Ali (Alien)
7
+ Author-email: farman20ali@example.com
8
+ Project-URL: Bug Reports, https://github.com/farman20ali/port-killer/issues
9
+ Project-URL: Source, https://github.com/farman20ali/port-killer
10
+ Keywords: port,kill,process,network,cross-platform,cli
11
+ Classifier: Development Status :: 4 - Beta
12
+ Classifier: Intended Audience :: Developers
13
+ Classifier: Intended Audience :: System Administrators
14
+ Classifier: Topic :: System :: Networking
15
+ Classifier: Topic :: System :: Systems Administration
16
+ Classifier: License :: OSI Approved :: MIT License
17
+ Classifier: Programming Language :: Python :: 3
18
+ Classifier: Programming Language :: Python :: 3.6
19
+ Classifier: Programming Language :: Python :: 3.7
20
+ Classifier: Programming Language :: Python :: 3.8
21
+ Classifier: Programming Language :: Python :: 3.9
22
+ Classifier: Programming Language :: Python :: 3.10
23
+ Classifier: Programming Language :: Python :: 3.11
24
+ Classifier: Operating System :: OS Independent
25
+ Classifier: Operating System :: Microsoft :: Windows
26
+ Classifier: Operating System :: POSIX :: Linux
27
+ Classifier: Operating System :: MacOS
28
+ Requires-Python: >=3.6
29
+ Description-Content-Type: text/markdown
30
+ License-File: LICENSE
31
+ Dynamic: author
32
+ Dynamic: author-email
33
+ Dynamic: classifier
34
+ Dynamic: description
35
+ Dynamic: description-content-type
36
+ Dynamic: home-page
37
+ Dynamic: keywords
38
+ Dynamic: license-file
39
+ Dynamic: project-url
40
+ Dynamic: requires-python
41
+ Dynamic: summary
42
+
43
+ # šŸ”Ŗ kport - Cross-Platform Port Inspector and Killer
44
+
45
+ A simple, powerful command-line tool to inspect and kill processes using specific ports on Windows, Linux, and macOS.
46
+
47
+ ## ✨ Features
48
+
49
+ - šŸ” **Inspect ports** - Find which process is using a specific port
50
+ - šŸ”Ž **Inspect by process name** - Find all processes matching a name and their ports
51
+ - šŸ”Ŗ **Kill processes** - Terminate processes using specific ports
52
+ - šŸ“‹ **List all ports** - View all listening ports and their processes
53
+ - šŸŽÆ **Kill by process name** - Kill all processes matching a name (e.g., "node", "python")
54
+ - šŸ”„ **Kill multiple ports** - Kill processes on multiple ports at once
55
+ - šŸŽØ **Colorized output** - Easy-to-read colored terminal output
56
+ - āœ… **Confirmation prompts** - Safety confirmation before killing processes
57
+ - šŸŒ **Cross-platform** - Works on Windows, Linux, and macOS
58
+ - šŸš€ **Easy to use** - Simple command-line interface
59
+
60
+ ## šŸ“¦ Installation
61
+
62
+ ### Quick Install (Once Published to PyPI)
63
+
64
+ ```bash
65
+ pip install kport
66
+ ```
67
+
68
+ ### Install from GitHub
69
+
70
+ ```bash
71
+ pip install git+https://github.com/farman20ali/port-killer.git
72
+ ```
73
+
74
+ ### Install from Source
75
+
76
+ ```bash
77
+ # Clone the repository
78
+ git clone https://github.com/farman20ali/port-killer.git
79
+ cd port-killer
80
+
81
+ # Install
82
+ pip install .
83
+ ```
84
+
85
+ ### Install for Development
86
+
87
+ ```bash
88
+ # Install in editable mode
89
+ pip install -e .
90
+ ```
91
+
92
+ After installation, `kport` will be available globally in your terminal.
93
+
94
+ ### Run Without Installing
95
+
96
+ ```bash
97
+ # Run directly with Python
98
+ python kport.py -h
99
+ ```
100
+
101
+ > šŸ“– For detailed installation instructions, see [INSTALL.md](INSTALL.md)
102
+ >
103
+ > šŸš€ For publishing instructions, see [PUBLISH.md](PUBLISH.md)
104
+
105
+ ## šŸš€ Usage
106
+
107
+ ### Inspect a port
108
+
109
+ Find out which process is using a specific port:
110
+
111
+ ```bash
112
+ kport -i 8080
113
+ ```
114
+
115
+ Example output:
116
+ ```
117
+ šŸ” Inspecting port 8080...
118
+
119
+ āœ“ Port 8080 is being used by PID 12345
120
+
121
+ Process Information:
122
+ ──────────────────────────────────────────────────
123
+ PID: 12345
124
+ Image Name: node.exe
125
+ Session Name: Console
126
+ Mem Usage: 45,678 K
127
+ ```
128
+
129
+ ### Inspect by process name
130
+
131
+ Find all processes matching a name and see what ports they're using:
132
+
133
+ ```bash
134
+ kport -ip node
135
+ ```
136
+
137
+ Example output:
138
+ ```
139
+ šŸ” Inspecting processes matching 'node'...
140
+
141
+ Found 3 connection(s) for processes matching 'node':
142
+
143
+ PID Process Port State
144
+ ──────────────────────────────────────────────────────────────────────
145
+ 12345 node.exe 3000 LISTENING
146
+ 3001 LISTENING
147
+ 12346 node.exe 8080 LISTENING
148
+
149
+ āœ“ Total processes found: 2
150
+ āœ“ Total connections: 3
151
+ ```
152
+
153
+ ### Kill a process on a port
154
+
155
+ Terminate the process using a specific port:
156
+
157
+ ```bash
158
+ kport -k 8080
159
+ ```
160
+
161
+ Example output:
162
+ ```
163
+ šŸ”Ŗ Attempting to kill process on port 8080...
164
+
165
+ Found PID 12345 using port 8080
166
+
167
+ Process to be terminated:
168
+ PID: 12345
169
+ Image Name: node.exe
170
+
171
+ Are you sure you want to kill this process? (y/N): y
172
+
173
+ āœ“ Successfully killed process 12345
174
+ Port 8080 is now free.
175
+ ```
176
+
177
+ ### List all listening ports
178
+
179
+ View all active listening ports and their associated processes:
180
+
181
+ ```bash
182
+ kport -l
183
+ ```
184
+
185
+ Example output:
186
+ ```
187
+ šŸ“‹ Listing all active ports...
188
+
189
+ Protocol Local Address State PID
190
+ ──────────────────────────────────────────────────────────────────────
191
+ TCP 0.0.0.0:80 LISTENING 1234
192
+ TCP 0.0.0.0:443 LISTENING 1234
193
+ TCP 0.0.0.0:3000 LISTENING 5678
194
+ TCP 0.0.0.0:8080 LISTENING 9012
195
+ ```
196
+
197
+ ### Kill by process name
198
+
199
+ Kill all processes matching a specific name:
200
+
201
+ ```bash
202
+ kport -kp node
203
+ ```
204
+
205
+ Example output:
206
+ ```
207
+ šŸ”Ŗ Killing all processes matching 'node'...
208
+
209
+ Found 3 process(es) matching 'node':
210
+ ──────────────────────────────────────────────────
211
+ PID 12345: node.exe
212
+ PID 12346: node.exe
213
+ PID 12347: node.exe
214
+
215
+ Are you sure you want to kill 3 process(es)? (y/N): y
216
+
217
+ āœ“ Killed PID 12345
218
+ āœ“ Killed PID 12346
219
+ āœ“ Killed PID 12347
220
+
221
+ āœ“ Successfully killed 3/3 process(es)
222
+ ```
223
+
224
+ ### Kill multiple ports at once
225
+
226
+ Kill processes on multiple ports simultaneously:
227
+
228
+ ```bash
229
+ kport -ka 3000 3001 3002
230
+ ```
231
+
232
+ Example output:
233
+ ```
234
+ šŸ”Ŗ Killing processes on 3 port(s)...
235
+
236
+ Found processes on 3 port(s):
237
+ ──────────────────────────────────────────────────
238
+ Port 3000: PID 12345 (node.exe)
239
+ Port 3001: PID 12346 (node.exe)
240
+ Port 3002: PID 12347 (python.exe)
241
+
242
+ Are you sure you want to kill 3 process(es)? (y/N): y
243
+
244
+ āœ“ Killed process on port 3000 (PID 12345)
245
+ āœ“ Killed process on port 3001 (PID 12346)
246
+ āœ“ Killed process on port 3002 (PID 12347)
247
+
248
+ āœ“ Successfully killed 3/3 process(es)
249
+ Ports freed: 3000, 3001, 3002
250
+ ```
251
+
252
+ ### Show help
253
+
254
+ ```bash
255
+ kport -h
256
+ ```
257
+
258
+ ### Show version
259
+
260
+ ```bash
261
+ kport -v
262
+ ```
263
+
264
+ ## šŸ“š Command-Line Options
265
+
266
+ | Option | Long Form | Description |
267
+ |--------|-----------|-------------|
268
+ | `-i PORT` | `--inspect PORT` | Inspect which process is using the specified port |
269
+ | `-ip NAME` | `--inspect-process NAME` | Inspect all processes matching the given name and their ports |
270
+ | `-k PORT` | `--kill PORT` | Kill the process using the specified port |
271
+ | `-kp NAME` | `--kill-process NAME` | Kill all processes matching the given name |
272
+ | `-ka PORT [PORT ...]` | `--kill-all PORT [PORT ...]` | Kill processes on multiple ports at once |
273
+ | `-l` | `--list` | List all listening ports and their processes |
274
+ | `-v` | `--version` | Show version information |
275
+ | `-h` | `--help` | Show help message |
276
+
277
+ ## šŸ› ļø Requirements
278
+
279
+ - Python 3.6 or higher
280
+ - No external dependencies (uses only Python standard library)
281
+
282
+ ### Platform-specific tools
283
+
284
+ The tool uses platform-native commands:
285
+
286
+ - **Windows**: `netstat`, `tasklist`, `taskkill`
287
+ - **Linux/macOS**: `lsof`, `ps`, `kill`
288
+
289
+ These tools are typically pre-installed on all platforms.
290
+
291
+ ## šŸ”§ Development
292
+
293
+ ### Clone and setup
294
+
295
+ ```bash
296
+ git clone https://github.com/farman20ali/port-killer.git
297
+ cd port-killer
298
+
299
+ # Install in development mode
300
+ pip install -e .
301
+ ```
302
+
303
+ ### Run tests
304
+
305
+ ```bash
306
+ # Test inspecting a port
307
+ kport -i 80
308
+
309
+ # Test listing ports
310
+ kport -l
311
+ ```
312
+
313
+ ## šŸ¤ Contributing
314
+
315
+ Contributions are welcome! Please feel free to submit a Pull Request.
316
+
317
+ 1. Fork the repository
318
+ 2. Create your feature branch (`git checkout -b feature/AmazingFeature`)
319
+ 3. Commit your changes (`git commit -m 'Add some AmazingFeature'`)
320
+ 4. Push to the branch (`git push origin feature/AmazingFeature`)
321
+ 5. Open a Pull Request
322
+
323
+ ## šŸ“ License
324
+
325
+ This project is licensed under the MIT License - see the LICENSE file for details.
326
+
327
+ ## āš ļø Important Notes
328
+
329
+ - **Administrator/sudo privileges**: Killing processes may require elevated privileges on some systems
330
+ - **Port validation**: Port numbers must be between 1 and 65535
331
+ - **Safety**: The tool asks for confirmation before killing any process
332
+ - **Multiple processes**: If multiple processes use the same port, the first one found will be shown/killed
333
+
334
+ ## šŸ› Troubleshooting
335
+
336
+ ### "Permission denied" errors
337
+
338
+ On Linux/macOS, you may need to run with sudo:
339
+ ```bash
340
+ sudo kport -k 80
341
+ ```
342
+
343
+ On Windows, run your terminal as Administrator.
344
+
345
+ ### Port not found
346
+
347
+ Make sure the port number is correct and that a process is actually using it. Use `kport -l` to see all active ports.
348
+
349
+ ### Color output not working on Windows
350
+
351
+ Colors should work on Windows 10 and later. If you're on an older version, colors may not display correctly.
352
+
353
+ ## šŸ“§ Contact
354
+
355
+ Your Name - your.email@example.com
356
+
357
+ Project Link: [https://github.com/yourusername/port-killer](https://github.com/yourusername/port-killer)
358
+
359
+ ---
360
+
361
+ Made with ā¤ļø for developers who are tired of hunting down processes
@@ -0,0 +1,7 @@
1
+ kport.py,sha256=6nx8AasiXMfykoymzkqmAGTQ3OIMkEOoFcKYvApSGgQ,18043
2
+ kport-1.0.0.dist-info/licenses/LICENSE,sha256=QQ8MyuCI55RKsPJcc50I2sT59jvpRtD9kvA031BtYs8,1083
3
+ kport-1.0.0.dist-info/METADATA,sha256=zampNq2_T6Em0La-nnV2DwAtNLwoZsec6d7meG-GPt0,10183
4
+ kport-1.0.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
5
+ kport-1.0.0.dist-info/entry_points.txt,sha256=ppZIgJ1vrmYs2EO9NcVSFCaZj7oj7t6RnJo8ArPQiRo,37
6
+ kport-1.0.0.dist-info/top_level.txt,sha256=yzlMBPZ7a-pcCN4DR5MRPO-VjY3fWnILtFUQpEuA2xY,6
7
+ kport-1.0.0.dist-info/RECORD,,
@@ -0,0 +1,5 @@
1
+ Wheel-Version: 1.0
2
+ Generator: setuptools (80.9.0)
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
5
+
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ kport = kport:main
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 kport
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.
@@ -0,0 +1 @@
1
+ kport
kport.py ADDED
@@ -0,0 +1,440 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ kport - Cross-platform port inspector and killer
4
+ A simple command-line tool to inspect and kill processes using specific ports
5
+ """
6
+ import argparse
7
+ import os
8
+ import platform
9
+ import subprocess
10
+ import sys
11
+ import re
12
+
13
+
14
+ # ANSI color codes
15
+ class Colors:
16
+ RED = '\033[91m'
17
+ GREEN = '\033[92m'
18
+ YELLOW = '\033[93m'
19
+ BLUE = '\033[94m'
20
+ MAGENTA = '\033[95m'
21
+ CYAN = '\033[96m'
22
+ WHITE = '\033[97m'
23
+ BOLD = '\033[1m'
24
+ RESET = '\033[0m'
25
+
26
+
27
+ def colorize(text, color):
28
+ """Add color to text if terminal supports it"""
29
+ if platform.system() == "Windows":
30
+ # Enable ANSI colors on Windows 10+
31
+ os.system("")
32
+ return f"{color}{text}{Colors.RESET}"
33
+
34
+
35
+ def run(cmd):
36
+ """Execute shell command and return output"""
37
+ try:
38
+ return subprocess.check_output(cmd, shell=True, text=True, stderr=subprocess.DEVNULL)
39
+ except subprocess.CalledProcessError:
40
+ return ""
41
+ except Exception as e:
42
+ print(colorize(f"Error executing command: {e}", Colors.RED))
43
+ return ""
44
+
45
+
46
+ def validate_port(port):
47
+ """Validate if port number is in valid range"""
48
+ if not (1 <= port <= 65535):
49
+ print(colorize(f"Error: Port {port} is not valid. Port must be between 1 and 65535.", Colors.RED))
50
+ sys.exit(1)
51
+
52
+
53
+ def find_pid(port):
54
+ """Find process ID using given port"""
55
+ system = platform.system()
56
+
57
+ if system == "Windows":
58
+ out = run(f"netstat -ano | findstr :{port}")
59
+ if not out:
60
+ return None, None
61
+
62
+ # Parse the first line (could be multiple connections)
63
+ lines = out.strip().split('\n')
64
+ for line in lines:
65
+ parts = line.split()
66
+ if len(parts) >= 5:
67
+ pid = parts[-1]
68
+ proc_info = run(f'tasklist /FI "PID eq {pid}" /FO LIST')
69
+ return pid, proc_info
70
+
71
+ return None, None
72
+
73
+ else: # Linux, Ubuntu, macOS
74
+ out = run(f"lsof -t -i:{port}")
75
+ if not out:
76
+ return None, None
77
+
78
+ pid = out.strip().split('\n')[0] # Get first PID if multiple
79
+ proc_info = run(f"ps -p {pid} -o pid,user,command")
80
+ return pid, proc_info
81
+
82
+
83
+ def list_all_ports():
84
+ """List all listening ports and their processes"""
85
+ system = platform.system()
86
+
87
+ print(colorize("\nšŸ“‹ Listing all active ports...\n", Colors.CYAN + Colors.BOLD))
88
+
89
+ if system == "Windows":
90
+ out = run("netstat -ano | findstr LISTENING")
91
+ if not out:
92
+ print(colorize("No listening ports found.", Colors.YELLOW))
93
+ return
94
+
95
+ print(colorize(f"{'Protocol':<10} {'Local Address':<25} {'State':<15} {'PID':<10}", Colors.BOLD))
96
+ print("─" * 70)
97
+
98
+ for line in out.strip().split('\n'):
99
+ parts = line.split()
100
+ if len(parts) >= 5:
101
+ protocol = parts[0]
102
+ local_addr = parts[1]
103
+ state = parts[3]
104
+ pid = parts[4]
105
+ print(f"{protocol:<10} {local_addr:<25} {state:<15} {pid:<10}")
106
+
107
+ else: # Linux, Ubuntu, macOS
108
+ out = run("lsof -i -P -n | grep LISTEN")
109
+ if not out:
110
+ print(colorize("No listening ports found.", Colors.YELLOW))
111
+ return
112
+
113
+ print(colorize(f"{'Command':<20} {'PID':<10} {'User':<15} {'Address':<30}", Colors.BOLD))
114
+ print("─" * 80)
115
+
116
+ for line in out.strip().split('\n'):
117
+ parts = line.split()
118
+ if len(parts) >= 9:
119
+ command = parts[0]
120
+ pid = parts[1]
121
+ user = parts[2]
122
+ address = parts[8]
123
+ print(f"{command:<20} {pid:<10} {user:<15} {address:<30}")
124
+
125
+
126
+ def find_pids_by_process_name(process_name):
127
+ """Find all PIDs matching a process name"""
128
+ system = platform.system()
129
+ pids = []
130
+
131
+ if system == "Windows":
132
+ out = run(f'tasklist /FI "IMAGENAME eq {process_name}*" /FO CSV /NH')
133
+ if out:
134
+ for line in out.strip().split('\n'):
135
+ parts = line.replace('"', '').split(',')
136
+ if len(parts) >= 2:
137
+ try:
138
+ pid = parts[1]
139
+ pids.append(pid)
140
+ except (ValueError, IndexError):
141
+ continue
142
+ else: # Linux, Ubuntu, macOS
143
+ out = run(f"pgrep -f {process_name}")
144
+ if out:
145
+ pids = [pid.strip() for pid in out.strip().split('\n') if pid.strip()]
146
+
147
+ return pids
148
+
149
+
150
+ def get_process_name(pid):
151
+ """Get process name from PID"""
152
+ system = platform.system()
153
+
154
+ if system == "Windows":
155
+ out = run(f'tasklist /FI "PID eq {pid}" /FO CSV /NH')
156
+ if out:
157
+ parts = out.strip().split(',')[0].replace('"', '')
158
+ return parts
159
+ else:
160
+ out = run(f"ps -p {pid} -o comm=")
161
+ if out:
162
+ return out.strip()
163
+
164
+ return "Unknown"
165
+
166
+
167
+ def find_ports_by_process_name(process_name):
168
+ """Find all ports used by processes matching a name"""
169
+ system = platform.system()
170
+ process_port_map = [] # List of tuples: (pid, process_name, port)
171
+
172
+ if system == "Windows":
173
+ # Get all PIDs matching the process name
174
+ pids = find_pids_by_process_name(process_name)
175
+
176
+ if pids:
177
+ # For each PID, find what ports it's using
178
+ for pid in pids:
179
+ out = run(f"netstat -ano | findstr {pid}")
180
+ if out:
181
+ proc_name = get_process_name(pid)
182
+ ports_seen = set()
183
+
184
+ for line in out.strip().split('\n'):
185
+ parts = line.split()
186
+ if len(parts) >= 5 and parts[-1] == pid:
187
+ # Extract port from local address (format: IP:PORT)
188
+ local_addr = parts[1]
189
+ if ':' in local_addr:
190
+ port = local_addr.split(':')[-1]
191
+ if port not in ports_seen:
192
+ ports_seen.add(port)
193
+ state = parts[3] if len(parts) > 3 else "UNKNOWN"
194
+ process_port_map.append((pid, proc_name, port, state))
195
+
196
+ else: # Linux, Ubuntu, macOS
197
+ # Use lsof to find ports by process name
198
+ out = run(f"lsof -i -P -n | grep -i {process_name}")
199
+ if out:
200
+ for line in out.strip().split('\n'):
201
+ parts = line.split()
202
+ if len(parts) >= 9:
203
+ command = parts[0]
204
+ pid = parts[1]
205
+ # Extract port from address (format: *:PORT or IP:PORT)
206
+ address = parts[8]
207
+ if ':' in address:
208
+ port = address.split(':')[-1]
209
+ # Filter out non-LISTEN states if needed
210
+ state = "LISTEN" if "LISTEN" in line else "ESTABLISHED"
211
+ process_port_map.append((pid, command, port, state))
212
+
213
+ return process_port_map
214
+
215
+
216
+ def kill_pid(pid, silent=False):
217
+ """Kill process by PID"""
218
+ system = platform.system()
219
+
220
+ if system == "Windows":
221
+ result = run(f"taskkill /PID {pid} /F")
222
+ return result
223
+ else:
224
+ result = run(f"kill -9 {pid}")
225
+ return result if result else "Process killed successfully"
226
+
227
+
228
+ def main():
229
+ """Main entry point"""
230
+ parser = argparse.ArgumentParser(
231
+ description="šŸ”Ŗ kport - Cross-platform port inspector and killer",
232
+ epilog="Examples:\n"
233
+ " kport -i 8080 Inspect port 8080\n"
234
+ " kport -ip node Inspect all processes matching 'node'\n"
235
+ " kport -k 8080 Kill process using port 8080\n"
236
+ " kport -l List all listening ports\n"
237
+ " kport -kp node Kill all processes matching 'node'\n"
238
+ " kport -ka 3000 3001 3002 Kill processes on multiple ports\n",
239
+ formatter_class=argparse.RawDescriptionHelpFormatter
240
+ )
241
+ parser.add_argument("-i", "--inspect", type=int, metavar="PORT",
242
+ help="Inspect which process is using the specified port")
243
+ parser.add_argument("-ip", "--inspect-process", type=str, metavar="NAME",
244
+ help="Inspect all processes matching the given name")
245
+ parser.add_argument("-k", "--kill", type=int, metavar="PORT",
246
+ help="Kill the process using the specified port")
247
+ parser.add_argument("-kp", "--kill-process", type=str, metavar="NAME",
248
+ help="Kill all processes matching the given name")
249
+ parser.add_argument("-ka", "--kill-all", type=int, nargs="+", metavar="PORT",
250
+ help="Kill processes on multiple ports")
251
+ parser.add_argument("-l", "--list", action="store_true",
252
+ help="List all listening ports and their processes")
253
+ parser.add_argument("-v", "--version", action="version", version="kport 1.0.0")
254
+
255
+ args = parser.parse_args()
256
+
257
+ # If no arguments provided, show help
258
+ if not (args.inspect or args.inspect_process or args.kill or args.list or args.kill_process or args.kill_all):
259
+ parser.print_help()
260
+ sys.exit(0)
261
+
262
+ if args.list:
263
+ list_all_ports()
264
+
265
+ if args.inspect_process:
266
+ print(colorize(f"\nšŸ” Inspecting processes matching '{args.inspect_process}'...\n", Colors.CYAN + Colors.BOLD))
267
+
268
+ process_info = find_ports_by_process_name(args.inspect_process)
269
+
270
+ if not process_info:
271
+ print(colorize(f"āŒ No processes found matching '{args.inspect_process}'", Colors.RED))
272
+ else:
273
+ print(colorize(f"Found {len(process_info)} connection(s) for processes matching '{args.inspect_process}':\n", Colors.YELLOW))
274
+
275
+ # Group by PID for better display
276
+ pid_groups = {}
277
+ for pid, proc_name, port, state in process_info:
278
+ if pid not in pid_groups:
279
+ pid_groups[pid] = {'name': proc_name, 'ports': []}
280
+ pid_groups[pid]['ports'].append((port, state))
281
+
282
+ print(colorize(f"{'PID':<10} {'Process':<25} {'Port':<10} {'State':<15}", Colors.BOLD))
283
+ print("─" * 70)
284
+
285
+ for pid, data in pid_groups.items():
286
+ proc_name = data['name']
287
+ ports = data['ports']
288
+
289
+ # Print first port
290
+ if ports:
291
+ port, state = ports[0]
292
+ print(f"{colorize(pid, Colors.CYAN):<19} {proc_name:<25} {port:<10} {state:<15}")
293
+
294
+ # Print additional ports for same PID
295
+ for port, state in ports[1:]:
296
+ print(f"{'':<10} {'':<25} {port:<10} {state:<15}")
297
+
298
+ print(colorize(f"\nāœ“ Total processes found: {len(pid_groups)}", Colors.GREEN))
299
+ print(colorize(f"āœ“ Total connections: {len(process_info)}", Colors.GREEN))
300
+
301
+ if args.kill_process:
302
+ print(colorize(f"\nšŸ”Ŗ Killing all processes matching '{args.kill_process}'...\n", Colors.CYAN + Colors.BOLD))
303
+
304
+ pids = find_pids_by_process_name(args.kill_process)
305
+ if not pids:
306
+ print(colorize(f"āŒ No processes found matching '{args.kill_process}'", Colors.RED))
307
+ else:
308
+ print(colorize(f"Found {len(pids)} process(es) matching '{args.kill_process}':", Colors.YELLOW))
309
+ print("─" * 50)
310
+
311
+ for pid in pids:
312
+ proc_name = get_process_name(pid)
313
+ print(colorize(f" PID {pid}: {proc_name}", Colors.WHITE))
314
+
315
+ # Ask for confirmation
316
+ try:
317
+ confirm = input(colorize(f"\nAre you sure you want to kill {len(pids)} process(es)? (y/N): ", Colors.MAGENTA))
318
+ if confirm.lower() not in ['y', 'yes']:
319
+ print(colorize("Operation cancelled.", Colors.YELLOW))
320
+ sys.exit(0)
321
+ except KeyboardInterrupt:
322
+ print(colorize("\n\nOperation cancelled.", Colors.YELLOW))
323
+ sys.exit(0)
324
+
325
+ # Kill all processes
326
+ killed_count = 0
327
+ for pid in pids:
328
+ result = kill_pid(pid, silent=True)
329
+ if result or "SUCCESS" in str(result) or "killed" in str(result).lower():
330
+ killed_count += 1
331
+ print(colorize(f"āœ“ Killed PID {pid}", Colors.GREEN))
332
+ else:
333
+ print(colorize(f"āœ— Failed to kill PID {pid}", Colors.RED))
334
+
335
+ print(colorize(f"\nāœ“ Successfully killed {killed_count}/{len(pids)} process(es)", Colors.GREEN + Colors.BOLD))
336
+
337
+ if args.kill_all:
338
+ print(colorize(f"\nšŸ”Ŗ Killing processes on {len(args.kill_all)} port(s)...\n", Colors.CYAN + Colors.BOLD))
339
+
340
+ # Validate all ports first
341
+ for port in args.kill_all:
342
+ validate_port(port)
343
+
344
+ # Find all PIDs
345
+ port_pid_map = {}
346
+ for port in args.kill_all:
347
+ pid, info = find_pid(port)
348
+ if pid:
349
+ port_pid_map[port] = (pid, info)
350
+
351
+ if not port_pid_map:
352
+ print(colorize(f"āŒ No processes found on any of the specified ports", Colors.RED))
353
+ else:
354
+ print(colorize(f"Found processes on {len(port_pid_map)} port(s):", Colors.YELLOW))
355
+ print("─" * 50)
356
+
357
+ for port, (pid, info) in port_pid_map.items():
358
+ proc_name = get_process_name(pid)
359
+ print(colorize(f" Port {port}: PID {pid} ({proc_name})", Colors.WHITE))
360
+
361
+ # Ask for confirmation
362
+ try:
363
+ confirm = input(colorize(f"\nAre you sure you want to kill {len(port_pid_map)} process(es)? (y/N): ", Colors.MAGENTA))
364
+ if confirm.lower() not in ['y', 'yes']:
365
+ print(colorize("Operation cancelled.", Colors.YELLOW))
366
+ sys.exit(0)
367
+ except KeyboardInterrupt:
368
+ print(colorize("\n\nOperation cancelled.", Colors.YELLOW))
369
+ sys.exit(0)
370
+
371
+ # Kill all processes
372
+ killed_count = 0
373
+ for port, (pid, info) in port_pid_map.items():
374
+ result = kill_pid(pid, silent=True)
375
+ if result or "SUCCESS" in str(result) or "killed" in str(result).lower():
376
+ killed_count += 1
377
+ print(colorize(f"āœ“ Killed process on port {port} (PID {pid})", Colors.GREEN))
378
+ else:
379
+ print(colorize(f"āœ— Failed to kill process on port {port} (PID {pid})", Colors.RED))
380
+
381
+ print(colorize(f"\nāœ“ Successfully killed {killed_count}/{len(port_pid_map)} process(es)", Colors.GREEN + Colors.BOLD))
382
+ print(colorize(f"Ports freed: {', '.join(map(str, port_pid_map.keys()))}", Colors.GREEN))
383
+
384
+ if args.inspect:
385
+ validate_port(args.inspect)
386
+ print(colorize(f"\nšŸ” Inspecting port {args.inspect}...\n", Colors.CYAN + Colors.BOLD))
387
+
388
+ pid, info = find_pid(args.inspect)
389
+ if not pid:
390
+ print(colorize(f"āŒ No process found using port {args.inspect}", Colors.RED))
391
+ else:
392
+ print(colorize(f"āœ“ Port {args.inspect} is being used by PID {pid}", Colors.GREEN + Colors.BOLD))
393
+ print(colorize("\nProcess Information:", Colors.YELLOW))
394
+ print("─" * 50)
395
+ print(info)
396
+
397
+ if args.kill:
398
+ validate_port(args.kill)
399
+ print(colorize(f"\nšŸ”Ŗ Attempting to kill process on port {args.kill}...\n", Colors.CYAN + Colors.BOLD))
400
+
401
+ pid, info = find_pid(args.kill)
402
+ if not pid:
403
+ print(colorize(f"āŒ No process found using port {args.kill}", Colors.RED))
404
+ else:
405
+ print(colorize(f"Found PID {pid} using port {args.kill}", Colors.YELLOW))
406
+
407
+ # Show process info before killing
408
+ if info:
409
+ print(colorize("\nProcess to be terminated:", Colors.YELLOW))
410
+ print(info)
411
+
412
+ # Ask for confirmation
413
+ try:
414
+ confirm = input(colorize("\nAre you sure you want to kill this process? (y/N): ", Colors.MAGENTA))
415
+ if confirm.lower() not in ['y', 'yes']:
416
+ print(colorize("Operation cancelled.", Colors.YELLOW))
417
+ sys.exit(0)
418
+ except KeyboardInterrupt:
419
+ print(colorize("\n\nOperation cancelled.", Colors.YELLOW))
420
+ sys.exit(0)
421
+
422
+ result = kill_pid(pid)
423
+ if result:
424
+ print(colorize(f"\nāœ“ Successfully killed process {pid}", Colors.GREEN + Colors.BOLD))
425
+ if "SUCCESS" in result or "killed" in result.lower():
426
+ print(colorize(f"Port {args.kill} is now free.", Colors.GREEN))
427
+ else:
428
+ print(colorize(f"\nāŒ Failed to kill process {pid}", Colors.RED))
429
+ print(colorize("You may need administrator/sudo privileges.", Colors.YELLOW))
430
+
431
+
432
+ if __name__ == "__main__":
433
+ try:
434
+ main()
435
+ except KeyboardInterrupt:
436
+ print(colorize("\n\nOperation cancelled by user.", Colors.YELLOW))
437
+ sys.exit(0)
438
+ except Exception as e:
439
+ print(colorize(f"\nUnexpected error: {e}", Colors.RED))
440
+ sys.exit(1)