B1. Tải và cài đặt Xampp mới nhất
B4, Extract sourcecode php và import .sql vô phpmyadmin
B1. Tải và cài đặt Xampp mới nhất
B1. Script cho AI thực hiện gen mã nguồn Python.
mình đang dùng python 3.13.5 hãy viết cho tôi 1 phần mềm đọc
thông tin phần cứng máy tính có giao diện đồ họa, mã nguồn nằm trong 1 file .py
duy nhất, Phần mềm sẽ sử dụng SQLite làm cơ sở dữ liệu , có thể chạy được luôn,
dễ dàng nâng cấp sau này để trở thành 1 tab của phần mềm lớn khác
B2. Sau khi cài xong python mới nhất: 3.13.5 thì chạy các lệnh sau trong cmd để tải package thư viện hỗ trợ xem thông tin phần cứng máy tính về:
C:\Windows\System32>pip install psutil
C:\Windows\System32>pip install wmi
C:\Windows\System32>pip install py-cpuinfo
B3. Code do gemini tạo mình save thành file hardware_monitor.py ròi chạy trong cmd:
d:\>py -3 hardware_monitor.py
import tkinter as tk from tkinter import ttk, messagebox import sqlite3 import platform import psutil import wmi # Chỉ dành cho Windows import cpuinfo import socket # Import thư viện socket để dùng AF_INET class HardwareInfoApp: def __init__(self, master): self.master = master master.title("Thông tin phần cứng máy tính") master.geometry("800x600") self.db_name = "hardware_info.db" self.create_database() self.create_widgets() self.load_hardware_info() def create_database(self): conn = sqlite3.connect(self.db_name) cursor = conn.cursor() cursor.execute(""" CREATE TABLE IF NOT EXISTS hardware_data ( id INTEGER PRIMARY KEY AUTOINCREMENT, category TEXT, item TEXT, value TEXT ) """) conn.commit() conn.close() def create_widgets(self): # Notebook for tabs self.notebook = ttk.Notebook(self.master) self.notebook.pack(expand=True, fill="both", padx=10, pady=10) # Tab 1: System Info self.system_frame = ttk.Frame(self.notebook) self.notebook.add(self.system_frame, text="Hệ thống") self.create_system_info_widgets(self.system_frame) # Tab 2: CPU Info self.cpu_frame = ttk.Frame(self.notebook) self.notebook.add(self.cpu_frame, text="CPU") self.create_cpu_info_widgets(self.cpu_frame) # Tab 3: Memory Info self.memory_frame = ttk.Frame(self.notebook) self.notebook.add(self.memory_frame, text="RAM") self.create_memory_info_widgets(self.memory_frame) # Tab 4: Disk Info self.disk_frame = ttk.Frame(self.notebook) self.notebook.add(self.disk_frame, text="Ổ đĩa") self.create_disk_info_widgets(self.disk_frame) # Tab 5: Network Info self.network_frame = ttk.Frame(self.notebook) self.notebook.add(self.network_frame, text="Mạng") self.create_network_info_widgets(self.network_frame) # Tab 6: GPU Info (Windows only) # Chỉ tạo tab GPU nếu hệ điều hành là Windows để tránh lỗi import wmi trên Linux/macOS if platform.system() == "Windows": self.gpu_frame = ttk.Frame(self.notebook) self.notebook.add(self.gpu_frame, text="GPU") self.create_gpu_info_widgets(self.gpu_frame) # Buttons button_frame = ttk.Frame(self.master) button_frame.pack(pady=5) self.refresh_button = ttk.Button(button_frame, text="Làm mới", command=self.load_hardware_info) self.refresh_button.pack(side="left", padx=5) self.save_button = ttk.Button(button_frame, text="Lưu vào DB", command=self.save_all_info_to_db) self.save_button.pack(side="left", padx=5) def create_system_info_widgets(self, parent_frame): self.system_info_tree = ttk.Treeview(parent_frame, columns=("Item", "Value"), show="headings") self.system_info_tree.heading("Item", text="Mục") self.system_info_tree.heading("Value", text="Giá trị") self.system_info_tree.pack(expand=True, fill="both") vsb = ttk.Scrollbar(parent_frame, orient="vertical", command=self.system_info_tree.yview) vsb.pack(side='right', fill='y') self.system_info_tree.configure(yscrollcommand=vsb.set) def create_cpu_info_widgets(self, parent_frame): self.cpu_info_tree = ttk.Treeview(parent_frame, columns=("Item", "Value"), show="headings") self.cpu_info_tree.heading("Item", text="Mục") self.cpu_info_tree.heading("Value", text="Giá trị") self.cpu_info_tree.pack(expand=True, fill="both") vsb = ttk.Scrollbar(parent_frame, orient="vertical", command=self.cpu_info_tree.yview) vsb.pack(side='right', fill='y') self.cpu_info_tree.configure(yscrollcommand=vsb.set) def create_memory_info_widgets(self, parent_frame): self.memory_info_tree = ttk.Treeview(parent_frame, columns=("Item", "Value"), show="headings") self.memory_info_tree.heading("Item", text="Mục") self.memory_info_tree.heading("Value", text="Giá trị") self.memory_info_tree.pack(expand=True, fill="both") vsb = ttk.Scrollbar(parent_frame, orient="vertical", command=self.memory_info_tree.yview) vsb.pack(side='right', fill='y') self.memory_info_tree.configure(yscrollcommand=vsb.set) def create_disk_info_widgets(self, parent_frame): self.disk_info_tree = ttk.Treeview(parent_frame, columns=("Device", "Mountpoint", "File System", "Size", "Used", "Free", "Percent"), show="headings") self.disk_info_tree.heading("Device", text="Thiết bị") self.disk_info_tree.heading("Mountpoint", text="Điểm gắn kết") self.disk_info_tree.heading("File System", text="Hệ thống tệp") self.disk_info_tree.heading("Size", text="Tổng dung lượng") self.disk_info_tree.heading("Used", text="Đã dùng") self.disk_info_tree.heading("Free", text="Còn trống") self.disk_info_tree.heading("Percent", text="Phần trăm") self.disk_info_tree.pack(expand=True, fill="both") vsb = ttk.Scrollbar(parent_frame, orient="vertical", command=self.disk_info_tree.yview) vsb.pack(side='right', fill='y') self.disk_info_tree.configure(yscrollcommand=vsb.set) def create_network_info_widgets(self, parent_frame): self.network_info_tree = ttk.Treeview(parent_frame, columns=("Interface", "IP Address", "Netmask", "MAC Address"), show="headings") self.network_info_tree.heading("Interface", text="Giao diện") self.network_info_tree.heading("IP Address", text="Địa chỉ IP") self.network_info_tree.heading("Netmask", text="Netmask") self.network_info_tree.heading("MAC Address", text="Địa chỉ MAC") self.network_info_tree.pack(expand=True, fill="both") vsb = ttk.Scrollbar(parent_frame, orient="vertical", command=self.network_info_tree.yview) vsb.pack(side='right', fill='y') self.network_info_tree.configure(yscrollcommand=vsb.set) def create_gpu_info_widgets(self, parent_frame): self.gpu_info_tree = ttk.Treeview(parent_frame, columns=("Property", "Value"), show="headings") self.gpu_info_tree.heading("Property", text="Thuộc tính") self.gpu_info_tree.heading("Value", text="Giá trị") self.gpu_info_tree.pack(expand=True, fill="both") vsb = ttk.Scrollbar(parent_frame, orient="vertical", command=self.gpu_info_tree.yview) vsb.pack(side='right', fill='y') self.gpu_info_tree.configure(yscrollcommand=vsb.set) def load_hardware_info(self): self.clear_trees() self.get_system_info() self.get_cpu_info() self.get_memory_info() self.get_disk_info() self.get_network_info() if platform.system() == "Windows": # Chỉ gọi nếu chạy trên Windows self.get_gpu_info() def clear_trees(self): for i in self.system_info_tree.get_children(): self.system_info_tree.delete(i) for i in self.cpu_info_tree.get_children(): self.cpu_info_tree.delete(i) for i in self.memory_info_tree.get_children(): self.memory_info_tree.delete(i) for i in self.disk_info_tree.get_children(): self.disk_info_tree.delete(i) for i in self.network_info_tree.get_children(): self.network_info_tree.delete(i) if platform.system() == "Windows": # Chỉ xóa nếu tab GPU tồn tại for i in self.gpu_info_tree.get_children(): self.gpu_info_tree.delete(i) def get_system_info(self): info = { "Hệ điều hành": platform.system(), "Phiên bản HĐH": platform.version(), "Kiến trúc": platform.machine(), "Tên máy tính": platform.node(), "Nền tảng": platform.platform(), "Phiên bản Python": platform.python_version(), } for item, value in info.items(): self.system_info_tree.insert("", "end", values=(item, value)) def get_cpu_info(self): cpu_data = cpuinfo.get_cpu_info() self.cpu_info_tree.insert("", "end", values=("Tên CPU", cpu_data.get('brand_original', 'N/A'))) self.cpu_info_tree.insert("", "end", values=("Kiến trúc", cpu_data.get('arch', 'N/A'))) self.cpu_info_tree.insert("", "end", values=("Số lõi vật lý", psutil.cpu_count(logical=False))) self.cpu_info_tree.insert("", "end", values=("Số luồng (lõi ảo)", psutil.cpu_count(logical=True))) # Lấy tần số CPU, xử lý trường hợp không có dữ liệu cpu_freq = psutil.cpu_freq() if cpu_freq: self.cpu_info_tree.insert("", "end", values=("Tần số tối đa", f"{cpu_freq.max:.2f} Mhz")) self.cpu_info_tree.insert("", "end", values=("Tần số hiện tại", f"{cpu_freq.current:.2f} Mhz")) else: self.cpu_info_tree.insert("", "end", values=("Tần số tối đa", "N/A")) self.cpu_info_tree.insert("", "end", values=("Tần số hiện tại", "N/A")) self.cpu_info_tree.insert("", "end", values=("Sử dụng CPU", f"{psutil.cpu_percent(interval=1)}%")) def get_memory_info(self): svmem = psutil.virtual_memory() self.memory_info_tree.insert("", "end", values=("Tổng RAM", self.bytes_to_gb(svmem.total))) self.memory_info_tree.insert("", "end", values=("RAM đã dùng", self.bytes_to_gb(svmem.used))) self.memory_info_tree.insert("", "end", values=("RAM còn trống", self.bytes_to_gb(svmem.available))) self.memory_info_tree.insert("", "end", values=("Phần trăm sử dụng", f"{svmem.percent}%")) swap = psutil.swap_memory() self.memory_info_tree.insert("", "end", values=("Tổng bộ nhớ ảo (Swap)", self.bytes_to_gb(swap.total))) self.memory_info_tree.insert("", "end", values=("Đã dùng bộ nhớ ảo (Swap)", self.bytes_to_gb(swap.used))) self.memory_info_tree.insert("", "end", values=("Còn trống bộ nhớ ảo (Swap)", self.bytes_to_gb(swap.free))) self.memory_info_tree.insert("", "end", values=("Phần trăm sử dụng bộ nhớ ảo (Swap)", f"{swap.percent}%")) def get_disk_info(self): partitions = psutil.disk_partitions() for p in partitions: try: usage = psutil.disk_usage(p.mountpoint) self.disk_info_tree.insert("", "end", values=( p.device, p.mountpoint, p.fstype, self.bytes_to_gb(usage.total), self.bytes_to_gb(usage.used), self.bytes_to_gb(usage.free), f"{usage.percent}%" )) except PermissionError: # Some partitions might not be accessible self.disk_info_tree.insert("", "end", values=(p.device, p.mountpoint, p.fstype, "N/A", "N/A", "N/A", "N/A")) except Exception as e: # Catch other potential errors self.disk_info_tree.insert("", "end", values=(p.device, p.mountpoint, p.fstype, "Lỗi", "Lỗi", "Lỗi", f"({e})")) def get_network_info(self): net_if_addrs = psutil.net_if_addrs() for interface_name, addresses in net_if_addrs.items(): ip_address = "N/A" netmask = "N/A" mac_address = "N/A" for address in addresses: # Sử dụng socket.AF_INET thay vì psutil.AF_INET để tương thích tốt hơn if address.family == socket.AF_INET: # IPv4 ip_address = address.address netmask = address.netmask # psutil.AF_LINK hoạt động tốt hơn với psutil elif address.family == psutil.AF_LINK: # MAC Address mac_address = address.address self.network_info_tree.insert("", "end", values=(interface_name, ip_address, netmask, mac_address)) def get_gpu_info(self): if platform.system() == "Windows": try: c = wmi.WMI() found_gpu = False for gpu in c.Win32_VideoController(): found_gpu = True self.gpu_info_tree.insert("", "end", values=("Tên card", gpu.Name)) # Kiểm tra và chuyển đổi AdapterRAM nếu có if hasattr(gpu, 'AdapterRAM') and gpu.AdapterRAM is not None: self.gpu_info_tree.insert("", "end", values=("Bộ nhớ RAM", self.bytes_to_gb(gpu.AdapterRAM))) else: self.gpu_info_tree.insert("", "end", values=("Bộ nhớ RAM", "N/A")) self.gpu_info_tree.insert("", "end", values=("Trạng thái", gpu.Status if hasattr(gpu, 'Status') else "N/A")) # Kiểm tra và hiển thị độ phân giải if hasattr(gpu, 'CurrentHorizontalResolution') and hasattr(gpu, 'CurrentVerticalResolution') and \ gpu.CurrentHorizontalResolution is not None and gpu.CurrentVerticalResolution is not None: self.gpu_info_tree.insert("", "end", values=("Độ phân giải", f"{gpu.CurrentHorizontalResolution}x{gpu.CurrentVerticalResolution}")) else: self.gpu_info_tree.insert("", "end", values=("Độ phân giải", "N/A")) self.gpu_info_tree.insert("", "end", values=("Bộ xử lý video", gpu.VideoProcessor if hasattr(gpu, 'VideoProcessor') else "N/A")) # Thêm một dòng trống để phân tách các GPU nếu có nhiều hơn 1 self.gpu_info_tree.insert("", "end", values=("", "")) if not found_gpu: self.gpu_info_tree.insert("", "end", values=("Không tìm thấy GPU", "Thông tin có thể không có sẵn hoặc cần driver")) except Exception as e: self.gpu_info_tree.insert("", "end", values=("Lỗi đọc GPU", str(e))) else: self.gpu_info_tree.insert("", "end", values=("Không hỗ trợ", "Chỉ hỗ trợ Windows")) def bytes_to_gb(self, bytes_val): if bytes_val is None: return "N/A" return f"{bytes_val / (1024**3):.2f} GB" def save_info_to_db(self, category, treeview): conn = sqlite3.connect(self.db_name) cursor = conn.cursor() for item in treeview.get_children(): values = treeview.item(item, 'values') if len(values) >= 2: # Ensure there are at least "Item" and "Value" item_name = values[0] item_value = values[1] cursor.execute("INSERT INTO hardware_data (category, item, value) VALUES (?, ?, ?)", (category, item_name, item_value)) else: # Handle cases like disk info with multiple columns if category == "Ổ đĩa": device = values[0] if len(values) > 0 else "N/A" details = ", ".join(map(str, values[1:])) if len(values) > 1 else "" cursor.execute("INSERT INTO hardware_data (category, item, value) VALUES (?, ?, ?)", (category, device, details)) elif category == "Mạng": interface = values[0] if len(values) > 0 else "N/A" details = ", ".join(map(str, values[1:])) if len(values) > 1 else "" cursor.execute("INSERT INTO hardware_data (category, item, value) VALUES (?, ?, ?)", (category, interface, details)) elif category == "GPU": prop = values[0] if len(values) > 0 else "N/A" val = values[1] if len(values) > 1 else "N/A" cursor.execute("INSERT INTO hardware_data (category, item, value) VALUES (?, ?, ?)", (category, prop, val)) conn.commit() conn.close() def save_all_info_to_db(self): conn = sqlite3.connect(self.db_name) cursor = conn.cursor() cursor.execute("DELETE FROM hardware_data") # Clear existing data conn.commit() conn.close() self.save_info_to_db("Hệ thống", self.system_info_tree) self.save_info_to_db("CPU", self.cpu_info_tree) self.save_info_to_db("RAM", self.memory_info_tree) self.save_info_to_db("Ổ đĩa", self.disk_info_tree) self.save_info_to_db("Mạng", self.network_info_tree) if platform.system() == "Windows": self.save_info_to_db("GPU", self.gpu_info_tree) messagebox.showinfo("Lưu thông tin", "Thông tin phần cứng đã được lưu vào cơ sở dữ liệu thành công!") # Cách chạy ứng dụng if __name__ == "__main__": root = tk.Tk() app = HardwareInfoApp(root) root.mainloop()
Cập nhật hệ thống:
sudo dnf update -y
Cài đặt NFS Utilities:
sudo dnf install -y nfs-utils
Kích hoạt và khởi động dịch vụ NFS:
sudo systemctl enable nfs-server rpcbind
sudo systemctl start nfs-server rpcbind
Kiểm tra trạng thái:
sudo systemctl status nfs-server rpcbind
Cấu hình FirewallD:
sudo firewall-cmd --permanent --add-service=nfs
sudo firewall-cmd --permanent --add-service=rpc-bind
sudo firewall-cmd --permanent --add-service=mountd sudo firewall-cmd --reload
Bạn có thể kiểm tra các dịch vụ đã được thêm:
sudo firewall-cmd --list-all
Tạo thư mục chia sẻ NFS:
Tạo một thư mục mới sẽ được chia sẻ cho ESXi. Ví dụ: /exports/datastore_NFS
sudo mkdir -p /exports/datastore_NFS
Gán quyền cho thư mục chia sẻ:
sudo chown nobody:nobody /exports/datastore_NFS
sudo chmod 777 /exports/datastore_NFS
Chỉnh sửa file /etc/exports
:
sudo vi /etc/exports
/exports/datastore_NFS 192.168.1.0/24(rw,sync,no_root_squash)
Áp dụng thay đổi: sudo exportfs -ra
Kiểm tra chia sẻ: showmount -e localhost
Nhập thông tin Datastore trên EXSI:
Nhập thông tin NFS Datastore trên EXSI 8 hoặc Vcenter
Name: Đặt tên cho Datastore của bạn (ví dụ: AlmaLinux_NFS_DS01
).
Folder: Nhập đường dẫn thư mục mà bạn đã chia sẻ trên AlmaLinux. Phải khớp chính xác với đường dẫn trong /etc/exports
. Ví dụ: /exports/datastore01
.
Server: Nhập địa chỉ IP hoặc hostname của AlmaLinux VM (NFS Server).
Nhấp Next.