/*auto readmore*/ /*auto readmore*/ /* an hien script*/ // an hien password /*an hien ma chuong trinh cong tru */ /*Scrollbox thanh cuon*/ /***Nhung CODE***/ /* dòng xanh dòng trắng */ /* https://cdnjs.com/libraries/prism lay thu vien, can vao ten file ma goi 1. copy link vao vi du:prism-python.min.js 2. ten ngon nua la python */ /*=== New posts ===*/ /*header slider*/ /*=== bai viet lien quan===*/ /*===tabcode===*/

Backup MySQL/MariaDB bằng CLI/Power Shell

 MỤC TIÊU:

- Backup Database của MySQL, lưu backup giữ lại bao nhiêu ngày gần nhất

- File .env chứa các thông tin Username, password, database cần backup, số ngày cần lưu, lưu trữ ở đâu

- Code chính backup bằng Power Shell

- Tạo file .bat gọi file Power Shell (.ps1) để thực backup

- Lập lịch backup theo thời gian

- Backup có ghi lại log đâ làm những gì

Cấu trúc thư mục:

- Souce Code:

C:\vck\TestMySQL\
├── bkDB\
├── .env
├── bkMySQL.ps1
└── bkMySQL.bat

- Cấu trúc thư mục backup tạo ra:

C:\vck\TestMySQL\bkDB\
├── vck_test_1\
│   ├── users.sql
│   ├── orders.sql
│   └── backup_log_2026-06-20_103000.log  <-- Log riêng của vck_test
├── tonyteo_v2_1\
│   ├── products.sql
│   ├── customers.sql
│   └── backup_log_2026-06-20_103115.log  <-- Log riêng của tony teo
└── company_db_1\
    ├── employees.sql
    └── backup_log_2026-06-20_103240.log  <-- Log riêng của company_db

THỰC HIỆN:

1. Nội dung file .env

#DB_NAME=vck_test,tonyteo_v2 # nhiều Database, đặt cách nhau dấu phẩy
DB_NAME=vck_test
DB_USER=root
DB_PASS=pk123456
DB_PORT=3308
DB_HOST=127.0.0.1
# Muốn lưu bao nhiêu ngày, giữ lại bao nhiêu ngày gần nhất
MAX_DAYS=4
MYSQL_BIN=C:\Program Files\MariaDB 12.3\bin\mysql.exe
MYSQLDUMP_BIN=C:\Program Files\MariaDB 12.3\bin\mysqldump.exe
# File backup lưu ở đâu
BASE_BACKUP_DIR=C:\vck\TestMySQL\bkDB

2. Nội dung file bkMySQL.ps1

# ==========================================
# ĐỌC VÀ LÀM SẠCH CẤU HÌNH TỪ FILE .ENV
# ==========================================
$envFile = Join-Path $PSScriptRoot ".env"

if (-not (Test-Path $envFile)) {
    Write-Error "KHÔNG TÌM THẤY file .env nằm cùng thư mục với script!"
    exit 1
}

Get-Content $envFile | ForEach-Object {
    $line = $_.Trim()
    if ($line -and -not $line.StartsWith('#') -and $line.Contains('=')) {
        $index = $line.IndexOf('=')
        $key   = $line.Substring(0, $index).Trim()
        $value = $line.Substring($index + 1).Trim().Trim('"').Trim("'")
        Set-Variable -Name $key -Value $value -Force
    }
}

# Tách chuỗi DB_NAME trong .env thành một mảng các Database
$dbList = $DB_NAME -split ',' | ForEach-Object { $_.Trim() }

# Kiểm tra đường dẫn công cụ trước khi vào vòng lặp
if (-not (Test-Path $MYSQL_BIN)) {
    Write-Error "KHÔNG TÌM THẤY file mysql.exe tại: $MYSQL_BIN"
    exit 1
}

