login.php cho wifi marketing Ruckus

 <?php
function h($s) {
    return htmlspecialchars((string)$s, ENT_QUOTES, 'UTF-8');
}

function cleanParams(array $input): array {
    $clean = [];

    foreach ($input as $key => $value) {
        $key = preg_replace('/^amp;/', '', (string)$key);
        $clean[$key] = $value;
    }

    return $clean;
}

$params = cleanParams($_POST);

// =======================
// CONFIG
// =======================

$defaultNbiHost = 'thay IP controller vào đây';

$nbiUser = 'nbi-acc';
$nbiPass = 'pass của nbi-acc';

// AAA Always Accept nên user/pass này chỉ là dummy
$ueUsername = 'ok';
$uePassword = 'ok';

// Chỉ cho phép gọi đúng vSZ NBI này
$allowedNbiHosts = [
    'thay IP controller vào đây',
];

// =======================
// INPUT FROM vSZ
// =======================

$nbiHost = $params['nbiIP'] ?? $defaultNbiHost;

if (!in_array($nbiHost, $allowedNbiHosts, true)) {
    $nbiHost = $defaultNbiHost;
}

$nbiUrl = 'https://' . $nbiHost . ':9443/portalintf';

$ueIp    = $params['uip'] ?? '';
$ueMac   = $params['client_mac'] ?? '';
$ueProxy = $params['proxy'] ?? '0';

if ($ueIp === '' || $ueMac === '') {
    http_response_code(400);
    echo 'Missing uip or client_mac';
    exit;
}

// =======================
// BUILD PAYLOAD
// =======================

$payload = [
    'Vendor'          => 'ruckus',
    'APIVersion'      => '1.0',
    'RequestCategory' => 'UserOnlineControl',
    'RequestType'     => 'Login',

    'RequestUserName' => $nbiUser,
    'RequestPassword' => $nbiPass,

    'UE-IP'       => $ueIp,
    'UE-MAC'      => $ueMac,
    'UE-Proxy'    => $ueProxy,
    'UE-Username' => $ueUsername,
    'UE-Password' => $uePassword,
];

// =======================
// CALL vSZ NBI
// =======================

$ch = curl_init($nbiUrl);

curl_setopt_array($ch, [
    CURLOPT_POST           => true,
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER     => [
        'Content-Type: application/json',
        'Accept: application/json',
    ],
    CURLOPT_POSTFIELDS     => json_encode($payload, JSON_UNESCAPED_SLASHES),

    // vSZ cert đang expired/self-signed thì để false.
    // Khi thay cert chuẩn có thể bật verify lại.
    CURLOPT_SSL_VERIFYPEER => false,
    CURLOPT_SSL_VERIFYHOST => false,

    CURLOPT_CONNECTTIMEOUT => 5,
    CURLOPT_TIMEOUT        => 10,
]);

$response = curl_exec($ch);

