Menu

7/29/25

chuẩn bị môi trường cài webserver Xampp trên windows

 B1. Tải và cài đặt Xampp mới nhất



B2, Sau khi cái xong, start các service và kiểm tra xem máy chủ web đã chạy hay chưa, truy cập trình duyệt:



B3. Truy cập phpmysql


B4, Extract sourcecode php và import .sql vô phpmyadmin




7/28/25

Code app xem phần cứng máy tính với python và gemini - AI

 

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()

7/24/25

Dựng NFS server (Almalinux) làm datastore cho EXSI 8

 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.