# ==========================================
# VÒNG LẶP DUYỆT QUA TỪNG DATABASE
# ==========================================
foreach ($currentDB in $dbList) {
    if ([string]::IsNullOrWhiteSpace($currentDB)) { continue }

    # Đã sửa lỗi chính tả từ Magentas -> Magenta để giao diện chạy mượt mà
    Write-Host "--------------------------------------------------" -ForegroundColor Magenta
    Write-Host "XỬ LÝ DATABASE: $currentDB" -ForegroundColor Magenta
    Write-Host "--------------------------------------------------" -ForegroundColor Magenta

    # 1. Tính toán cấu trúc xoay vòng (Retention) cho từng DB
    $currentDayOfMonth = (Get-Date).Day
    $xx = ($currentDayOfMonth % [int]$MAX_DAYS) + 1

    $FOLDER_NAME = "${currentDB}_$xx"
    $BACKUP_DIR  = Join-Path $BASE_BACKUP_DIR $FOLDER_NAME

    # 2. Xử lý dọn dẹp / tạo mới thư mục của DB hiện tại
    if (Test-Path $BACKUP_DIR) {
        Write-Host "Thu muc $FOLDER_NAME da ton tai. Dang xoa file cu de lam rong..." -ForegroundColor Yellow
        Remove-Item -Path "$BACKUP_DIR\*" -Recurse -Force -ErrorAction SilentlyContinue
    } else {
        Write-Host "Dang tao thu muc backup moi: $FOLDER_NAME" -ForegroundColor Cyan
        New-Item -ItemType Directory -Path $BACKUP_DIR | Out-Null
    }

    # 3. Định nghĩa file log nằm trong thư mục backup riêng của DB đó
    $TIMESTAMP      = Get-Date -Format "yyyy-MM-dd_HHmmss"
    $PROCESS_LOG    = Join-Path $BACKUP_DIR "backup_log_$TIMESTAMP.log"
    $ERROR_LOG_FILE = Join-Path $PSScriptRoot "table.log"

    # Hàm ghi log cục bộ (Inline function)
    function Log-CurrentMessage ($msg) {
        $timeStr = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
        "[$timeStr] $msg" | Out-File -FilePath $PROCESS_LOG -Append -Encoding utf8
    }

    Log-CurrentMessage "=== BAT DAU TIEN TRINH BACKUP DATABASE: $currentDB ==="
    Log-CurrentMessage "Thu muc luu tru: $BACKUP_DIR"

    # 4. Kiểm tra kết nối tới Database hiện tại (Health Check)
    # Thêm Out-Null để không bị in đè số 1 1 thừa thãi ra màn hình console của bạn
    & $MYSQL_BIN -h $DB_HOST -u $DB_USER "-p$DB_PASS" -P $DB_PORT -e "USE $currentDB; SELECT 1;" 2>$null | Out-Null
    if ($LASTEXITCODE -ne 0) {
        $errorMsg = "ERROR: Khong the ket noi MySQL hoac Database '$currentDB' khong ton tai."
        Set-Content -Path $ERROR_LOG_FILE -Value $errorMsg
        Log-CurrentMessage "ERROR: Ket noi den '$currentDB' that bai. Bo qua DB nay."
        Write-Warning "Ket noi that bai toi database '$currentDB'. Chi tiet ghi tai table.log. Dang chuyen sang DB tiep theo..."
        continue
    }

    Log-CurrentMessage "Ket noi database thanh cong. Dang lay danh sach cac bang..."

    # 5. Lấy danh sách bảng của DB hiện tại
    $tables = & $MYSQL_BIN -h $DB_HOST -u $DB_USER "-p$DB_PASS" -P $DB_PORT -N -e "SHOW TABLES FROM $currentDB;"

    # 6. Vòng lặp Backup từng bảng dữ liệu
    $successCount = 0
    foreach ($table in $tables) {
        if (-not [string]::IsNullOrWhiteSpace($table)) {
            $outputFile = Join-Path $BACKUP_DIR "$table.sql"
            
            & $MYSQLDUMP_BIN -h $DB_HOST -u $DB_USER "-p$DB_PASS" -P $DB_PORT $currentDB $table --result-file=$outputFile 2>$nul
            
            if ($LASTEXITCODE -eq 0) {
                Log-CurrentMessage "Backup thanh cong table: $table -> $table.sql"
                $successCount++
            } else {
                Log-CurrentMessage "ERROR: Backup THAT BAI table: $table"
            }
        }
    }

    Log-CurrentMessage "=== KET THUC TIEN TRINH: Da backup thanh cong $successCount tables cua DB $currentDB ==="
    Write-Host "Finished export database [$currentDB] to folder: $BACKUP_DIR" -ForegroundColor Green
}