$curlNo   = curl_errno($ch);
$curlErr  = curl_error($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
$info     = curl_getinfo($ch);

curl_close($ch);

// =======================
// LOG DEBUG
// =======================

$logPayload = $payload;
$logPayload['RequestPassword'] = '***';

/*
file_put_contents(
    __DIR__ . '/nbi-login.log',
    date('c') .
    ' URL=' . $nbiUrl .
    ' HTTP=' . $httpCode .
    ' CURL_NO=' . $curlNo .
    ' CURL_ERR=' . $curlErr .
    ' INFO=' . json_encode($info, JSON_UNESCAPED_SLASHES) .
    ' PAYLOAD=' . json_encode($logPayload, JSON_UNESCAPED_SLASHES) .
    ' RESPONSE=' . $response .
    PHP_EOL,
    FILE_APPEND
);
*/

// =======================
// CHECK CURL RESULT
// =======================

if ($response === false || $curlNo !== 0 || $curlErr !== '' || $httpCode < 200 || $httpCode >= 300) {
    http_response_code(500);

    echo '<pre>';
    echo "NBI request failed\n";
    echo "HTTP: " . h($httpCode) . "\n";
    echo "CURL_NO: " . h($curlNo) . "\n";
    echo "CURL_ERR: " . h($curlErr) . "\n";
    echo "Response:\n" . h($response) . "\n";
    echo '</pre>';

    exit;
}

$data = json_decode($response, true);

$responseCode = isset($data['ResponseCode']) ? (int)$data['ResponseCode'] : 0;
$replyMessage = $data['ReplyMessage'] ?? '';

// vSZ có thể trả:
// 201 = Login succeeded
// 101 = Client authorized
$successCodes = [101, 201];

if (!in_array($responseCode, $successCodes, true)) {
    http_response_code(500);

    echo '<pre>';
    echo "NBI login not successful\n";
    echo "ResponseCode: " . h($responseCode) . "\n";
    echo "ReplyMessage: " . h($replyMessage) . "\n";
    echo "Full response:\n" . h($response) . "\n";
    echo '</pre>';

    exit;
}

// =======================
// SUCCESS PAGE
// =======================

header('Content-Type: text/html; charset=utf-8');
header('Cache-Control: no-store, no-cache, must-revalidate, max-age=0');
header('Pragma: no-cache');
?>
<!doctype html>
<html lang="vi">
<head>
    <meta charset="utf-8">
    <title>Connected</title>
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <style>
        * { box-sizing: border-box; }
        body {
            margin: 0;
            min-height: 100vh;
            font-family: Arial, sans-serif;
            background: #111827;
            color: white;
            display: flex;
            align-items: center;
            justify-content: center;
            text-align: center;
        }
        .box {
            width: 90%;
            max-width: 360px;
            background: #ffffff;
            color: #111827;
            padding: 28px;
            border-radius: 16px;
            box-shadow: 0 20px 50px rgba(0,0,0,.35);
        }
        .check {
            width: 64px;
            height: 64px;
            margin: 0 auto 16px;
            border-radius: 50%;
            background: #16a34a;
            color: #ffffff;
            display: flex;
            align-items: center;
            justify-content: center;
            font-size: 36px;
            font-weight: bold;
        }
        h2 { margin: 0 0 10px; font-size: 24px; }
        p { margin: 0; color: #4b5563; line-height: 1.5; }
        .small { margin-top: 12px; font-size: 12px; color: #6b7280; }
        .dots span {
            animation: bounce 1.2s infinite ease-in-out;
            display: inline-block;
        }
        .dots span:nth-child(2) { animation-delay: 0.2s; }
        .dots span:nth-child(3) { animation-delay: 0.4s; }
        @keyframes bounce {
            0%, 80%, 100% { transform: translateY(0); opacity: 0.4; }
            40% { transform: translateY(-5px); opacity: 1; }
        }
        #preload-frame {
            position: absolute;
            width: 1px;
            height: 1px;
            opacity: 0;
            pointer-events: none;
            border: none;
        }
    </style>
</head>
<body>
    <div class="box">
        <div class="check">✓</div>
        <h2>Connected</h2>
        <p>Bạn đã kết nối Internet.</p>
        <div class="small dots">Đang chuyển hướng<span>.</span><span>.</span><span>.</span></div>
    </div>

    <iframe id="preload-frame"></iframe>

<script>
    const TARGET = 'https://tamanhhospital.vn/vu-tru-robot/?utm_campaign=bvta_longbien_wifi-sitelongbien_vutrurobot2026_he-thong-may-moc_traffic&utm_source=wifi-sitelongbien&utm_medium=wifi-marketing&utm_content=robot-traffic&utm_term=mass';
    const MIN_DISPLAY_MS = 4000; // minimum time to show this screen

    const start = Date.now();
    let iframeReady = false;
    let timerDone = false;

    function tryRedirect() {
        if (iframeReady || timerDone) {
            window.location.replace(TARGET);
        }
    }

    // Start preloading in hidden iframe
    const frame = document.getElementById('preload-frame');
    frame.src = TARGET;
    frame.onload = function () {
        iframeReady = true;
        tryRedirect();
    };
    frame.onerror = function () {
        // If iframe fails (e.g. X-Frame-Options blocks it), redirect anyway
        iframeReady = true;
        tryRedirect();
    };

    // Minimum display timer
    setTimeout(function () {
        timerDone = true;
        tryRedirect();
    }, MIN_DISPLAY_MS);
</script>
</body>
</html>
<?php
exit;

index.php cho wifi marketing Ruckus

<?php
function h($s) {
    return htmlspecialchars((string)$s, ENT_QUOTES, 'UTF-8');
}

function getCleanParams(): array {
    $query = parse_url($_SERVER['REQUEST_URI'] ?? '', PHP_URL_QUERY) ?? '';
    $query = html_entity_decode($query, ENT_QUOTES | ENT_HTML5, 'UTF-8');

    $params = [];
    parse_str($query, $params);

    $clean = [];
    foreach ($params as $key => $value) {
        $key = preg_replace('/^amp;/', '', (string)$key);
        $clean[$key] = $value;
    }

    return $clean;
}

$params = getCleanParams();
?>
<!doctype html>
<html lang="vi">
<head>
    <meta charset="utf-8">
    <title>Guest Wi-Fi</title>
    <meta name="viewport" content="width=device-width, initial-scale=1">

    <style>
        * {
            box-sizing: border-box;
        }

        body {
            margin: 0;
            height: 100vh;
            font-family: Arial, sans-serif;
            background: #111827;
            display: flex;
            align-items: center;
            justify-content: center;
        }

        .box {
            width: 90%;
            max-width: 420px;
            background: #ffffff;
            padding: 0;
            border-radius: 16px;
            text-align: center;
            box-shadow: 0 20px 50px rgba(0, 0, 0, .35);
            overflow: hidden;
        }

        .slider {
            position: relative;
            width: 100%;
            aspect-ratio: 9 / 16;
            overflow: hidden;
            background: #e5e7eb;
        }

        .slide {
            position: absolute;
            inset: 0;
            width: 100%;
            height: 100%;
            object-fit: contain;
            opacity: 0;
            transition: opacity 600ms ease-in-out;
        }

        .slide.active {
            opacity: 1;
        }

        .dots {
            position: absolute;
            left: 0;
            right: 0;
            bottom: 10px;
            display: flex;
            justify-content: center;
            gap: 6px;
        }

        .dot {
            width: 8px;
            height: 8px;
            border-radius: 50%;
            background: rgba(255, 255, 255, .55);
        }

        .dot.active {
            background: #ffffff;
        }

        .content {
            padding: 24px;
            background: #111111;
        }

        button {
            width: 100%;
            padding: 14px;
            border: 0;
            border-radius: 10px;
            background: #2563eb;
            color: #ffffff;
            font-size: 17px;
            font-weight: bold;
            cursor: pointer;
        }

        button:hover {
            background: #1d4ed8;
        }

        button:disabled {
            background: #9ca3af;
            cursor: not-allowed;
        }
    </style>
</head>
<body>
    <div class="box">
        <div class="slider">
            <img class="slide active" src="images/1.jpg" alt="Slide 1">
            <img class="slide" src="images/2.jpg" alt="Slide 2">

            <div class="dots">
                <span class="dot active"></span>
                <span class="dot"></span>
            </div>
        </div>

        <div class="content">
            <form method="post" action="login.php" id="connectForm">
                <?php foreach ($params as $key => $value): ?>
                    <input type="hidden" name="<?= h($key) ?>" value="<?= h($value) ?>">
                <?php endforeach; ?>

                <button type="submit" id="connectBtn">Kết nối Internet</button>
            </form>
        </div>
    </div>

    <script>
        const slides = document.querySelectorAll('.slide');
        const dots = document.querySelectorAll('.dot');
        let currentSlide = 0;

        function showSlide(index) {
            slides.forEach(function (slide, i) {
                slide.classList.toggle('active', i === index);
            });
            dots.forEach(function (dot, i) {
                dot.classList.toggle('active', i === index);
            });
        }

        if (slides.length > 1) {
            setInterval(function () {
                currentSlide = (currentSlide + 1) % slides.length;
                showSlide(currentSlide);
            }, 2000);
        }

        document.getElementById('connectForm').addEventListener('submit', function () {
            const btn = document.getElementById('connectBtn');
            btn.innerText = 'Đang kết nối...';
            btn.disabled = true;
        });
    </script>
</body>
</html>

Backup file local sang shard folder

Tạo VBscript: 

Set WshShell = CreateObject("WScript.Shell")

cmd = "robocopy ""Source-path"" ""Target=path"" /E /XO /Z /FFT /R:2 /W:5 /MT:16"

WshShell.Run cmd, 0, True 

Tạo task schdule chạy mỗi 60 phút:

schtasks /Create /TN "ZaloData Robocopy" /SC MINUTE /MO 60 /TR "wscript.exe \"Script-path\DataBackup.vbs\"" /F

Xóa folder có nhiều cấp con - path quá dài

Thực hiện tạo 1 folder trống rồi robocopy kiểu mirror tới folder bị lỗi:

 robocopy C:\Empty "D:\Backup path" /MIR 

Sau đó sẽ xóa được 

Import MAC-IP reservation vào DHCP server

# trước khi chạy: kiểm tra csv dạng UTF-8, check duplicate MAC
# ghi đè lên các bản ghi đã có nếu trùng MAC
# Xóa các reserve có trên DHCP nhưng không có trong file. Không xóa các bản ghi DHCP bình thường
# Ghi log ra file CSV kèm thời gian, action
# ================= CONFIG =================
$ScopeId = "x.x.x.x"
$CsvPath = "C:\bat\Reserve-MAC-IP.csv"
$LogPath = "C:\bat\Dhcp-Reserve-Log.csv"

$rawCsv = Import-Csv -Path $CsvPath -Encoding UTF8

# ================= FUNCTION =================

# Format MAC về aa-bb-cc-dd-ee-ff
function Format-Mac($mac) {
    $mac = $mac -replace "[:-]", ""
    return ($mac.ToLower() -split '(.{2})' | Where-Object { $_ }) -join "-"
}

function Write-Log($mac, $ip, $desc, $action) {

    $time = Get-Date -Format "yyyy-MM-dd HH:mm:ss"

    $logObj = [PSCustomObject]@{
        "MAC"         = $mac
        "IP"          = $ip
        "Description" = $desc
        "Action"      = $action
        "Time"        = $time
    }

    Write-Host ("[{0}] {1} | {2} | {3} | {4}" -f $time, $action, $mac, $ip, $desc)

    if (!(Test-Path $LogPath)) {
        $logObj | Export-Csv -Path $LogPath -NoTypeInformation -Encoding UTF8
    } else {
        $logObj | Export-Csv -Path $LogPath -NoTypeInformation -Append -Encoding UTF8
    }
}

# ================= NORMALIZE CSV =================
$csvData = $rawCsv | ForEach-Object {
    [PSCustomObject]@{
        MAC         = (Format-Mac $_.'MAC validate')
        IP          = $_.'IP Reserve'
        Description = $_.Description
    }
}

# ================= CHECK DUPLICATE MAC =================
$dupMac = $csvData | Group-Object MAC | Where-Object { $_.Count -gt 1 }

foreach ($d in $dupMac) {
    Write-Host ("WARNING: DUPLICATE MAC {0} ({1} records) -> giữ dòng cuối" -f $d.Name, $d.Count) -ForegroundColor Yellow
}

# ================= REMOVE DUPLICATE (GIỮ DÒNG CUỐI) =================
$csvData = $csvData |
    Group-Object MAC |
    ForEach-Object { $_.Group[-1] }

# ================= GET EXISTING =================
$existingReservations = Get-DhcpServerv4Reservation -ScopeId $ScopeId

$existingByMac = @{}
foreach ($res in $existingReservations) {
    $existingByMac[$res.ClientId.ToLower()] = $res
}

$csvMacSet = @{}

# ================= ADD / OVERWRITE =================
foreach ($row in $csvData) {

    $mac  = $row.MAC
    $ip   = $row.IP
    $desc = $row.Description

    $csvMacSet[$mac.ToLower()] = $true

    if ($existingByMac.ContainsKey($mac.ToLower())) {

        try {
            Remove-DhcpServerv4Reservation -ScopeId $ScopeId -ClientId $mac -Confirm:$false -ErrorAction Stop
            Add-DhcpServerv4Reservation -ScopeId $ScopeId -IPAddress $ip -ClientId $mac -Description $desc -ErrorAction Stop

            Write-Log $mac $ip $desc "Overwrite"
        } catch {
            Write-Host "ERROR Overwrite: $mac" -ForegroundColor Red
        }

    } else {

        try {
            Add-DhcpServerv4Reservation -ScopeId $ScopeId -IPAddress $ip -ClientId $mac -Description $desc -ErrorAction Stop

            Write-Log $mac $ip $desc "Add"
        } catch {
            Write-Host "ERROR Add: $mac" -ForegroundColor Red
        }
    }
}

# ================= DELETE =================
foreach ($res in $existingReservations) {

    $mac = $res.ClientId.ToLower()

    if (-not $csvMacSet.ContainsKey($mac)) {
        try {
            Remove-DhcpServerv4Reservation -ScopeId $ScopeId -ClientId $res.ClientId -Confirm:$false -ErrorAction Stop

            Write-Log $res.ClientId $res.IPAddress $res.Description "Delete"
        } catch {
            Write-Host "ERROR Delete: $mac" -ForegroundColor Red
        }
    }
}

Get cert SSL cho tên miền DDNS

Sử dụng NAS Synology (xpen)

Sử dụng domain free qua ddns

Truy cập domain => lỗi cert

Phương án xử lý:

- Sử dụng ddns của Synology => cần có tài khoản Syno mới tạo đc domain và get cert, xpen thì ko login tài khoản Synology đc

- Sử dụng ddns bên ngoài như noip => domain riêng, quá trình get cert cần thông từ internet tới port 80 trên NAS:

  •     Cần NAT port 80 vào NAS để cấp qua HTTP-01
  •     Bị ISP block port 80 => không thể  dùng HTTP-01, chỉ còn cách dùng DNS-01, nhưng DNS-01 yêu cầu tạo TXT record cho tên miền. Dịch vụ DDNS không cho phép tạo => fail

Hiện chưa có cách gì. Hướng xử lý có thể nghĩ tới: 

- Ôm cục NAS tới mạng khác cho phép mở port 80, chờ ddns update IP mới rồi thực hiện get cert

- Tìm cách login đc tài khoản Synology lên NAS => tạo domain theo Syno

Dựng external captive portal cho hệ thống Ruckus

Cấu hình SSID:
Bật DNS Google hoặc DNS public khác
Authentication type: Hotspot (WISPr)
Hotspot (WISPr) Portal: theo cấu hình portal đã tạo
Authentication server: bật Use Controller as proxy và chọn Always Accept
Tạo tài khoản Northbound Interface nbi-acc để portal xác thực với vSZ
Add IP của MKT-server vào Walled garden

Mở rule:
- tạm đi internet cho Rocky để cài package
- Guest tới MKT-server port http 
- MKT-server tới vSZ port 9443
  

Dựng VM Rocky

Chạy playbook new_server, và:

dnf install -y nginx php php-fpm php-cli php-curl php-json policycoreutils-python-utils firewalld
systemctl enable --now nginx
systemctl enable --now php-fpm
systemctl enable --now firewalld
setsebool -P httpd_can_network_connect 1
firewall-cmd --permanent --add-service=http
firewall-cmd --reload

Lấy serial MSA 1040

 SSH vào thiết bị

Chạy Show configuration

Tìm dòng SKU để lấy serial:

SKU
---
Part Number: E7W00A
Serial Number: xxx
Revision: F
 

Điều chỉnh roaming factor trên hệ thống Ruckus

Roaming factor trên hệ thống Ruckus sử dụng để điều chỉnh mức độ nhạy khi client di chuyển giữa các AP. Tương ứng có các mức từ 1 đến 10: mức 1 - client sẽ "bám" AP nhất, mức 10 sẽ dễ đổi AP nhất.

Ví dụ cài đặt để set mức 3: vào console của controller:

config
zone "tên zone" => áp dụng cho zone
wlan "tên SSID" => áp dụng cho SSID
roam => bật smart roaming
roam-factor 2.4g 3 => áp dụng cho sóng 2.4Ghz
roam-factor 5g 3 => áp dụng cho sóng 5Ghz

Như vậy khi thay đổi/phát sinh zone và SSID cũng sẽ phải chạy lại lệnh mới để có tác dụng 

Kiểm tra lại config:

show running-config zone "tên zone" wlan "tên SSID"

  

Export root CA từ CA server

CA server riêng, chạy Windows core, cấp phát cert cho AD và các client pc

Sử dụng windows server khác, kết nối remote vào CA server, chuột phải và kết nối vào CA:

 

Login vào thẳng exec mode cho switch Cisco chạy aaa new-model

 Cần thêm config:

aaa new-model
!
!
aaa authentication login default local
aaa authorization exec default local
 

và:

line vty 0 15
login authentication default
 

Thao tác với disk iscsi trên windows core

Lấy thông tin disk đã map (powershell):

 Get-IscsiSession | Get-Disk | Get-Partition | ft DiskNumber, DriveLetter

Get-IscsiSession | Get-Disk | Get-Partition | Select DiskNumber, PartitionNumber, DriveLetter

Get-IscsiSession | Get-Disk | Get-Partition | Get-Volume | Select DriveLetter, FileSystemLabel, FileSystem, SizeRemaining, Size
  

Online lại disk:

- Diskpart (cmd) > select disk

- Online disk 

- sửa readonly: Attributes disk clear readonly

 

Gỡ license 365 cho hàng loạt username

 # Gỡ license cho hàng loạt username từ file csv, có 1 cột UserToDisable
$csvPath = "D:\OneDrive\Downloads\Documents\ReportM365\UserToDisable.csv"
$users = Import-Csv $csvPath

$domain = "@tamanhhospital.vn"

# License cần remove
$targetLicenses = @(
    "4b585984-651b-448a-9e53-3b10f069cf7f", # Microsoft 365 F3
    "f8ced641-8e17-4dc5-b014-f5a2d53f6ac8", # Office 365 E1
    "46c3a859-c90d-40b3-9551-6178a48d5c18", # Office 365 E3
    "3ab6abff-666f-4424-bfb7-f0bc274ec7bc", # Microsoft Teams Essentials
    "7e31c0d9-9551-471d-836f-32ee72be4a01" # Microsoft Teams Enterprise (Teams add-on)
)

foreach ($user in $users) {
    try {
        # Ghép domain vào username
        $userId = $user.UserToDisable.Trim() + $domain

        # Get license hiện tại
        $currentLicenses = (Get-MgUser -UserId $userId -Property AssignedLicenses).AssignedLicenses.SkuId

        # Lọc license cần remove
        $removeLicenses = $targetLicenses | Where-Object { $_ -in $currentLicenses }

        if ($removeLicenses.Count -gt 0) {
            Set-MgUserLicense -UserId $userId -AddLicenses @() -RemoveLicenses $removeLicenses
            Write-Host "$userId - Removed license" -ForegroundColor Green
        }
        else {
            Write-Host "$userId - No target license" -ForegroundColor Yellow
        }
    }
    catch {
        Write-Host "$($user.UserToDisable) - ERROR: $($_.Exception.Message)" -ForegroundColor Red
    }
}

Tăng dung lượng cho Datastore

    Tăng (resize) cho volume trên SAN
    vSphere => Rescan storage
    vSphere => chọn storage > Action > Increase Storage Capacity > done
    check lại dung lượng đã tăng đủ

Upgrade cho ManageEngine theo lộ trình

Tải file update từ hãng, theo phiên bản đang sử dụng 

 https://www.manageengine.com/products/service-desk/on-premises/migration-sequence.html

Stop service:

net stop "ManageEngine ServiceDesk Plus" 

Chạy tool update: 

C:\ManageEngine\ServiceDeskPlus\bin\UpdateManager.bat

Làm theo hướng dẫn để backup rồi cài. Thời gian backup có thể khá lâu tùy lượng data đã có

Các bản archive: https://archives.manageengine.com/service-desk/
 

 

Update cho Windows Server Core

Import-Module PSWindowsUpdate Install-WindowsUpdate -MicrosoftUpdate -AcceptAll -AutoReboot

Reset time cho remote desktop

# Remove-RDSTimebomb.ps1
# Remove registry value start with "L$RTMTIMEBOMB" in key GracePeriod
# Require: run as Administrator

$ErrorActionPreference = 'SilentlyContinue'
$path = "HKLM:\SYSTEM\CurrentControlSet\Control\Terminal Server\RCM\GracePeriod"
if (Test-Path $path) {
    $values = (Get-Item $path).GetValueNames() | Where-Object { $_ -like "L$RTMTIMEBOMB*" }
    foreach ($v in $values) {
        try {
            Remove-ItemProperty -Path $path -Name $v -Force
            Write-Output ("{0} - Removed: {1} in {2}" -f (Get-Date -Format 'yyyy-MM-dd HH:mm:ss'), $v, $path)
        } catch {
            Write-Output ("{0} - Error {1}: {2}" -f (Get-Date -Format 'yyyy-MM-dd HH:mm:ss'), $v, ${_}.Exception.Message)
        }
    }
} else {
    Write-Output ("{0} - Not found key GracePeriod." -f (Get-Date -Format 'yyyy-MM-dd HH:mm:ss'))
}
Write-Output "Success."

Cấu hình syslog cho SAN HP MSA 1040

 Xem thông số hiện tại:

# show syslog-parameters
Syslog Parameters
-----------------
Syslog Host IP: 0.0.0.0
Syslog Notification Level: none
Syslog Host Port: 0

Cấu hình thông số:

set syslog-parameters   [host-ip <IP-address>]   [host-port <port-number>]   notification-level crit|error|warn|info|none

Để xem hướng dẫn: thêm help ở đầu dòng 

login.php cho wifi marketing Ruckus

 <?php function h($s) {     return htmlspecialchars((string)$s, ENT_QUOTES, 'UTF-8'); } function cleanParams(array $input): array...