[Powershell 入门教程]第10天:综合项目实战与进阶

这是入门教程的最后一篇,希望读者可以实际用起来,实现逐步从入门到精通的全过程。

📅 第10天:综合项目实战与进阶

🔧 核心目标

将前9天所学(函数、REST API、作业、错误处理、JSON、模块化等)融会贯通,构建 可落地、可扩展、跨平台 的自动化工具。

✅ 适用环境:Windows / Linux / macOS(PowerShell 7+)

✅ 输出形式:独立脚本 + 模块化结构 + 用户友好交互


🎯 三大实战项目概览

项目 技术栈 应用场景
1. 自动化系统健康仪表盘 Get-Process, Get-Volume, Test-Connection, ConvertTo-Html 本地/远程服务器状态可视化
2. 跨平台服务检查器 Invoke-RestMethod, Start-ThreadJob, 参数验证 微服务/API 健康监测(HTTP/S)
3. RESTful 管理代理(Mock Agent) Register-ObjectEvent, New-PSSessionConfiguration, 自定义 REST 接口 安全接收外部指令并执行本地操作

🛠️ 项目1:自动化系统健康仪表盘

💡 需求

生成一个 HTML 报告,展示:

  • CPU 使用率 Top 5 进程
  • 内存使用率
  • 磁盘剩余空间(所有卷)
  • 网络连通性(到关键服务如 DNS、网关)
  • 最后更新时间

