diff --git a/submissions/SysMonit/Readme.md b/submissions/SysMonit/Readme.md new file mode 100644 index 00000000..8282e4aa --- /dev/null +++ b/submissions/SysMonit/Readme.md @@ -0,0 +1,125 @@ +# System Analyzer + +A comprehensive cross-platform system analysis tool with CLI/TUI interface for Windows, Linux, and macOS. + +## šŸš€ Quick Start + +### Option 1: Automatic Installation +```bash +python install.py +``` + +### Option 2: Manual Installation +```bash +pip install psutil rich +python main.py +``` + +## šŸ“‹ Features + +### šŸ—„ļø Storage Analyzer +- Disk usage analysis with visual indicators +- Large file finder with customizable size filters +- Directory size analysis and comparison +- Cross-platform drive/partition detection + +### 🌐 Network Analyzer +- Network interface information and status +- Port scanner with common service detection +- Ping test with detailed response times +- Active network connections monitoring + +### šŸ“Š Task Manager +- Process list with CPU/memory usage sorting +- Real-time system resource monitoring +- Process search and termination +- Live process monitoring with auto-refresh + +### šŸ–„ļø System Monitor +- Complete system information display +- CPU details with per-core usage +- Memory and swap usage monitoring +- Disk I/O statistics +- Temperature and fan sensor readings +- Real-time system performance dashboard + +## šŸ’» System Requirements + +- Python 3.6 or higher +- Works on Windows, Linux, and macOS +- Administrator/root privileges recommended for full functionality + +## šŸ”§ Installation Files + +- `main.py` - Main application entry point +- `storage_analyzer.py` - Storage analysis module +- `network_analyzer.py` - Network analysis module +- `task_manager.py` - Process and task management +- `system_monitor.py` - System monitoring and information +- `install.py` - Automated installation script +- `requirements.txt` - Python dependencies + +## šŸŽÆ Usage Examples + +### Launch the application +```bash +python main.py +``` + +## šŸ›”ļø Security Features + +- Safe process termination with confirmation +- Non-destructive analysis operations +- Permission handling for restricted areas +- Error handling for access denied scenarios + +## šŸ” Key Capabilities + +- **Storage Analysis**: Find space-consuming files and directories +- **Network Diagnostics**: Test connectivity and scan for open ports +- **Performance Monitoring**: Track CPU, memory, and disk usage +- **Process Management**: View and manage running applications + +## šŸ“ˆ Visual Interface + +- Color-coded status indicators (šŸŸ¢šŸŸ”šŸ”“) +- Rich text formatting and tables +- Real-time updating displays +- Intuitive menu navigation +- Progress bars for long operations + +## šŸ› Troubleshooting + +### Common Issues + +**Permission Errors**: Run as administrator/root for full access to system information + +**Missing Dependencies**: +```bash +pip install --user psutil rich +``` + +**Python Not Found**: Ensure Python 3.6+ is installed and in PATH + +### Platform-Specific Notes + +- **Windows**: Some features require administrator privileges +- **Linux**: Temperature sensors may require root access +- **macOS**: Some system information requires elevated permissions + +## šŸ“š Dependencies + +- `psutil` - System and process utilities +- `rich` - Rich text and beautiful formatting + +## šŸŽØ Interface Highlights + +- Clean, modern terminal interface +- Beginner-friendly navigation +- Comprehensive system analysis +- Cross-platform compatibility +- Real-time monitoring capabilities + +--- + +**Note**: For demo please look on this video: https://drive.google.com/file/d/1BuWdgPXkkFybzn3-TuEyxlZiC1it8Ka2/view?usp=sharing \ No newline at end of file diff --git a/submissions/SysMonit/install.py b/submissions/SysMonit/install.py new file mode 100644 index 00000000..c7e7f6d3 --- /dev/null +++ b/submissions/SysMonit/install.py @@ -0,0 +1,91 @@ + +import subprocess +import sys +import os +import platform + +def run_command(cmd, check=True): + try: + result = subprocess.run(cmd, shell=True, check=check, capture_output=True, text=True) + return result.returncode == 0 + except subprocess.CalledProcessError: + return False + +def install_dependencies(): + print("šŸ”§ Installing System Analyzer...") + print("šŸ“¦ Installing Python dependencies...") + + pip_commands = ['pip3 install -r requirements.txt', 'pip install -r requirements.txt'] + + for cmd in pip_commands: + if run_command(cmd, check=False): + print("āœ… Dependencies installed successfully!") + return True + + print("āŒ Failed to install dependencies") + print("Please manually run: pip install psutil rich") + return False + +def create_launcher(): + system = platform.system() + + if system == "Windows": + launcher_content = """@echo off +python main.py +pause +""" + with open("system_analyzer.bat", "w") as f: + f.write(launcher_content) + print("āœ… Created system_analyzer.bat launcher") + + else: + launcher_content = """#!/bin/bash +python3 main.py +""" + with open("system_analyzer.sh", "w") as f: + f.write(launcher_content) + + os.chmod("system_analyzer.sh", 0o755) + print("āœ… Created system_analyzer.sh launcher") + +def main(): + print("=" * 50) + print("šŸ–„ļø SYSTEM ANALYZER INSTALLER") + print("=" * 50) + + if not os.path.exists("main.py"): + print("āŒ main.py not found!") + print("Please make sure all files are in the same directory") + return + + if not os.path.exists("requirements.txt"): + print("āŒ requirements.txt not found!") + return + + if install_dependencies(): + create_launcher() + + print("\nšŸŽ‰ Installation complete!") + print("\nšŸ“‹ To run the System Analyzer:") + + if platform.system() == "Windows": + print(" • Double-click system_analyzer.bat") + print(" • Or run: python main.py") + else: + print(" • Run: ./system_analyzer.sh") + print(" • Or run: python3 main.py") + + print("\nšŸ”§ Features included:") + print(" • Storage Analyzer (disk usage, large files)") + print(" • Network Analyzer (ports, ping, connections)") + print(" • Task Manager (processes, resource usage)") + print(" • System Monitor (CPU, memory, sensors)") + + print("\n✨ Enjoy analyzing your system!") + else: + print("\nāŒ Installation failed") + print("Please install dependencies manually:") + print(" pip install psutil rich") + +if __name__ == "__main__": + main() \ No newline at end of file diff --git a/submissions/SysMonit/main.py b/submissions/SysMonit/main.py new file mode 100644 index 00000000..0cfbdea3 --- /dev/null +++ b/submissions/SysMonit/main.py @@ -0,0 +1,112 @@ +#!/usr/bin/env python3 + +import sys +import os +from rich.console import Console +from rich.panel import Panel +from rich.text import Text +from rich.align import Align +from rich.prompt import Prompt +import time + +try: + from storage_analyzer import StorageAnalyzer + from network_analyzer import NetworkAnalyzer + from task_manager import TaskManager + from system_monitor import SystemMonitor +except ImportError as e: + print(f"Missing module: {e}") + print("Please run: pip install -r requirements.txt") + sys.exit(1) + +class SystemAnalyzer: + def __init__(self): + self.console = Console() + self.storage = StorageAnalyzer() + self.network = NetworkAnalyzer() + self.tasks = TaskManager() + self.monitor = SystemMonitor() + + def show_banner(self): + banner = Text("SYSTEM ANALYZER", style="bold cyan") + subtitle = Text("Cross-platform system analysis tool", style="dim") + + panel = Panel( + Align.center(banner + "\n" + subtitle), + border_style="cyan", + padding=(1, 2) + ) + self.console.print(panel) + self.console.print() + + def show_main_menu(self): + menu_text = """ +[bold green]1.[/bold green] Storage Analyzer +[bold green]2.[/bold green] Network Analyzer +[bold green]3.[/bold green] Task Manager +[bold green]4.[/bold green] System Monitor +[bold green]5.[/bold green] Run All Diagnostics +[bold red]0.[/bold red] Exit + """ + + panel = Panel( + menu_text.strip(), + title="[bold]Main Menu[/bold]", + border_style="green" + ) + self.console.print(panel) + + def run_all_diagnostics(self): + self.console.print("\n[bold yellow]Running comprehensive system analysis...[/bold yellow]") + + with self.console.status("[bold green]Analyzing storage..."): + time.sleep(1) + self.storage.show_disk_usage() + + with self.console.status("[bold green]Checking network..."): + time.sleep(1) + self.network.show_network_info() + + with self.console.status("[bold green]Getting system info..."): + time.sleep(1) + self.monitor.show_system_info() + + self.console.print("\n[bold green]āœ“ Diagnostic complete![/bold green]") + input("\nPress Enter to continue...") + + def run(self): + while True: + self.console.clear() + self.show_banner() + self.show_main_menu() + + choice = Prompt.ask( + "\n[bold]Select option[/bold]", + choices=["0", "1", "2", "3", "4", "5"], + default="0" + ) + + if choice == "0": + self.console.print("\n[bold green]Goodbye![/bold green]") + break + elif choice == "1": + self.storage.run() + elif choice == "2": + self.network.run() + elif choice == "3": + self.tasks.run() + elif choice == "4": + self.monitor.run() + elif choice == "5": + self.run_all_diagnostics() + +if __name__ == "__main__": + try: + analyzer = SystemAnalyzer() + analyzer.run() + except KeyboardInterrupt: + print("\n\nExiting...") + sys.exit(0) + except Exception as e: + print(f"Error: {e}") + sys.exit(1) \ No newline at end of file diff --git a/submissions/SysMonit/network_analyzer.py b/submissions/SysMonit/network_analyzer.py new file mode 100644 index 00000000..dd0276f6 --- /dev/null +++ b/submissions/SysMonit/network_analyzer.py @@ -0,0 +1,281 @@ +import socket +import subprocess +import platform +import psutil +import time +from rich.console import Console +from rich.table import Table +from rich.panel import Panel +from rich.prompt import Prompt +from rich.progress import Progress +import threading + +class NetworkAnalyzer: + def __init__(self): + self.console = Console() + self.system = platform.system() + + def get_network_interfaces(self): + interfaces = [] + net_if_addrs = psutil.net_if_addrs() + net_if_stats = psutil.net_if_stats() + + for interface, addresses in net_if_addrs.items(): + stats = net_if_stats.get(interface) + interface_info = { + 'name': interface, + 'is_up': stats.isup if stats else False, + 'addresses': [] + } + + for addr in addresses: + if addr.family == socket.AF_INET: + interface_info['addresses'].append(f"IPv4: {addr.address}") + elif addr.family == socket.AF_INET6: + interface_info['addresses'].append(f"IPv6: {addr.address}") + elif hasattr(socket, 'AF_PACKET') and addr.family == socket.AF_PACKET: + interface_info['addresses'].append(f"MAC: {addr.address}") + elif self.system == "Windows" and addr.family == -1: + interface_info['addresses'].append(f"MAC: {addr.address}") + + interfaces.append(interface_info) + + return interfaces + + def show_network_info(self): + self.console.print("\n[bold cyan]Network Interfaces[/bold cyan]") + + interfaces = self.get_network_interfaces() + + table = Table(show_header=True, header_style="bold magenta") + table.add_column("Interface", style="cyan") + table.add_column("Status", justify="center") + table.add_column("Addresses", style="dim") + + for interface in interfaces: + status = "🟢 UP" if interface['is_up'] else "šŸ”“ DOWN" + addresses = "\n".join(interface['addresses']) if interface['addresses'] else "No addresses" + + table.add_row( + interface['name'], + status, + addresses + ) + + self.console.print(table) + + def scan_ports(self, host, start_port=1, end_port=1000): + open_ports = [] + + def scan_port(port): + try: + sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + sock.settimeout(0.5) + result = sock.connect_ex((host, port)) + if result == 0: + open_ports.append(port) + sock.close() + except: + pass + + threads = [] + for port in range(start_port, end_port + 1): + thread = threading.Thread(target=scan_port, args=(port,)) + threads.append(thread) + thread.start() + + if len(threads) > 50: + for t in threads: + t.join() + threads = [] + + for t in threads: + t.join() + + return sorted(open_ports) + + def show_port_scan(self): + host = Prompt.ask("\n[bold]Enter host to scan[/bold]", default="127.0.0.1") + start_port = Prompt.ask("[bold]Start port[/bold]", default="1") + end_port = Prompt.ask("[bold]End port[/bold]", default="1000") + + try: + start_port = int(start_port) + end_port = int(end_port) + except ValueError: + self.console.print("[red]Invalid port numbers![/red]") + return + + self.console.print(f"\n[bold yellow]Scanning {host} ports {start_port}-{end_port}...[/bold yellow]") + + with self.console.status("[bold green]Scanning ports..."): + open_ports = self.scan_ports(host, start_port, end_port) + + if not open_ports: + self.console.print("[green]No open ports found[/green]") + return + + table = Table(show_header=True, header_style="bold magenta") + table.add_column("Port", justify="center", style="cyan") + table.add_column("Status", justify="center") + table.add_column("Service", style="dim") + + common_ports = { + 21: "FTP", 22: "SSH", 23: "Telnet", 25: "SMTP", 53: "DNS", + 80: "HTTP", 110: "POP3", 143: "IMAP", 443: "HTTPS", 993: "IMAPS", + 995: "POP3S", 3389: "RDP", 5432: "PostgreSQL", 3306: "MySQL" + } + + for port in open_ports: + service = common_ports.get(port, "Unknown") + table.add_row(str(port), "🟢 OPEN", service) + + panel = Panel(table, title=f"[bold]Open Ports on {host}[/bold]", border_style="green") + self.console.print(panel) + + def ping_host(self, host, count=4): + results = [] + + if self.system == "Windows": + cmd = ["ping", "-n", str(count), host] + else: + cmd = ["ping", "-c", str(count), host] + + try: + process = subprocess.Popen( + cmd, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + text=True + ) + + stdout, stderr = process.communicate() + + if process.returncode == 0: + lines = stdout.split('\n') + for line in lines: + if 'time=' in line.lower() or 'zeit=' in line.lower(): + results.append(line.strip()) + return True, results + else: + return False, [stderr.strip()] + + except Exception as e: + return False, [str(e)] + + def show_ping_test(self): + host = Prompt.ask("\n[bold]Enter host to ping[/bold]", default="google.com") + count = Prompt.ask("[bold]Number of pings[/bold]", default="4") + + try: + count = int(count) + except ValueError: + count = 4 + + self.console.print(f"\n[bold yellow]Pinging {host}...[/bold yellow]") + + success, results = self.ping_host(host, count) + + if success: + self.console.print(f"[green]āœ“ {host} is reachable[/green]") + for result in results: + self.console.print(f" {result}") + else: + self.console.print(f"[red]āœ— {host} is unreachable[/red]") + for result in results: + self.console.print(f" {result}") + + def get_active_connections(self): + connections = [] + try: + for conn in psutil.net_connections(kind='inet'): + if conn.status == 'ESTABLISHED': + local_addr = f"{conn.laddr.ip}:{conn.laddr.port}" + remote_addr = f"{conn.raddr.ip}:{conn.raddr.port}" if conn.raddr else "N/A" + + try: + process = psutil.Process(conn.pid) if conn.pid else None + process_name = process.name() if process else "Unknown" + except: + process_name = "Unknown" + + connections.append({ + 'local': local_addr, + 'remote': remote_addr, + 'status': conn.status, + 'process': process_name, + 'pid': conn.pid or 0 + }) + except: + pass + + return connections + + def show_active_connections(self): + self.console.print("\n[bold cyan]Active Network Connections[/bold cyan]") + + with self.console.status("[bold green]Getting connections..."): + connections = self.get_active_connections() + + if not connections: + self.console.print("[yellow]No active connections found[/yellow]") + return + + table = Table(show_header=True, header_style="bold magenta") + table.add_column("Local Address", style="cyan") + table.add_column("Remote Address", style="yellow") + table.add_column("Status", justify="center") + table.add_column("Process", style="dim") + table.add_column("PID", justify="right") + + for conn in connections[:20]: + table.add_row( + conn['local'], + conn['remote'], + "🟢 " + conn['status'], + conn['process'], + str(conn['pid']) + ) + + self.console.print(table) + + def show_network_menu(self): + menu_text = """ +[bold green]1.[/bold green] Network Interfaces +[bold green]2.[/bold green] Port Scanner +[bold green]3.[/bold green] Ping Test +[bold green]4.[/bold green] Active Connections +[bold red]0.[/bold red] Back to Main Menu + """ + + panel = Panel( + menu_text.strip(), + title="[bold]Network Analyzer[/bold]", + border_style="cyan" + ) + self.console.print(panel) + + def run(self): + while True: + self.console.clear() + self.show_network_menu() + + choice = Prompt.ask( + "\n[bold]Select option[/bold]", + choices=["0", "1", "2", "3", "4"], + default="0" + ) + + if choice == "0": + break + elif choice == "1": + self.show_network_info() + elif choice == "2": + self.show_port_scan() + elif choice == "3": + self.show_ping_test() + elif choice == "4": + self.show_active_connections() + + if choice != "0": + input("\nPress Enter to continue...") \ No newline at end of file diff --git a/submissions/SysMonit/requirements.txt b/submissions/SysMonit/requirements.txt new file mode 100644 index 00000000..c3169fdf --- /dev/null +++ b/submissions/SysMonit/requirements.txt @@ -0,0 +1,2 @@ +psutil>=5.9.0 +rich>=13.0.0 \ No newline at end of file diff --git a/submissions/SysMonit/storage_analyzer.py b/submissions/SysMonit/storage_analyzer.py new file mode 100644 index 00000000..568b72b7 --- /dev/null +++ b/submissions/SysMonit/storage_analyzer.py @@ -0,0 +1,246 @@ +import os +import shutil +import platform +from pathlib import Path +from rich.console import Console +from rich.table import Table +from rich.panel import Panel +from rich.progress import Progress, BarColumn, TextColumn +from rich.prompt import Prompt +from rich.tree import Tree +import time + +class StorageAnalyzer: + def __init__(self): + self.console = Console() + self.system = platform.system() + + def format_bytes(self, bytes_val): + for unit in ['B', 'KB', 'MB', 'GB', 'TB']: + if bytes_val < 1024.0: + return f"{bytes_val:.1f} {unit}" + bytes_val /= 1024.0 + return f"{bytes_val:.1f} PB" + + def get_disk_usage(self): + disks = [] + if self.system == "Windows": + import string + for letter in string.ascii_uppercase: + drive = f"{letter}:\\" + if os.path.exists(drive): + try: + total, used, free = shutil.disk_usage(drive) + disks.append({ + 'path': drive, + 'total': total, + 'used': used, + 'free': free, + 'percent': (used / total) * 100 + }) + except: + pass + else: + for mount in ['/'] + ['/home', '/tmp', '/var']: + if os.path.exists(mount): + try: + total, used, free = shutil.disk_usage(mount) + disks.append({ + 'path': mount, + 'total': total, + 'used': used, + 'free': free, + 'percent': (used / total) * 100 + }) + except: + pass + return disks + + def show_disk_usage(self): + self.console.print("\n[bold cyan]Disk Usage Analysis[/bold cyan]") + + disks = self.get_disk_usage() + + table = Table(show_header=True, header_style="bold magenta") + table.add_column("Drive/Mount", style="cyan") + table.add_column("Total", justify="right") + table.add_column("Used", justify="right") + table.add_column("Free", justify="right") + table.add_column("Usage %", justify="right") + table.add_column("Status", justify="center") + + for disk in disks: + status = "šŸ”“" if disk['percent'] > 90 else "🟔" if disk['percent'] > 75 else "🟢" + table.add_row( + disk['path'], + self.format_bytes(disk['total']), + self.format_bytes(disk['used']), + self.format_bytes(disk['free']), + f"{disk['percent']:.1f}%", + status + ) + + self.console.print(table) + + def find_large_files(self, path, min_size_mb=100): + large_files = [] + min_size = min_size_mb * 1024 * 1024 + + try: + for root, dirs, files in os.walk(path): + for file in files: + try: + file_path = os.path.join(root, file) + size = os.path.getsize(file_path) + if size > min_size: + large_files.append({ + 'path': file_path, + 'size': size, + 'name': file + }) + except (OSError, PermissionError): + continue + + dirs[:] = [d for d in dirs if not d.startswith('.')] + + except (OSError, PermissionError): + pass + + return sorted(large_files, key=lambda x: x['size'], reverse=True)[:20] + + def show_large_files(self): + path = Prompt.ask( + "\n[bold]Enter path to scan[/bold]", + default="/" if self.system != "Windows" else "C:\\" + ) + + min_size = Prompt.ask( + "[bold]Minimum file size (MB)[/bold]", + default="100" + ) + + try: + min_size = int(min_size) + except ValueError: + min_size = 100 + + self.console.print(f"\n[bold yellow]Scanning {path} for files larger than {min_size}MB...[/bold yellow]") + + with self.console.status("[bold green]Scanning..."): + large_files = self.find_large_files(path, min_size) + + if not large_files: + self.console.print(f"[green]No files larger than {min_size}MB found[/green]") + return + + table = Table(show_header=True, header_style="bold magenta") + table.add_column("File Name", style="cyan", max_width=40) + table.add_column("Size", justify="right") + table.add_column("Path", style="dim", max_width=60) + + for file_info in large_files: + table.add_row( + file_info['name'], + self.format_bytes(file_info['size']), + file_info['path'] + ) + + panel = Panel(table, title="[bold]Large Files Found[/bold]", border_style="yellow") + self.console.print(panel) + + def get_directory_size(self, path): + total = 0 + try: + for dirpath, dirnames, filenames in os.walk(path): + for filename in filenames: + try: + filepath = os.path.join(dirpath, filename) + total += os.path.getsize(filepath) + except (OSError, FileNotFoundError): + continue + except (OSError, PermissionError): + pass + return total + + def show_directory_analysis(self): + path = Prompt.ask( + "\n[bold]Enter directory path[/bold]", + default="/" if self.system != "Windows" else "C:\\" + ) + + if not os.path.exists(path): + self.console.print("[red]Path does not exist![/red]") + return + + self.console.print(f"\n[bold yellow]Analyzing directory: {path}[/bold yellow]") + + subdirs = [] + try: + with self.console.status("[bold green]Calculating sizes..."): + for item in os.listdir(path): + item_path = os.path.join(path, item) + if os.path.isdir(item_path): + size = self.get_directory_size(item_path) + subdirs.append({'name': item, 'size': size, 'path': item_path}) + except PermissionError: + self.console.print("[red]Permission denied![/red]") + return + + subdirs.sort(key=lambda x: x['size'], reverse=True) + + if not subdirs: + self.console.print("[yellow]No subdirectories found[/yellow]") + return + + table = Table(show_header=True, header_style="bold magenta") + table.add_column("Directory", style="cyan") + table.add_column("Size", justify="right") + table.add_column("Path", style="dim", max_width=50) + + for subdir in subdirs[:15]: + table.add_row( + subdir['name'], + self.format_bytes(subdir['size']), + subdir['path'] + ) + + panel = Panel(table, title="[bold]Directory Sizes[/bold]", border_style="blue") + self.console.print(panel) + + def show_storage_menu(self): + menu_text = """ +[bold green]1.[/bold green] Show Disk Usage +[bold green]2.[/bold green] Find Large Files +[bold green]3.[/bold green] Directory Analysis +[bold red]0.[/bold red] Back to Main Menu + """ + + panel = Panel( + menu_text.strip(), + title="[bold]Storage Analyzer[/bold]", + border_style="cyan" + ) + self.console.print(panel) + + def run(self): + while True: + self.console.clear() + self.show_storage_menu() + + choice = Prompt.ask( + "\n[bold]Select option[/bold]", + choices=["0", "1", "2", "3"], + default="0" + ) + + if choice == "0": + break + elif choice == "1": + self.show_disk_usage() + elif choice == "2": + self.show_large_files() + elif choice == "3": + self.show_directory_analysis() + + if choice != "0": + input("\nPress Enter to continue...") \ No newline at end of file diff --git a/submissions/SysMonit/system_monitor.py b/submissions/SysMonit/system_monitor.py new file mode 100644 index 00000000..a51c0c00 --- /dev/null +++ b/submissions/SysMonit/system_monitor.py @@ -0,0 +1,349 @@ +import psutil +import platform +import time +from datetime import datetime +from rich.console import Console +from rich.table import Table +from rich.panel import Panel +from rich.prompt import Prompt +from rich.columns import Columns +from rich.live import Live +import json + +class SystemMonitor: + def __init__(self): + self.console = Console() + + def format_bytes(self, bytes_val): + for unit in ['B', 'KB', 'MB', 'GB', 'TB']: + if bytes_val < 1024.0: + return f"{bytes_val:.1f} {unit}" + bytes_val /= 1024.0 + return f"{bytes_val:.1f} PB" + + def get_system_info(self): + uname = platform.uname() + boot_time = datetime.fromtimestamp(psutil.boot_time()) + + return { + 'system': uname.system, + 'node': uname.node, + 'release': uname.release, + 'version': uname.version, + 'machine': uname.machine, + 'processor': uname.processor, + 'boot_time': boot_time, + 'uptime': datetime.now() - boot_time + } + + def show_system_info(self): + self.console.print("\n[bold cyan]System Information[/bold cyan]") + + info = self.get_system_info() + + table = Table(show_header=False, box=None) + table.add_column("Property", style="bold cyan", width=15) + table.add_column("Value", style="white") + + table.add_row("System:", info['system']) + table.add_row("Node Name:", info['node']) + table.add_row("Release:", info['release']) + table.add_row("Machine:", info['machine']) + table.add_row("Processor:", info['processor'] if info['processor'] else 'Unknown') + table.add_row("Boot Time:", info['boot_time'].strftime('%Y-%m-%d %H:%M:%S')) + table.add_row("Uptime:", str(info['uptime']).split('.')[0]) + + panel = Panel(table, title="[bold]System Details[/bold]", border_style="blue") + self.console.print(panel) + + def get_cpu_info(self): + cpu_freq = psutil.cpu_freq() + cpu_count_physical = psutil.cpu_count(logical=False) + cpu_count_logical = psutil.cpu_count(logical=True) + + return { + 'physical_cores': cpu_count_physical, + 'logical_cores': cpu_count_logical, + 'max_frequency': cpu_freq.max if cpu_freq else 0, + 'min_frequency': cpu_freq.min if cpu_freq else 0, + 'current_frequency': cpu_freq.current if cpu_freq else 0, + 'cpu_usage': psutil.cpu_percent(interval=1), + 'per_cpu_usage': psutil.cpu_percent(interval=1, percpu=True) + } + + def show_cpu_info(self): + self.console.print("\n[bold cyan]CPU Information[/bold cyan]") + + cpu_info = self.get_cpu_info() + + main_table = Table(show_header=False, box=None) + main_table.add_column("Property", style="bold cyan", width=20) + main_table.add_column("Value", style="white") + + main_table.add_row("Physical Cores:", str(cpu_info['physical_cores'])) + main_table.add_row("Logical Cores:", str(cpu_info['logical_cores'])) + + if cpu_info['max_frequency']: + main_table.add_row("Max Frequency:", f"{cpu_info['max_frequency']:.2f} MHz") + main_table.add_row("Min Frequency:", f"{cpu_info['min_frequency']:.2f} MHz") + main_table.add_row("Current Frequency:", f"{cpu_info['current_frequency']:.2f} MHz") + + usage_color = "red" if cpu_info['cpu_usage'] > 80 else "yellow" if cpu_info['cpu_usage'] > 60 else "green" + main_table.add_row("Overall Usage:", f"[{usage_color}]{cpu_info['cpu_usage']:.1f}%[/{usage_color}]") + + per_cpu_table = Table(show_header=True, header_style="bold magenta") + per_cpu_table.add_column("Core", justify="center", style="cyan") + per_cpu_table.add_column("Usage", justify="right") + + for i, usage in enumerate(cpu_info['per_cpu_usage']): + color = "red" if usage > 80 else "yellow" if usage > 60 else "green" + per_cpu_table.add_row(f"Core {i}", f"[{color}]{usage:.1f}%[/{color}]") + + cpu_panel = Panel(main_table, title="[bold]CPU Details[/bold]", border_style="green") + usage_panel = Panel(per_cpu_table, title="[bold]Per-Core Usage[/bold]", border_style="green") + + self.console.print(Columns([cpu_panel, usage_panel])) + + def get_memory_info(self): + virtual_mem = psutil.virtual_memory() + swap_mem = psutil.swap_memory() + + return { + 'total': virtual_mem.total, + 'available': virtual_mem.available, + 'used': virtual_mem.used, + 'free': virtual_mem.free, + 'percent': virtual_mem.percent, + 'swap_total': swap_mem.total, + 'swap_used': swap_mem.used, + 'swap_free': swap_mem.free, + 'swap_percent': swap_mem.percent + } + + def show_memory_info(self): + self.console.print("\n[bold cyan]Memory Information[/bold cyan]") + + mem_info = self.get_memory_info() + + ram_table = Table(show_header=False, box=None) + ram_table.add_column("Property", style="bold cyan", width=15) + ram_table.add_column("Value", style="white") + + mem_color = "red" if mem_info['percent'] > 80 else "yellow" if mem_info['percent'] > 60 else "green" + + ram_table.add_row("Total RAM:", self.format_bytes(mem_info['total'])) + ram_table.add_row("Available:", self.format_bytes(mem_info['available'])) + ram_table.add_row("Used:", self.format_bytes(mem_info['used'])) + ram_table.add_row("Free:", self.format_bytes(mem_info['free'])) + ram_table.add_row("Usage:", f"[{mem_color}]{mem_info['percent']:.1f}%[/{mem_color}]") + + ram_panel = Panel(ram_table, title="[bold]RAM[/bold]", border_style="blue") + + if mem_info['swap_total'] > 0: + swap_table = Table(show_header=False, box=None) + swap_table.add_column("Property", style="bold cyan", width=15) + swap_table.add_column("Value", style="white") + + swap_color = "red" if mem_info['swap_percent'] > 80 else "yellow" if mem_info['swap_percent'] > 60 else "green" + + swap_table.add_row("Total Swap:", self.format_bytes(mem_info['swap_total'])) + swap_table.add_row("Used:", self.format_bytes(mem_info['swap_used'])) + swap_table.add_row("Free:", self.format_bytes(mem_info['swap_free'])) + swap_table.add_row("Usage:", f"[{swap_color}]{mem_info['swap_percent']:.1f}%[/{swap_color}]") + + swap_panel = Panel(swap_table, title="[bold]Swap[/bold]", border_style="yellow") + self.console.print(Columns([ram_panel, swap_panel])) + else: + self.console.print(ram_panel) + + def get_disk_info(self): + disk_usage = [] + disk_io = psutil.disk_io_counters(perdisk=True) + + for partition in psutil.disk_partitions(): + try: + usage = psutil.disk_usage(partition.mountpoint) + disk_info = { + 'device': partition.device, + 'mountpoint': partition.mountpoint, + 'file_system': partition.fstype, + 'total': usage.total, + 'used': usage.used, + 'free': usage.free, + 'percent': (usage.used / usage.total) * 100 + } + disk_usage.append(disk_info) + except PermissionError: + continue + + return disk_usage, disk_io + + def show_disk_info(self): + self.console.print("\n[bold cyan]Disk Information[/bold cyan]") + + disk_usage, disk_io = self.get_disk_info() + + table = Table(show_header=True, header_style="bold magenta") + table.add_column("Device", style="cyan") + table.add_column("Mountpoint", style="green") + table.add_column("File System", style="dim") + table.add_column("Total", justify="right") + table.add_column("Used", justify="right") + table.add_column("Free", justify="right") + table.add_column("Usage%", justify="right") + + for disk in disk_usage: + usage_color = "red" if disk['percent'] > 90 else "yellow" if disk['percent'] > 75 else "green" + + table.add_row( + disk['device'], + disk['mountpoint'], + disk['file_system'], + self.format_bytes(disk['total']), + self.format_bytes(disk['used']), + self.format_bytes(disk['free']), + f"[{usage_color}]{disk['percent']:.1f}%[/{usage_color}]" + ) + + panel = Panel(table, title="[bold]Disk Usage[/bold]", border_style="green") + self.console.print(panel) + + def show_sensors_info(self): + self.console.print("\n[bold cyan]Sensors Information[/bold cyan]") + + try: + temps = psutil.sensors_temperatures() + if temps: + temp_table = Table(show_header=True, header_style="bold magenta") + temp_table.add_column("Sensor", style="cyan") + temp_table.add_column("Temperature", justify="right") + temp_table.add_column("High", justify="right") + temp_table.add_column("Critical", justify="right") + + for name, entries in temps.items(): + for entry in entries: + temp_color = "red" if entry.current > 80 else "yellow" if entry.current > 60 else "green" + temp_table.add_row( + f"{name} ({entry.label or 'N/A'})", + f"[{temp_color}]{entry.current:.1f}°C[/{temp_color}]", + f"{entry.high:.1f}°C" if entry.high else "N/A", + f"{entry.critical:.1f}°C" if entry.critical else "N/A" + ) + + temp_panel = Panel(temp_table, title="[bold]Temperature Sensors[/bold]", border_style="red") + self.console.print(temp_panel) + else: + self.console.print("[yellow]No temperature sensors found[/yellow]") + + except AttributeError: + self.console.print("[yellow]Temperature sensors not supported on this platform[/yellow]") + + try: + fans = psutil.sensors_fans() + if fans: + fan_table = Table(show_header=True, header_style="bold magenta") + fan_table.add_column("Fan", style="cyan") + fan_table.add_column("Speed (RPM)", justify="right") + + for name, entries in fans.items(): + for entry in entries: + fan_table.add_row( + f"{name} ({entry.label or 'N/A'})", + f"{entry.current} RPM" + ) + + fan_panel = Panel(fan_table, title="[bold]Fan Sensors[/bold]", border_style="blue") + self.console.print(fan_panel) + + except AttributeError: + pass + + def show_realtime_monitor(self, duration=30): + self.console.print(f"\n[bold yellow]Real-time System Monitor ({duration}s)[/bold yellow]") + self.console.print("[dim]Press Ctrl+C to stop[/dim]") + + def create_monitor_layout(): + cpu_percent = psutil.cpu_percent(interval=0.1) + memory = psutil.virtual_memory() + + cpu_color = "red" if cpu_percent > 80 else "yellow" if cpu_percent > 60 else "green" + mem_color = "red" if memory.percent > 80 else "yellow" if memory.percent > 60 else "green" + + monitor_table = Table(show_header=True, header_style="bold magenta") + monitor_table.add_column("Resource", style="cyan", width=15) + monitor_table.add_column("Usage", justify="right", width=15) + monitor_table.add_column("Status", justify="center", width=10) + + monitor_table.add_row( + "CPU", + f"[{cpu_color}]{cpu_percent:.1f}%[/{cpu_color}]", + "šŸ”“" if cpu_percent > 80 else "🟔" if cpu_percent > 60 else "🟢" + ) + + monitor_table.add_row( + "Memory", + f"[{mem_color}]{memory.percent:.1f}%[/{mem_color}]", + "šŸ”“" if memory.percent > 80 else "🟔" if memory.percent > 60 else "🟢" + ) + + return Panel( + monitor_table, + title=f"[bold]System Monitor - {datetime.now().strftime('%H:%M:%S')}[/bold]", + border_style="green" + ) + + try: + with Live(create_monitor_layout(), refresh_per_second=2) as live: + start_time = time.time() + while time.time() - start_time < duration: + time.sleep(0.5) + live.update(create_monitor_layout()) + except KeyboardInterrupt: + self.console.print("\n[yellow]Monitoring stopped[/yellow]") + + def show_monitor_menu(self): + menu_text = """ +[bold green]1.[/bold green] System Information +[bold green]2.[/bold green] CPU Information +[bold green]3.[/bold green] Memory Information +[bold green]4.[/bold green] Disk Information +[bold green]5.[/bold green] Sensors Information +[bold green]6.[/bold green] Real-time Monitor +[bold red]0.[/bold red] Back to Main Menu + """ + + panel = Panel( + menu_text.strip(), + title="[bold]System Monitor[/bold]", + border_style="cyan" + ) + self.console.print(panel) + + def run(self): + while True: + self.console.clear() + self.show_monitor_menu() + + choice = Prompt.ask( + "\n[bold]Select option[/bold]", + choices=["0", "1", "2", "3", "4", "5", "6"], + default="0" + ) + + if choice == "0": + break + elif choice == "1": + self.show_system_info() + elif choice == "2": + self.show_cpu_info() + elif choice == "3": + self.show_memory_info() + elif choice == "4": + self.show_disk_info() + elif choice == "5": + self.show_sensors_info() + elif choice == "6": + self.show_realtime_monitor() + + if choice != "0": + input("\nPress Enter to continue...") \ No newline at end of file diff --git a/submissions/SysMonit/task_manager.py b/submissions/SysMonit/task_manager.py new file mode 100644 index 00000000..c8be59bc --- /dev/null +++ b/submissions/SysMonit/task_manager.py @@ -0,0 +1,263 @@ +import psutil +import time +import signal +import os +from rich.console import Console +from rich.table import Table +from rich.panel import Panel +from rich.prompt import Prompt, Confirm +from rich.live import Live +from rich.layout import Layout + +class TaskManager: + def __init__(self): + self.console = Console() + + def format_bytes(self, bytes_val): + for unit in ['B', 'KB', 'MB', 'GB']: + if bytes_val < 1024.0: + return f"{bytes_val:.1f}{unit}" + bytes_val /= 1024.0 + return f"{bytes_val:.1f}TB" + + def get_processes(self, sort_by='cpu'): + processes = [] + + for proc in psutil.process_iter(['pid', 'name', 'cpu_percent', 'memory_percent', 'status', 'username']): + try: + proc_info = proc.info + proc_info['memory_mb'] = proc.memory_info().rss / 1024 / 1024 + processes.append(proc_info) + except (psutil.NoSuchProcess, psutil.AccessDenied): + continue + + if sort_by == 'cpu': + processes.sort(key=lambda x: x['cpu_percent'] or 0, reverse=True) + elif sort_by == 'memory': + processes.sort(key=lambda x: x['memory_percent'] or 0, reverse=True) + elif sort_by == 'name': + processes.sort(key=lambda x: x['name'] or '') + + return processes + + def show_processes(self, sort_by='cpu', limit=20): + processes = self.get_processes(sort_by) + + table = Table(show_header=True, header_style="bold magenta") + table.add_column("PID", justify="right", style="cyan") + table.add_column("Name", style="green", max_width=25) + table.add_column("CPU%", justify="right") + table.add_column("Memory%", justify="right") + table.add_column("Memory", justify="right") + table.add_column("Status", justify="center") + table.add_column("User", style="dim", max_width=15) + + for proc in processes[:limit]: + cpu_color = "red" if (proc['cpu_percent'] or 0) > 80 else "yellow" if (proc['cpu_percent'] or 0) > 50 else "white" + mem_color = "red" if (proc['memory_percent'] or 0) > 80 else "yellow" if (proc['memory_percent'] or 0) > 50 else "white" + + status_icon = { + 'running': '🟢', + 'sleeping': '🟔', + 'stopped': 'šŸ”“', + 'zombie': 'šŸ’€' + }.get(proc['status'], '⚪') + + table.add_row( + str(proc['pid']), + proc['name'] or 'Unknown', + f"[{cpu_color}]{proc['cpu_percent']:.1f}%[/{cpu_color}]" if proc['cpu_percent'] else "0.0%", + f"[{mem_color}]{proc['memory_percent']:.1f}%[/{mem_color}]" if proc['memory_percent'] else "0.0%", + self.format_bytes(proc['memory_mb'] * 1024 * 1024), + f"{status_icon} {proc['status']}", + proc['username'] or 'Unknown' + ) + + return table + + def show_process_list(self): + sort_options = {'1': 'cpu', '2': 'memory', '3': 'name'} + + self.console.print("\n[bold cyan]Process List[/bold cyan]") + sort_choice = Prompt.ask( + "[bold]Sort by[/bold] ([green]1[/green]) CPU [green]2[/green]) Memory [green]3[/green]) Name", + choices=["1", "2", "3"], + default="1" + ) + + sort_by = sort_options[sort_choice] + table = self.show_processes(sort_by) + + panel = Panel(table, title=f"[bold]Processes (sorted by {sort_by.upper()})[/bold]", border_style="green") + self.console.print(panel) + + def kill_process(self): + pid = Prompt.ask("\n[bold]Enter PID to terminate[/bold]") + + try: + pid = int(pid) + process = psutil.Process(pid) + process_name = process.name() + + if Confirm.ask(f"[red]Terminate process '{process_name}' (PID: {pid})?[/red]"): + process.terminate() + + try: + process.wait(timeout=3) + self.console.print(f"[green]āœ“ Process {process_name} (PID: {pid}) terminated[/green]") + except psutil.TimeoutExpired: + process.kill() + self.console.print(f"[yellow]⚠ Process {process_name} (PID: {pid}) force killed[/yellow]") + + except ValueError: + self.console.print("[red]Invalid PID![/red]") + except psutil.NoSuchProcess: + self.console.print("[red]Process not found![/red]") + except psutil.AccessDenied: + self.console.print("[red]Access denied! Try running as administrator/root[/red]") + except Exception as e: + self.console.print(f"[red]Error: {e}[/red]") + + def show_system_resources(self): + cpu_percent = psutil.cpu_percent(interval=1) + memory = psutil.virtual_memory() + swap = psutil.swap_memory() + + table = Table(show_header=True, header_style="bold magenta") + table.add_column("Resource", style="cyan") + table.add_column("Usage", justify="right") + table.add_column("Total", justify="right") + table.add_column("Available", justify="right") + table.add_column("Percent", justify="right") + + cpu_color = "red" if cpu_percent > 80 else "yellow" if cpu_percent > 60 else "green" + mem_color = "red" if memory.percent > 80 else "yellow" if memory.percent > 60 else "green" + swap_color = "red" if swap.percent > 80 else "yellow" if swap.percent > 60 else "green" + + table.add_row( + "CPU", + f"[{cpu_color}]{cpu_percent:.1f}%[/{cpu_color}]", + f"{psutil.cpu_count()} cores", + "-", + f"[{cpu_color}]{cpu_percent:.1f}%[/{cpu_color}]" + ) + + table.add_row( + "Memory", + self.format_bytes(memory.used), + self.format_bytes(memory.total), + self.format_bytes(memory.available), + f"[{mem_color}]{memory.percent:.1f}%[/{mem_color}]" + ) + + if swap.total > 0: + table.add_row( + "Swap", + self.format_bytes(swap.used), + self.format_bytes(swap.total), + self.format_bytes(swap.free), + f"[{swap_color}]{swap.percent:.1f}%[/{swap_color}]" + ) + + panel = Panel(table, title="[bold]System Resources[/bold]", border_style="blue") + self.console.print(panel) + + def show_top_processes(self, duration=10): + self.console.print(f"\n[bold yellow]Real-time process monitor ({duration}s)[/bold yellow]") + self.console.print("[dim]Press Ctrl+C to stop[/dim]") + + try: + with Live(self.show_processes(), refresh_per_second=2) as live: + start_time = time.time() + while time.time() - start_time < duration: + time.sleep(0.5) + live.update(self.show_processes()) + except KeyboardInterrupt: + self.console.print("\n[yellow]Monitoring stopped[/yellow]") + + def search_processes(self): + search_term = Prompt.ask("\n[bold]Enter process name to search[/bold]").lower() + + matching_processes = [] + for proc in psutil.process_iter(['pid', 'name', 'cpu_percent', 'memory_percent', 'status']): + try: + if search_term in proc.info['name'].lower(): + proc_info = proc.info + proc_info['memory_mb'] = proc.memory_info().rss / 1024 / 1024 + matching_processes.append(proc_info) + except (psutil.NoSuchProcess, psutil.AccessDenied): + continue + + if not matching_processes: + self.console.print(f"[yellow]No processes found matching '{search_term}'[/yellow]") + return + + table = Table(show_header=True, header_style="bold magenta") + table.add_column("PID", justify="right", style="cyan") + table.add_column("Name", style="green") + table.add_column("CPU%", justify="right") + table.add_column("Memory%", justify="right") + table.add_column("Status", justify="center") + + for proc in matching_processes: + status_icon = { + 'running': '🟢', + 'sleeping': '🟔', + 'stopped': 'šŸ”“', + 'zombie': 'šŸ’€' + }.get(proc['status'], '⚪') + + table.add_row( + str(proc['pid']), + proc['name'], + f"{proc['cpu_percent']:.1f}%" if proc['cpu_percent'] else "0.0%", + f"{proc['memory_percent']:.1f}%" if proc['memory_percent'] else "0.0%", + f"{status_icon} {proc['status']}" + ) + + panel = Panel(table, title=f"[bold]Processes matching '{search_term}'[/bold]", border_style="green") + self.console.print(panel) + + def show_task_menu(self): + menu_text = """ +[bold green]1.[/bold green] Process List +[bold green]2.[/bold green] System Resources +[bold green]3.[/bold green] Real-time Monitor +[bold green]4.[/bold green] Search Processes +[bold green]5.[/bold green] Kill Process +[bold red]0.[/bold red] Back to Main Menu + """ + + panel = Panel( + menu_text.strip(), + title="[bold]Task Manager[/bold]", + border_style="cyan" + ) + self.console.print(panel) + + def run(self): + while True: + self.console.clear() + self.show_task_menu() + + choice = Prompt.ask( + "\n[bold]Select option[/bold]", + choices=["0", "1", "2", "3", "4", "5"], + default="0" + ) + + if choice == "0": + break + elif choice == "1": + self.show_process_list() + elif choice == "2": + self.show_system_resources() + elif choice == "3": + self.show_top_processes() + elif choice == "4": + self.search_processes() + elif choice == "5": + self.kill_process() + + if choice != "0": + input("\nPress Enter to continue...") \ No newline at end of file