Write-Host "`n================================================--" -ForegroundColor Green
Write-Host "HOÀN THÀNH TẤT CẢ TIẾN TRÌNH BACKUP DỮ LIỆU!" -ForegroundColor Green

3. Nội dung file bkMySQL.bat

@echo off
:: Di chuyển terminal về đúng thư mục chứa file .bat này
cd /d "%~dp0"

:: Gọi PowerShell chạy script với quyền Bypass/RemoteSigned tạm thời
powershell -NoProfile -ExecutionPolicy Bypass -File "bkMySQL.ps1"

exit /b %errorlevel%

4. Lập lịch Task Sheduler 

(này đơn giản nên không hướng dẫn)


[TIP] SỬA LỖI CHẶN TRUY CẬP SMB GUEST/ANONYMOUS TRÊN WINDOWS SERVER 2019

 Áp dụng khi: Windows Server 2019/2022 kết nối vào NAS hoặc File Server khác qua tài khoản Guest/Anonymous nhưng bị báo lỗi bảo mật (Block) hoặc không tìm thấy đường dẫn dù mạng vẫn thông, nhập mật khẩu đúng

Mở gpedit.msc (Local Group Policy Editor) trên máy Server và cấu hình các mục sau:

0. Trên NAS

  • Enable tài khoảng Guest trên NAS (nếu muốn xem không cần password thì làm mục này)

  • Phân quyền tài khoảng Guest vào phần Share



1. Cho phép đăng nhập Guest không xác thực (Insecure Guest Logons)

  • Đường dẫn: Computer ConfigurationAdministrative TemplatesNetworkLanman Workstation

  • Chính sách: Enable insecure guest logons ➔ Chọn Enabled.



2. Tắt bắt buộc ký số SMB (SMB Client Digitally Sign)

  • Đường dẫn: Computer ConfigurationWindows SettingsSecurity SettingsLocal PoliciesSecurity Options

  • Chính sách 1: Microsoft network client: Digitally sign communications (always) ➔ Chọn Disabled.

  • Chính sách 2: Microsoft network client: Digitally sign communications (if server agrees) ➔ Chọn Enabled.



3. Cấu hình cho phép truy cập Anonymous (Null Session)

  • Đường dẫn: (Vẫn ở mục Security Options bên trên)

  • Chính sách 1: Network access: Restrict anonymous access to Named Pipes and Shares ➔ Chọn Disabled.

  • Chính sách 2: Network access: Shares that can be accessed anonymously ➔ Nhấp đúp và điền tên thư mục Share (Ví dụ: \\192.168.99.111).



4. Áp dụng chính sách và xóa Cache cũ

Mở Command Prompt (Admin) và chạy tuần tự 2 lệnh sau:

DOS
:: 1. Ép hệ thống cập nhật Group Policy ngay lập tức
gpupdate /force

:: 2. Xóa sạch các session kết nối mạng cũ đang bị kẹt/lỗi trong bộ nhớ tạm
net use * /delete /y

Hoàn tất: Sử dụng Windows + R và truy cập lại đường dẫn \\IP_NAS hoặc \\Domain_NAS.

/*header slide*/