checkport 2.0.0__tar.gz

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,66 @@
1
+ Metadata-Version: 2.4
2
+ Name: checkport
3
+ Version: 2.0.0
4
+ Summary: Port management tool for checking and killing processes on specific ports
5
+ Home-page: https://github.com/watcher1337/checkport
6
+ Author: watcher1337
7
+ Author-email: watcher1337 <watcher1337@example.com>
8
+ License: MIT
9
+ Classifier: Programming Language :: Python :: 3
10
+ Classifier: Programming Language :: Python :: 3.8
11
+ Classifier: Programming Language :: Python :: 3.9
12
+ Classifier: Programming Language :: Python :: 3.10
13
+ Classifier: Programming Language :: Python :: 3.11
14
+ Classifier: Programming Language :: Python :: 3.12
15
+ Classifier: Programming Language :: Python :: 3.13
16
+ Classifier: License :: OSI Approved :: MIT License
17
+ Classifier: Operating System :: OS Independent
18
+ Requires-Python: >=3.8
19
+ Description-Content-Type: text/markdown
20
+ Dynamic: author
21
+ Dynamic: home-page
22
+ Dynamic: requires-python
23
+
24
+ # checkport
25
+
26
+ [![GitHub release](https://img.shields.io/github/release/watcher1337/checkport.svg)](https://github.com/watcher1337/checkport/releases/latest)
27
+ [![Python 3.8+](https://img.shields.io/badge/python-3.8+-blue.svg)](https://www.python.org/)
28
+ [![Platform](https://img.shields.io/badge/platform-Windows%20%7C%20Linux%20%7C%20macOS-lightgrey.svg)](https://github.com/watcher1337/checkport/releases)
29
+
30
+ **A powerful port management tool for checking and killing processes running on specific ports. Cross-platform and easy to use.**
31
+
32
+ ---
33
+
34
+ ## 📋 Table of Contents
35
+
36
+ - [Features](#-features)
37
+ - [Quick Install](#-quick-install)
38
+ - [Usage](#-usage)
39
+ - [Examples](#-examples)
40
+ - [Building from Source](#-building-from-source)
41
+
42
+ ---
43
+
44
+ ## ✨ Features
45
+
46
+ - 🔍 **Port Checking** – Check if a port is in use and get process information
47
+ - 🔪 **Process Killing** – Kill processes running on specific ports with graceful termination
48
+ - 📋 **List Ports** – Display all listening ports with process details
49
+ - 🔎 **Port Scanning** – Scan a range of ports to find open ones
50
+ - 🖥️ **Cross-platform** – Windows, Linux, macOS (x64 & ARM64)
51
+ - 🎨 **Colored Output** – Beautiful terminal output with status indicators
52
+ - 🚀 **Fast** – Concurrent scanning for quick results
53
+ - 💪 **Force Kill** – Force kill processes when graceful termination fails
54
+
55
+ ---
56
+
57
+ ## 🚀 Quick Install
58
+
59
+ ### Using pip / pipx
60
+
61
+ ```bash
62
+ # Install using pip
63
+ pip install checkport
64
+
65
+ # Install using pipx (recommended for CLI tools)
66
+ pipx install checkport
@@ -0,0 +1,43 @@
1
+ # checkport
2
+
3
+ [![GitHub release](https://img.shields.io/github/release/watcher1337/checkport.svg)](https://github.com/watcher1337/checkport/releases/latest)
4
+ [![Python 3.8+](https://img.shields.io/badge/python-3.8+-blue.svg)](https://www.python.org/)
5
+ [![Platform](https://img.shields.io/badge/platform-Windows%20%7C%20Linux%20%7C%20macOS-lightgrey.svg)](https://github.com/watcher1337/checkport/releases)
6
+
7
+ **A powerful port management tool for checking and killing processes running on specific ports. Cross-platform and easy to use.**
8
+
9
+ ---
10
+
11
+ ## 📋 Table of Contents
12
+
13
+ - [Features](#-features)
14
+ - [Quick Install](#-quick-install)
15
+ - [Usage](#-usage)
16
+ - [Examples](#-examples)
17
+ - [Building from Source](#-building-from-source)
18
+
19
+ ---
20
+
21
+ ## ✨ Features
22
+
23
+ - 🔍 **Port Checking** – Check if a port is in use and get process information
24
+ - 🔪 **Process Killing** – Kill processes running on specific ports with graceful termination
25
+ - 📋 **List Ports** – Display all listening ports with process details
26
+ - 🔎 **Port Scanning** – Scan a range of ports to find open ones
27
+ - 🖥️ **Cross-platform** – Windows, Linux, macOS (x64 & ARM64)
28
+ - 🎨 **Colored Output** – Beautiful terminal output with status indicators
29
+ - 🚀 **Fast** – Concurrent scanning for quick results
30
+ - 💪 **Force Kill** – Force kill processes when graceful termination fails
31
+
32
+ ---
33
+
34
+ ## 🚀 Quick Install
35
+
36
+ ### Using pip / pipx
37
+
38
+ ```bash
39
+ # Install using pip
40
+ pip install checkport
41
+
42
+ # Install using pipx (recommended for CLI tools)
43
+ pipx install checkport
@@ -0,0 +1,66 @@
1
+ Metadata-Version: 2.4
2
+ Name: checkport
3
+ Version: 2.0.0
4
+ Summary: Port management tool for checking and killing processes on specific ports
5
+ Home-page: https://github.com/watcher1337/checkport
6
+ Author: watcher1337
7
+ Author-email: watcher1337 <watcher1337@example.com>
8
+ License: MIT
9
+ Classifier: Programming Language :: Python :: 3
10
+ Classifier: Programming Language :: Python :: 3.8
11
+ Classifier: Programming Language :: Python :: 3.9
12
+ Classifier: Programming Language :: Python :: 3.10
13
+ Classifier: Programming Language :: Python :: 3.11
14
+ Classifier: Programming Language :: Python :: 3.12
15
+ Classifier: Programming Language :: Python :: 3.13
16
+ Classifier: License :: OSI Approved :: MIT License
17
+ Classifier: Operating System :: OS Independent
18
+ Requires-Python: >=3.8
19
+ Description-Content-Type: text/markdown
20
+ Dynamic: author
21
+ Dynamic: home-page
22
+ Dynamic: requires-python
23
+
24
+ # checkport
25
+
26
+ [![GitHub release](https://img.shields.io/github/release/watcher1337/checkport.svg)](https://github.com/watcher1337/checkport/releases/latest)
27
+ [![Python 3.8+](https://img.shields.io/badge/python-3.8+-blue.svg)](https://www.python.org/)
28
+ [![Platform](https://img.shields.io/badge/platform-Windows%20%7C%20Linux%20%7C%20macOS-lightgrey.svg)](https://github.com/watcher1337/checkport/releases)
29
+
30
+ **A powerful port management tool for checking and killing processes running on specific ports. Cross-platform and easy to use.**
31
+
32
+ ---
33
+
34
+ ## 📋 Table of Contents
35
+
36
+ - [Features](#-features)
37
+ - [Quick Install](#-quick-install)
38
+ - [Usage](#-usage)
39
+ - [Examples](#-examples)
40
+ - [Building from Source](#-building-from-source)
41
+
42
+ ---
43
+
44
+ ## ✨ Features
45
+
46
+ - 🔍 **Port Checking** – Check if a port is in use and get process information
47
+ - 🔪 **Process Killing** – Kill processes running on specific ports with graceful termination
48
+ - 📋 **List Ports** – Display all listening ports with process details
49
+ - 🔎 **Port Scanning** – Scan a range of ports to find open ones
50
+ - 🖥️ **Cross-platform** – Windows, Linux, macOS (x64 & ARM64)
51
+ - 🎨 **Colored Output** – Beautiful terminal output with status indicators
52
+ - 🚀 **Fast** – Concurrent scanning for quick results
53
+ - 💪 **Force Kill** – Force kill processes when graceful termination fails
54
+
55
+ ---
56
+
57
+ ## 🚀 Quick Install
58
+
59
+ ### Using pip / pipx
60
+
61
+ ```bash
62
+ # Install using pip
63
+ pip install checkport
64
+
65
+ # Install using pipx (recommended for CLI tools)
66
+ pipx install checkport
@@ -0,0 +1,9 @@
1
+ README.md
2
+ checkport.py
3
+ pyproject.toml
4
+ setup.py
5
+ checkport.egg-info/PKG-INFO
6
+ checkport.egg-info/SOURCES.txt
7
+ checkport.egg-info/dependency_links.txt
8
+ checkport.egg-info/entry_points.txt
9
+ checkport.egg-info/top_level.txt
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ checkport = checkport:main
@@ -0,0 +1 @@
1
+ checkport
@@ -0,0 +1,608 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ PORT MANAGER v2.0
4
+ A tool to check and kill processes running on specific ports
5
+ Enhanced with fixtime-style architecture and features
6
+ """
7
+
8
+ import os
9
+ import sys
10
+ import platform
11
+ import subprocess
12
+ import argparse
13
+ import socket
14
+ import threading
15
+ import time
16
+ import re
17
+ import warnings
18
+ from typing import Optional, Tuple, List, Dict, Any
19
+ from datetime import datetime
20
+ import concurrent.futures
21
+
22
+ # ============================================================
23
+ # Terminal Colors
24
+ # ============================================================
25
+
26
+ class Color:
27
+ RESET = "\033[0m"
28
+ BOLD = "\033[1m"
29
+ DIM = "\033[2m"
30
+ BLACK = "\033[30m"
31
+ RED = "\033[91m"
32
+ GREEN = "\033[92m"
33
+ YELLOW = "\033[93m"
34
+ BLUE = "\033[94m"
35
+ MAGENTA = "\033[95m"
36
+ CYAN = "\033[96m"
37
+ WHITE = "\033[97m"
38
+
39
+ def supports_color():
40
+ """Return True if terminal likely supports ANSI colors."""
41
+ if os.getenv("NO_COLOR") is not None:
42
+ return False
43
+ if not hasattr(sys.stdout, "isatty"):
44
+ return False
45
+ if not sys.stdout.isatty():
46
+ return False
47
+ if platform.system().lower() == "windows":
48
+ return (os.getenv("ANSICON") is not None or
49
+ os.getenv("WT_SESSION") is not None or
50
+ os.getenv("TERM_PROGRAM") == "vscode" or
51
+ os.getenv("TERM") is not None)
52
+ return True
53
+
54
+ USE_COLOR = supports_color()
55
+
56
+ def color(text, code):
57
+ if not USE_COLOR:
58
+ return str(text)
59
+ return f"{code}{text}{Color.RESET}"
60
+
61
+ def bold(text): return color(text, Color.BOLD)
62
+ def red(text): return color(text, Color.RED)
63
+ def green(text): return color(text, Color.GREEN)
64
+ def yellow(text): return color(text, Color.YELLOW)
65
+ def blue(text): return color(text, Color.BLUE)
66
+ def cyan(text): return color(text, Color.CYAN)
67
+ def magenta(text): return color(text, Color.MAGENTA)
68
+ def dim(text): return color(text, Color.DIM)
69
+
70
+ def colorize_message(message):
71
+ message = str(message)
72
+ prefixes = (("[✓]", Color.GREEN), ("[✗]", Color.RED), ("[!]", Color.YELLOW))
73
+ for prefix, prefix_color in prefixes:
74
+ if message.startswith(prefix):
75
+ colored_prefix = color(prefix, prefix_color)
76
+ return f"{colored_prefix}{message[len(prefix):]}"
77
+ return message
78
+
79
+ def cprint(*values, **kwargs):
80
+ """Replacement for print() that colors known status prefixes."""
81
+ if not values:
82
+ print(**kwargs)
83
+ return
84
+ values = list(values)
85
+ if isinstance(values[0], str):
86
+ values[0] = colorize_message(values[0])
87
+ print(*values, **kwargs)
88
+
89
+ def print_value(label, value, indent=4):
90
+ """Print a label/value pair with cyan label and bold value."""
91
+ spaces = " " * indent
92
+ print(f"{spaces}{cyan(f'{label:<16}')}{bold(value)}")
93
+
94
+ def print_separator(char="=", length=60):
95
+ print(dim(char * length))
96
+
97
+ # ============================================================
98
+ # Platform detection
99
+ # ============================================================
100
+
101
+ def detect_os():
102
+ """Detect OS and architecture."""
103
+ system = platform.system().lower()
104
+ machine = platform.machine().lower()
105
+
106
+ if system == "windows":
107
+ return "windows"
108
+ elif system == "darwin":
109
+ if machine in ["arm64", "aarch64"]:
110
+ return "darwin_arm"
111
+ return "darwin"
112
+ else:
113
+ if machine in ["arm64", "aarch64", "armv7l", "armv8l"]:
114
+ return "linux_arm"
115
+ return "linux"
116
+
117
+ def is_admin():
118
+ """Return True if running with admin/root privileges."""
119
+ if OS_NAME == "windows":
120
+ try:
121
+ import ctypes
122
+ return ctypes.windll.shell32.IsUserAnAdmin() != 0
123
+ except Exception:
124
+ return False
125
+ else:
126
+ try:
127
+ return os.geteuid() == 0
128
+ except AttributeError:
129
+ return os.system("sudo -n true") == 0
130
+
131
+ OS_NAME = detect_os()
132
+ IS_ADMIN = is_admin()
133
+
134
+ # ============================================================
135
+ # Configuration
136
+ # ============================================================
137
+
138
+ MAX_WORKERS = 4
139
+ print_lock = threading.Lock()
140
+
141
+ # ============================================================
142
+ # Arguments
143
+ # ============================================================
144
+
145
+ parser = argparse.ArgumentParser(
146
+ description="Port management tool for checking and killing processes on specific ports",
147
+ formatter_class=argparse.RawDescriptionHelpFormatter,
148
+ usage="checkport [OPTIONS]",
149
+ add_help=False,
150
+ epilog="""
151
+ Examples:
152
+ checkport -c 8080 # Check if port 8080 is in use
153
+ checkport -k 8080 # Kill process on port 8080
154
+ checkport -c 80 -v # Check port 80 with verbose output
155
+ checkport -k 443 --force # Force kill process on port 443
156
+ checkport --list # List all listening ports
157
+ checkport --scan 8000-8100 # Scan port range
158
+ """,
159
+ )
160
+
161
+ parser.add_argument("-h", action="help", default=argparse.SUPPRESS,
162
+ help="show this help message")
163
+ parser.add_argument("-c", "--check", type=int, metavar="PORT",
164
+ help="Check if a port is open and show process info")
165
+ parser.add_argument("-k", "--kill", type=int, metavar="PORT",
166
+ help="Kill the process running on the specified port")
167
+ parser.add_argument("-v", "--verbose", action="store_true",
168
+ help="Enable verbose output")
169
+ parser.add_argument("--force", action="store_true",
170
+ help="Force kill process (SIGKILL immediately)")
171
+ parser.add_argument("--list", action="store_true",
172
+ help="List all listening ports")
173
+ parser.add_argument("--scan", type=str, metavar="RANGE",
174
+ help="Scan port range (e.g., 8000-8100)")
175
+ parser.add_argument("--no-color", action="store_true",
176
+ help="Disable colored output")
177
+
178
+ args = parser.parse_args()
179
+
180
+ if args.no_color:
181
+ USE_COLOR = False
182
+
183
+ # ============================================================
184
+ # Logging
185
+ # ============================================================
186
+
187
+ def log(msg, force=False):
188
+ if args.verbose or force:
189
+ with print_lock:
190
+ cprint(msg)
191
+
192
+ # ============================================================
193
+ # Core Port Management
194
+ # ============================================================
195
+
196
+ class PortManager:
197
+ def __init__(self):
198
+ self.system = OS_NAME
199
+ self.is_admin = IS_ADMIN
200
+
201
+ def find_process_on_port(self, port: int) -> Optional[Tuple[str, str, str]]:
202
+ """
203
+ Find process using a specific port.
204
+ Returns (pid, command, user) if found, None otherwise.
205
+ """
206
+ log(f"[*] Looking for process on port {port}")
207
+
208
+ # Try lsof first (most reliable)
209
+ try:
210
+ result = subprocess.run(
211
+ ['lsof', '-i', f':{port}', '-t'],
212
+ capture_output=True,
213
+ text=True,
214
+ timeout=5
215
+ )
216
+ if result.stdout.strip():
217
+ pid = result.stdout.strip().split('\n')[0]
218
+ # Get process info
219
+ ps_result = subprocess.run(
220
+ ['ps', '-p', pid, '-o', 'comm=', '-o', 'user='],
221
+ capture_output=True,
222
+ text=True,
223
+ timeout=5
224
+ )
225
+ if ps_result.stdout.strip():
226
+ parts = ps_result.stdout.strip().split()
227
+ if len(parts) >= 2:
228
+ command = parts[0]
229
+ user = parts[1]
230
+ log(f"[+] Found process {pid} ({command}) on port {port}")
231
+ return (pid, command, user)
232
+ except (subprocess.CalledProcessError, FileNotFoundError, subprocess.TimeoutExpired):
233
+ pass
234
+
235
+ # Fallback to netstat/ss
236
+ try:
237
+ if self.system == 'linux' or self.system == 'linux_arm':
238
+ cmd = ['ss', '-tlnp', f'sport = :{port}']
239
+ elif self.system.startswith('darwin'):
240
+ cmd = ['netstat', '-anv', '-p', 'tcp']
241
+ else: # windows
242
+ cmd = ['netstat', '-ano', '-p', 'TCP']
243
+
244
+ result = subprocess.run(cmd, capture_output=True, text=True, timeout=5)
245
+
246
+ if self.system.startswith('linux'):
247
+ # Parse ss output
248
+ for line in result.stdout.split('\n'):
249
+ if f':{port}' in line and 'LISTEN' in line:
250
+ match = re.search(r'pid=(\d+)', line)
251
+ if match:
252
+ pid = match.group(1)
253
+ ps_result = subprocess.run(
254
+ ['ps', '-p', pid, '-o', 'comm=', '-o', 'user='],
255
+ capture_output=True,
256
+ text=True,
257
+ timeout=5
258
+ )
259
+ if ps_result.stdout.strip():
260
+ parts = ps_result.stdout.strip().split()
261
+ if len(parts) >= 2:
262
+ command = parts[0]
263
+ user = parts[1]
264
+ log(f"[+] Found process {pid} ({command}) on port {port}")
265
+ return (pid, command, user)
266
+ elif self.system.startswith('darwin'):
267
+ # Parse netstat output (macOS)
268
+ for line in result.stdout.split('\n'):
269
+ if f'.{port}' in line and 'LISTEN' in line:
270
+ parts = line.split()
271
+ if len(parts) >= 9:
272
+ pid = parts[8] if parts[8].isdigit() else None
273
+ if pid:
274
+ ps_result = subprocess.run(
275
+ ['ps', '-p', pid, '-o', 'comm=', '-o', 'user='],
276
+ capture_output=True,
277
+ text=True,
278
+ timeout=5
279
+ )
280
+ if ps_result.stdout.strip():
281
+ parts = ps_result.stdout.strip().split()
282
+ if len(parts) >= 2:
283
+ command = parts[0]
284
+ user = parts[1]
285
+ log(f"[+] Found process {pid} ({command}) on port {port}")
286
+ return (pid, command, user)
287
+ else: # Windows
288
+ for line in result.stdout.split('\n'):
289
+ if f':{port}' in line and 'LISTENING' in line:
290
+ parts = line.split()
291
+ if len(parts) >= 5:
292
+ pid = parts[4] if parts[4].isdigit() else None
293
+ if pid:
294
+ try:
295
+ ps_result = subprocess.run(
296
+ ['tasklist', '/FI', f'PID eq {pid}'],
297
+ capture_output=True,
298
+ text=True,
299
+ timeout=5
300
+ )
301
+ if ps_result.stdout:
302
+ lines = ps_result.stdout.split('\n')
303
+ if len(lines) > 3:
304
+ proc_info = lines[3].split()
305
+ if len(proc_info) >= 2:
306
+ command = proc_info[0]
307
+ user = "N/A"
308
+ log(f"[+] Found process {pid} ({command}) on port {port}")
309
+ return (pid, command, user)
310
+ except Exception:
311
+ pass
312
+ except (subprocess.CalledProcessError, FileNotFoundError, subprocess.TimeoutExpired):
313
+ pass
314
+
315
+ # Last fallback: try fuser
316
+ try:
317
+ result = subprocess.run(
318
+ ['fuser', f'{port}/tcp'],
319
+ capture_output=True,
320
+ text=True,
321
+ timeout=5
322
+ )
323
+ if result.stdout.strip():
324
+ pid = result.stdout.strip().split()[0]
325
+ ps_result = subprocess.run(
326
+ ['ps', '-p', pid, '-o', 'comm=', '-o', 'user='],
327
+ capture_output=True,
328
+ text=True,
329
+ timeout=5
330
+ )
331
+ if ps_result.stdout.strip():
332
+ parts = ps_result.stdout.strip().split()
333
+ if len(parts) >= 2:
334
+ command = parts[0]
335
+ user = parts[1]
336
+ log(f"[+] Found process {pid} ({command}) on port {port}")
337
+ return (pid, command, user)
338
+ except (subprocess.CalledProcessError, FileNotFoundError, subprocess.TimeoutExpired):
339
+ pass
340
+
341
+ log(f"[-] No process found on port {port}")
342
+ return None
343
+
344
+ def check_port(self, port: int) -> bool:
345
+ """
346
+ Check if port is in use and display process info.
347
+ Returns True if port is in use, False otherwise.
348
+ """
349
+ log(f"[*] Checking port {port}")
350
+
351
+ result = self.find_process_on_port(port)
352
+
353
+ print()
354
+ print_separator()
355
+ if result:
356
+ pid, command, user = result
357
+ cprint(f"[✓] Port {port} is IN USE")
358
+ print_separator()
359
+ print_value("COMMAND", command)
360
+ print_value("PID", pid)
361
+ print_value("USER", user)
362
+ print_separator()
363
+
364
+ # Show detailed lsof output if available
365
+ if self.system.startswith('darwin') or self.system.startswith('linux'):
366
+ try:
367
+ lsof_result = subprocess.run(
368
+ ['lsof', '-i', f':{port}'],
369
+ capture_output=True,
370
+ text=True,
371
+ timeout=5
372
+ )
373
+ if lsof_result.stdout:
374
+ lines = lsof_result.stdout.split('\n')
375
+ if len(lines) > 1:
376
+ print("\nDetailed info:")
377
+ print(lines[0]) # Header
378
+ if len(lines) > 2:
379
+ print(lines[1]) # First data line
380
+ except (subprocess.CalledProcessError, FileNotFoundError, subprocess.TimeoutExpired):
381
+ pass
382
+ return True
383
+ else:
384
+ cprint(f"[✓] Port {port} is FREE")
385
+ print_separator()
386
+ return False
387
+
388
+ def kill_process_on_port(self, port: int) -> bool:
389
+ """
390
+ Kill process running on specified port.
391
+ Returns True if successful, False otherwise.
392
+ """
393
+ # Check if port is privileged
394
+ if port < 1024 and not self.is_admin:
395
+ cprint(f"[!] Port {port} is a privileged port (below 1024)")
396
+ cprint("[!] You may need to run with sudo for proper operation")
397
+
398
+ result = self.find_process_on_port(port)
399
+
400
+ if not result:
401
+ cprint(f"[✓] No process found on port {port}")
402
+ return False
403
+
404
+ pid, command, user = result
405
+ cprint(f"[*] Found process {pid} ({command}) on port {port}")
406
+
407
+ try:
408
+ if args.force:
409
+ # Force kill immediately
410
+ if self.system == "windows":
411
+ subprocess.run(['taskkill', '/F', '/PID', pid], check=True)
412
+ else:
413
+ os.kill(int(pid), 9) # SIGKILL
414
+ cprint(f"[✓] Successfully force killed process {pid} on port {port}")
415
+ return True
416
+
417
+ # Try gentle kill first (SIGTERM)
418
+ if self.system == "windows":
419
+ subprocess.run(['taskkill', '/PID', pid], check=True)
420
+ else:
421
+ os.kill(int(pid), 15) # SIGTERM
422
+
423
+ # Wait a moment and check if process is still running
424
+ time.sleep(0.5)
425
+
426
+ # Check if process still exists
427
+ if self.system == "windows":
428
+ try:
429
+ subprocess.run(['tasklist', '/FI', f'PID eq {pid}'],
430
+ capture_output=True, check=True)
431
+ except Exception:
432
+ cprint(f"[✓] Successfully killed process {pid} on port {port}")
433
+ return True
434
+ else:
435
+ try:
436
+ os.kill(int(pid), 0) # Check if process exists
437
+ # Process still exists, try SIGKILL
438
+ cprint("[!] Process didn't terminate gracefully, forcing kill...")
439
+ os.kill(int(pid), 9) # SIGKILL
440
+ cprint(f"[✓] Successfully killed process {pid} on port {port}")
441
+ return True
442
+ except OSError:
443
+ # Process is gone
444
+ cprint(f"[✓] Successfully killed process {pid} on port {port}")
445
+ return True
446
+
447
+ except PermissionError:
448
+ cprint("[✗] Permission denied. Try running with sudo")
449
+ return False
450
+ except ProcessLookupError:
451
+ cprint(f"[✓] Process {pid} was already terminated")
452
+ return True
453
+ except Exception as e:
454
+ cprint(f"[✗] Error killing process: {e}")
455
+ return False
456
+
457
+ def list_listening_ports(self) -> List[Dict[str, Any]]:
458
+ """List all listening ports with process info."""
459
+ ports = []
460
+
461
+ try:
462
+ if self.system.startswith('linux'):
463
+ cmd = ['ss', '-tlnp']
464
+ elif self.system.startswith('darwin'):
465
+ cmd = ['netstat', '-anv', '-p', 'tcp']
466
+ else: # windows
467
+ cmd = ['netstat', '-ano', '-p', 'TCP']
468
+
469
+ result = subprocess.run(cmd, capture_output=True, text=True, timeout=10)
470
+
471
+ for line in result.stdout.split('\n'):
472
+ if 'LISTEN' in line:
473
+ port_match = re.search(r':(\d+)\s', line)
474
+ if port_match:
475
+ port = int(port_match.group(1))
476
+ process_info = self.find_process_on_port(port)
477
+ ports.append({
478
+ 'port': port,
479
+ 'pid': process_info[0] if process_info else 'N/A',
480
+ 'command': process_info[1] if process_info else 'N/A',
481
+ 'user': process_info[2] if process_info else 'N/A'
482
+ })
483
+ except Exception as e:
484
+ log(f"[-] Error listing ports: {e}")
485
+
486
+ return ports
487
+
488
+ def scan_port_range(self, start: int, end: int) -> List[int]:
489
+ """Scan a range of ports and return open ones."""
490
+ open_ports = []
491
+
492
+ cprint(f"[*] Scanning ports {start}-{end}...")
493
+
494
+ def scan_single_port(port):
495
+ try:
496
+ sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
497
+ sock.settimeout(0.5)
498
+ result = sock.connect_ex(('127.0.0.1', port))
499
+ sock.close()
500
+ if result == 0:
501
+ return port
502
+ except Exception:
503
+ pass
504
+ return None
505
+
506
+ with concurrent.futures.ThreadPoolExecutor(max_workers=MAX_WORKERS) as executor:
507
+ futures = {executor.submit(scan_single_port, port): port
508
+ for port in range(start, end + 1)}
509
+
510
+ for future in concurrent.futures.as_completed(futures):
511
+ result = future.result()
512
+ if result:
513
+ open_ports.append(result)
514
+ process_info = self.find_process_on_port(result)
515
+ if process_info:
516
+ cprint(f"[+] Port {result} is open (PID: {process_info[0]}, {process_info[1]})")
517
+ else:
518
+ cprint(f"[+] Port {result} is open")
519
+
520
+ return open_ports
521
+
522
+ # ============================================================
523
+ # Main
524
+ # ============================================================
525
+
526
+ def main():
527
+ """Main entry point for the checkport tool."""
528
+ # Display system info in verbose mode
529
+ if args.verbose:
530
+ cprint(f"[*] OS: {OS_NAME}")
531
+ cprint(f"[*] Architecture: {platform.machine()}")
532
+ cprint(f"[*] Admin privileges: {IS_ADMIN}")
533
+
534
+ pm = PortManager()
535
+
536
+ # Handle list operation
537
+ if args.list:
538
+ cprint("\n[🔄] Listing all listening ports...")
539
+ print_separator()
540
+ ports = pm.list_listening_ports()
541
+ if ports:
542
+ cprint(f"[+] Found {len(ports)} listening ports:")
543
+ print_separator()
544
+ print(f"{'PORT':<8} {'PID':<8} {'USER':<12} COMMAND")
545
+ print_separator()
546
+ for p in sorted(ports, key=lambda x: x['port']):
547
+ print(f"{p['port']:<8} {p['pid']:<8} {p['user']:<12} {p['command']}")
548
+ print_separator()
549
+ else:
550
+ cprint("[!] No listening ports found")
551
+ return
552
+
553
+ # Handle scan operation
554
+ if args.scan:
555
+ try:
556
+ if '-' in args.scan:
557
+ start, end = map(int, args.scan.split('-'))
558
+ if start > end:
559
+ start, end = end, start
560
+ if start < 1 or end > 65535:
561
+ cprint("[✗] Port range must be between 1 and 65535")
562
+ sys.exit(1)
563
+ open_ports = pm.scan_port_range(start, end)
564
+ if open_ports:
565
+ cprint(f"\n[+] Found {len(open_ports)} open ports: {open_ports}")
566
+ else:
567
+ cprint("\n[!] No open ports found in range")
568
+ else:
569
+ cprint("[✗] Invalid port range format. Use start-end (e.g., 8000-8100)")
570
+ sys.exit(1)
571
+ except ValueError:
572
+ cprint("[✗] Invalid port range. Use numeric values (e.g., 8000-8100)")
573
+ sys.exit(1)
574
+ return
575
+
576
+ # Handle check operation
577
+ if args.check:
578
+ port = args.check
579
+ if not (1 <= port <= 65535):
580
+ cprint(f"[✗] Invalid port number: {port}. Must be between 1 and 65535")
581
+ sys.exit(1)
582
+ in_use = pm.check_port(port)
583
+ sys.exit(0 if in_use else 1)
584
+
585
+ # Handle kill operation
586
+ if args.kill:
587
+ port = args.kill
588
+ if not (1 <= port <= 65535):
589
+ cprint(f"[✗] Invalid port number: {port}. Must be between 1 and 65535")
590
+ sys.exit(1)
591
+ success = pm.kill_process_on_port(port)
592
+ sys.exit(0 if success else 1)
593
+
594
+ # No arguments provided
595
+ parser.print_help()
596
+
597
+ if __name__ == "__main__":
598
+ try:
599
+ main()
600
+ except KeyboardInterrupt:
601
+ cprint("\n[!] Operation cancelled by user")
602
+ sys.exit(1)
603
+ except Exception as e:
604
+ cprint(f"\n[✗] Unexpected error: {e}")
605
+ if args.verbose:
606
+ import traceback
607
+ traceback.print_exc()
608
+ sys.exit(1)
@@ -0,0 +1,32 @@
1
+ [project]
2
+ name = "checkport"
3
+ version = "2.0.0"
4
+ description = "Port management tool for checking and killing processes on specific ports"
5
+ readme = "README.md"
6
+ requires-python = ">=3.8"
7
+ authors = [
8
+ {name = "watcher1337", email = "watcher1337@example.com"}
9
+ ]
10
+ license = {text = "MIT"}
11
+ classifiers = [
12
+ "Programming Language :: Python :: 3",
13
+ "Programming Language :: Python :: 3.8",
14
+ "Programming Language :: Python :: 3.9",
15
+ "Programming Language :: Python :: 3.10",
16
+ "Programming Language :: Python :: 3.11",
17
+ "Programming Language :: Python :: 3.12",
18
+ "Programming Language :: Python :: 3.13",
19
+ "License :: OSI Approved :: MIT License",
20
+ "Operating System :: OS Independent",
21
+ ]
22
+ dependencies = []
23
+
24
+ [project.scripts]
25
+ checkport = "checkport:main"
26
+
27
+ [build-system]
28
+ requires = ["setuptools>=61.0"]
29
+ build-backend = "setuptools.build_meta"
30
+
31
+ [tool.setuptools]
32
+ py-modules = ["checkport"]
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,17 @@
1
+ from setuptools import setup
2
+
3
+ setup(
4
+ name="checkport",
5
+ version="2.0.0",
6
+ py_modules=["checkport"],
7
+ install_requires=[],
8
+ entry_points={
9
+ "console_scripts": [
10
+ "checkport=checkport:main",
11
+ ],
12
+ },
13
+ author="watcher1337",
14
+ description="Port management tool for checking and killing processes on specific ports",
15
+ url="https://github.com/watcher1337/checkport",
16
+ python_requires=">=3.8",
17
+ )