✅ 实现代码(Get-SystemHealthReport.ps1

cs 复制代码
function Get-SystemHealthReport {
    [CmdletBinding()]
    param(
        [string]$OutputPath = "./system_health_$(Get-Date -Format 'yyyyMMdd_HHmm').html"
    )

    # 获取数据
    $cpuTop = Get-Process | Sort-Object CPU -Descending | Select-Object -First 5 Name, CPU
    $memUsage = [math]::Round((Get-CimInstance Win32_OperatingSystem).FreePhysicalMemory / 1MB, 2)
    $totalMem = [math]::Round((Get-CimInstance Win32_ComputerSystem).TotalPhysicalMemory / 1GB, 2)
    $diskInfo = Get-Volume | Where-Object DriveLetter | Select-Object DriveLetter, 
        @{Name="FreeGB"; Expression={[math]::Round($_.SizeRemaining / 1GB, 2)}},
        @{Name="TotalGB"; Expression={[math]::Round($_.Size / 1GB, 2)}}
    
    $networkTests = @(
        @{Target="8.8.8.8"; Status=(Test-Connection 8.8.8.8 -Count 1 -Quiet)}
        @{Target="gateway"; Status=(Test-Connection (Get-NetRoute 0.0.0.0).NextHop -Count 1 -Quiet -ErrorAction SilentlyContinue)}
    )

    # 构建 HTML
    $html = @"
<!DOCTYPE html>
<html>
<head><title>系统健康报告</title>
<style>
body { font-family: Arial; margin: 20px; }
table { border-collapse: collapse; width: 100%; }
th, td { border: 1px solid #ddd; padding: 8px; text-align: left; }
th { background-color: #f2f2f2; }
.green { color: green; }
.red { color: red; }
</style>
</head>
<body>
<h1>📊 系统健康仪表盘</h1>
<p>生成时间: $(Get-Date)</p>

<h2>🔥 CPU Top 5 进程</h2>
$($cpuTop | ConvertTo-Html -Fragment)

<h2>🧠 内存使用</h2>
<p>总内存: ${totalMem} GB | 可用: ${memUsage} GB</p>

<h2>💾 磁盘空间</h2>
$($diskInfo | ConvertTo-Html -Fragment)

<h2>🌐 网络连通性</h2>
<table>
<tr><th>目标</th><th>状态</th></tr>
$(
    foreach ($test in $networkTests) {
        $color = if ($test.Status) { "green" } else { "red" }
        $statusText = if ($test.Status) { "✅ 在线" } else { "❌ 离线" }
        "<tr><td>$($test.Target)</td><td class='$color'>$statusText</td></tr>"
    }
)
</table>
</body>
</html>
"@

    $html | Out-File -FilePath $OutputPath -Encoding UTF8
    Write-Host "✅ 报告已生成: $OutputPath" -ForegroundColor Green
    if ($IsWindows) { Start-Process $OutputPath }
}

🔍 技术亮点

  • 跨平台兼容 :使用 Get-CimInstance(Windows)或可替换为 free(Linux)
  • HTML 内嵌 CSS:无需外部依赖,直接浏览器打开
  • 自动打开报告Start-Process(Windows)/ open(macOS)/ xdg-open(Linux)可进一步适配

🌐 项目2:跨平台服务检查器

💡 需求

并发检测多个 HTTP 服务状态(支持 Basic Auth、自定义 Header),输出表格并高亮异常。

✅ 实现代码(Test-ServiceHealth.ps1

cs 复制代码
function Test-ServiceHealth {
    [CmdletBinding()]
    param(
        [Parameter(Mandatory)]
        [hashtable[]]$Services,  # 示例: @{Url="https://api.example.com"; Auth="user:pass"}
        [int]$TimeoutSec = 10,
        [int]$MaxConcurrency = 5
    )

    # 安装 ThreadJob(如未安装)
    if (-not (Get-Module ThreadJob -ListAvailable)) {
        Install-Module ThreadJob -Scope CurrentUser -Force
    }

    $jobs = foreach ($svc in $Services) {
        Start-ThreadJob -ThrottleLimit $MaxConcurrency -ScriptBlock {
            param($url, $auth, $timeout)
            $headers = @{}
            if ($auth) {
                $bytes = [System.Text.Encoding]::ASCII.GetBytes($auth)
                $base64 = [Convert]::ToBase64String($bytes)
                $headers.Authorization = "Basic $base64"
            }

            $sw = [System.Diagnostics.Stopwatch]::StartNew()
            try {
                $response = Invoke-RestMethod -Uri $url -Headers $headers -TimeoutSec $timeout -UseBasicParsing
                $status = "OK"
                $statusCode = 200
            } catch {
                $status = "FAIL"
                $statusCode = $_.Exception.Response?.StatusCode?.value__ -as [int] -or 0
            }
            $sw.Stop()

            [PSCustomObject]@{
                Service = $url
                Status  = $status
                Code    = $statusCode
                Latency = $sw.ElapsedMilliseconds
                Time    = Get-Date
            }
        } -ArgumentList $svc.Url, $svc.Auth, $TimeoutSec
    }

    $results = $jobs | Wait-Job | Receive-Job
    $jobs | Remove-Job

    # 彩色输出
    $results | ForEach-Object {
        $color = if ($_.Status -eq "OK") { "Green" } else { "Red" }
        Write-Host "$($_.Service) | $($_.Status) | Code: $($_.Code) | Latency: $($_.Latency)ms" -ForegroundColor $color
    }

    return $results
}

# 使用示例
$myServices = @(
    @{Url = "https://httpbin.org/status/200"},
    @{Url = "https://httpbin.org/status/500"},
    @{Url = "https://api.github.com/rate_limit"; Auth = "user:token"} # 如需认证
)

Test-ServiceHealth -Services $myServices -MaxConcurrency 3

🔍 技术亮点

  • Start-ThreadJob:轻量级并发,避免传统 Job 开销
  • Basic Auth 支持:动态构造 Authorization Header
  • 结构化输出 :返回对象数组,便于后续 Export-Csv 或告警集成

🤖 项目3:RESTful 管理代理(安全执行本地命令)

⚠️ 仅限受控内网环境!需严格权限控制

💡 需求

启动一个本地 HTTP 服务,接收 JSON 指令(如 {"action": "restart-service", "service": "spooler"}),执行对应 PowerShell 命令并返回结果。

✅ 实现思路(简化版,基于 HttpListener

cs 复制代码
# rest-agent.ps1
function Start-ManagementAgent {
    param([int]$Port = 8080)

    $listener = New-Object System.Net.HttpListener
    $listener.Prefixes.Add("http://localhost:$Port/")
    $listener.Start()
    Write-Host "🚀 管理代理已启动: http://localhost:$Port/" -ForegroundColor Cyan

    while ($listener.IsListening) {
        $context = $listener.GetContext()
        $request = $context.Request
        $response = $context.Response

        if ($request.HttpMethod -ne "POST") {
            $msg = "仅支持 POST"
            $buffer = [System.Text.Encoding]::UTF8.GetBytes($msg)
            $response.StatusCode = 405
            $response.OutputStream.Write($buffer, 0, $buffer.Length)
            $response.Close()
            continue
        }

        # 读取请求体
        $reader = New-Object System.IO.StreamReader($request.InputStream)
        $rawBody = $reader.ReadToEnd()
        $reader.Dispose()

        try {
            $payload = $rawBody | ConvertFrom-Json
            $action = $payload.action

            switch ($action) {
                "get-process" {
                    $result = Get-Process | Select-Object Name, Id, CPU | ConvertTo-Json
                }
                "restart-service" {
                    $svc = $payload.service
                    Restart-Service $svc -PassThru | Out-Null
                    $result = @{ status = "success"; service = $svc } | ConvertTo-Json
                }
                default {
                    throw "不支持的操作: $action"
                }
            }

            $buffer = [System.Text.Encoding]::UTF8.GetBytes($result)
            $response.ContentType = "application/json"
            $response.StatusCode = 200
        } catch {
            $err = @{ error = $_.Exception.Message } | ConvertTo-Json
            $buffer = [System.Text.Encoding]::UTF8.GetBytes($err)
            $response.StatusCode = 500
        }

        $response.OutputStream.Write($buffer, 0, $buffer.Length)
        $response.Close()
    }
}

# 启动代理(后台运行)
Start-ManagementAgent -Port 8080

🔒 安全加固建议(生产环境必须):

  1. 绑定到 127.0.0.1(禁止外网访问)
  2. 添加 API Token 认证 (检查 Header 中 X-API-Key
  3. 白名单操作(只允许预定义的 action)
  4. 以最小权限账户运行

🧪 测试命令(另一终端):

cs 复制代码
# 重启打印服务
$body = @{ action = "restart-service"; service = "spooler" } | ConvertTo-Json
Invoke-RestMethod -Uri "http://localhost:8080/" -Method Post -Body $body -ContentType "application/json"

# 获取进程列表
Invoke-RestMethod -Uri "http://localhost:8080/" -Method Post -Body '{"action":"get-process"}' -ContentType "application/json"

🧠 第10天能力升华

能力维度 体现
工程化思维 模块化、参数化、错误隔离
跨平台意识 避免 Windows 专属 Cmdlet(如用 Get-CimInstance → 可替换)
安全第一 输入验证、最小权限、网络隔离
用户体验 彩色输出、HTML 报告、进度反馈
可扩展性 函数设计支持管道、导出 CSV、集成监控系统

🚀 课后挑战(选做)

  1. 仪表盘 改为 Web 服务(用 Start-ManagementAgent 返回 HTML)
  2. 服务检查器 添加 Slack/邮件告警(当状态 ≠ 200)
  3. 管理代理 封装为 Windows Service(使用 nssm.exe
相关推荐
LAM LAB2 天前
【shell】win10 Powershell字体美化
powershell
humors2214 天前
AI工具合集,不定期更新
人工智能·windows·ai·工具·powershell·deepseek
fengyehongWorld11 天前
Powershell 自动安装Excel自定义标签页,开启宏
powershell
西西弗Sisyphus13 天前
PowerShell 配置为启动时自动激活 Conda 环境
conda·powershell
夫唯不争,故无尤也1 个月前
curl与Invoke-RestMethod核心区别
后端·fastapi·powershell·curl
bu_shuo1 个月前
Windows电脑使用VSCode远程控制Windows主机方法记录
windows·vscode·ssh·powershell
Moshow郑锴2 个月前
WindowsRemoteAdmin(超级马里奥像素版)专为无远程登录桌面系统打造的便携式管理工具
java·powershell·远程控制·远程桌面·系统运维
超级大福宝2 个月前
PowerShell 实现类似 Bash 的补全行为
bash·powershell
小雪_Snow2 个月前
PowerShell 版本升级教程
powershell
Whoami!2 个月前
⓫⁄₅ ⟦ OSCP ⬖ 研记 ⟧ Windows权限提升 ➱ 利用PowerShell获取敏感信息
网络安全·信息安全·powershell·windows日志