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

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

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

🔧 核心目标

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

✅ 适用环境:Windows / Linux / macOS(PowerShell 7+)
✅ 输出形式:独立脚本 + 模块化结构 + 用户友好交互


🎯 三大实战项目概览

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

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

💡 需求

生成一个 HTML 报告,展示:

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

✅ 实现代码(Get-SystemHealthReport.ps1

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

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

# 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. 以最小权限账户运行

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

# 重启打印服务
$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
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值