PowerShell 技能连载 - 基础设施即代码实践

在现代IT运维领域,基础设施即代码(Infrastructure as Code, IaC)已成为标准实践。本文将介绍如何使用PowerShell实现高效的IaC解决方案。

首先,让我们创建一个基础环境配置定义函数:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
# 创建环境配置定义函数
function New-InfrastructureDefinition {
param(
[Parameter(Mandatory)]
[string]$EnvironmentName,

[Parameter(Mandatory)]
[string]$OutputPath,

[string]$Description = "",

[ValidateSet("Development", "Testing", "Staging", "Production")]
[string]$EnvironmentType = "Development",

[switch]$Force
)

try {
# 创建基础环境配置对象
$infrastructureDefinition = [PSCustomObject]@{
EnvironmentName = $EnvironmentName
EnvironmentType = $EnvironmentType
Description = $Description
CreatedBy = $env:USERNAME
CreatedOn = Get-Date
Version = "1.0"
Resources = @{
VirtualMachines = @()
NetworkResources = @()
StorageResources = @()
SecurityResources = @()
DatabaseResources = @()
ApplicationResources = @()
}
Dependencies = @{}
DeploymentOrder = @()
State = "Draft"
Metadata = @{}
}

# 创建JSON定义文件
$definitionFile = Join-Path -Path $OutputPath -ChildPath "$EnvironmentName.json"

if ((Test-Path -Path $definitionFile) -and (-not $Force)) {
throw "定义文件 '$definitionFile' 已存在。使用 -Force 参数覆盖现有文件。"
}

# 创建输出目录(如果不存在)
if (-not (Test-Path -Path $OutputPath)) {
New-Item -Path $OutputPath -ItemType Directory -Force | Out-Null
}

# 保存定义
$infrastructureDefinition | ConvertTo-Json -Depth 10 | Out-File -FilePath $definitionFile -Encoding UTF8

Write-Host "已创建基础设施定义: $definitionFile" -ForegroundColor Green
return $infrastructureDefinition
}
catch {
Write-Error "创建基础设施定义时出错: $_"
}
}

接下来,添加虚拟机资源定义:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
# 添加虚拟机资源定义
function Add-VMResource {
param(
[Parameter(Mandatory, ValueFromPipeline)]
[PSObject]$InfrastructureDefinition,

[Parameter(Mandatory)]
[string]$VMName,

[Parameter(Mandatory)]
[string]$Size,

[string]$OSType = "Windows",

[string]$OSVersion = "2022-Datacenter",

[string]$NetworkName,

[string]$SubnetName,

[hashtable]$Tags = @{},

[string[]]$DependsOn = @(),

[hashtable]$Properties = @{},

[string]$OutputPath
)

process {
try {
# 创建VM定义
$vmResource = [PSCustomObject]@{
Name = $VMName
ResourceType = "VirtualMachine"
Size = $Size
OSType = $OSType
OSVersion = $OSVersion
NetworkName = $NetworkName
SubnetName = $SubnetName
Tags = $Tags
Properties = $Properties
DependsOn = $DependsOn
ResourceId = [guid]::NewGuid().ToString()
CreatedOn = Get-Date
}

# 添加到定义中
$InfrastructureDefinition.Resources.VirtualMachines += $vmResource

# 添加依赖关系
foreach ($dependency in $DependsOn) {
if (-not $InfrastructureDefinition.Dependencies.ContainsKey($VMName)) {
$InfrastructureDefinition.Dependencies[$VMName] = @()
}
$InfrastructureDefinition.Dependencies[$VMName] += $dependency
}

# 如果提供了输出路径,更新定义文件
if ($OutputPath) {
$definitionFile = Join-Path -Path $OutputPath -ChildPath "$($InfrastructureDefinition.EnvironmentName).json"
$InfrastructureDefinition | ConvertTo-Json -Depth 10 | Out-File -FilePath $definitionFile -Encoding UTF8
Write-Host "已更新基础设施定义: $definitionFile" -ForegroundColor Green
}

return $InfrastructureDefinition
}
catch {
Write-Error "添加虚拟机资源定义时出错: $_"
}
}
}

添加网络资源定义:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
# 添加网络资源定义
function Add-NetworkResource {
param(
[Parameter(Mandatory, ValueFromPipeline)]
[PSObject]$InfrastructureDefinition,

[Parameter(Mandatory)]
[string]$NetworkName,

[Parameter(Mandatory)]
[string]$AddressSpace,

[Parameter(Mandatory)]
[PSObject[]]$Subnets,

[bool]$EnableDnsSupport = $true,

[hashtable]$Tags = @{},

[string[]]$DependsOn = @(),

[hashtable]$Properties = @{},

[string]$OutputPath
)

process {
try {
# 创建网络定义
$networkResource = [PSCustomObject]@{
Name = $NetworkName
ResourceType = "VirtualNetwork"
AddressSpace = $AddressSpace
Subnets = $Subnets
EnableDnsSupport = $EnableDnsSupport
Tags = $Tags
Properties = $Properties
DependsOn = $DependsOn
ResourceId = [guid]::NewGuid().ToString()
CreatedOn = Get-Date
}

# 添加到定义中
$InfrastructureDefinition.Resources.NetworkResources += $networkResource

# 添加依赖关系
foreach ($dependency in $DependsOn) {
if (-not $InfrastructureDefinition.Dependencies.ContainsKey($NetworkName)) {
$InfrastructureDefinition.Dependencies[$NetworkName] = @()
}
$InfrastructureDefinition.Dependencies[$NetworkName] += $dependency
}

# 如果提供了输出路径,更新定义文件
if ($OutputPath) {
$definitionFile = Join-Path -Path $OutputPath -ChildPath "$($InfrastructureDefinition.EnvironmentName).json"
$InfrastructureDefinition | ConvertTo-Json -Depth 10 | Out-File -FilePath $definitionFile -Encoding UTF8
Write-Host "已更新基础设施定义: $definitionFile" -ForegroundColor Green
}

return $InfrastructureDefinition
}
catch {
Write-Error "添加网络资源定义时出错: $_"
}
}
}

生成部署顺序:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
# 生成资源部署顺序
function Set-DeploymentOrder {
param(
[Parameter(Mandatory, ValueFromPipeline)]
[PSObject]$InfrastructureDefinition,

[switch]$Validate,

[string]$OutputPath
)

process {
try {
# 创建依赖图
$dependencyGraph = @{}
$resourceList = @()

# 收集所有资源
foreach ($vmResource in $InfrastructureDefinition.Resources.VirtualMachines) {
$resourceList += $vmResource.Name
$dependencyGraph[$vmResource.Name] = $vmResource.DependsOn
}

foreach ($netResource in $InfrastructureDefinition.Resources.NetworkResources) {
$resourceList += $netResource.Name
$dependencyGraph[$netResource.Name] = $netResource.DependsOn
}

# 添加其他资源类型...

# 检测循环依赖
$visited = @{}
$recStack = @{}

function Test-CyclicDependency {
param([string]$Node)

$visited[$Node] = $true
$recStack[$Node] = $true

foreach ($neighbor in $dependencyGraph[$Node]) {
if (-not $visited.ContainsKey($neighbor)) {
if (Test-CyclicDependency -Node $neighbor) {
return $true
}
}
elseif ($recStack.ContainsKey($neighbor)) {
return $true
}
}

$recStack.Remove($Node)
return $false
}

foreach ($resource in $resourceList) {
if (-not $visited.ContainsKey($resource)) {
if (Test-CyclicDependency -Node $resource) {
throw "检测到循环依赖关系。无法确定部署顺序。"
}
}
}

# 拓扑排序
$visited = @{}
$deploymentOrder = [System.Collections.ArrayList]::new()

function Sort-Topology {
param([string]$Node)

$visited[$Node] = $true

foreach ($neighbor in $dependencyGraph[$Node]) {
if (-not $visited.ContainsKey($neighbor)) {
Sort-Topology -Node $neighbor
}
}

$deploymentOrder.Add($Node) | Out-Null
}

foreach ($resource in $resourceList) {
if (-not $visited.ContainsKey($resource)) {
Sort-Topology -Node $resource
}
}

# 反转列表,因为我们需要先部署没有依赖的资源
[Array]::Reverse($deploymentOrder)

# 更新部署顺序
$InfrastructureDefinition.DeploymentOrder = $deploymentOrder

# 验证部署顺序
if ($Validate) {
Write-Host "验证部署顺序..." -ForegroundColor Yellow
$deploymentSet = @{}
$isValid = $true

foreach ($resource in $deploymentOrder) {
foreach ($dependency in $dependencyGraph[$resource]) {
if (-not $deploymentSet.ContainsKey($dependency)) {
Write-Host "错误: 资源 '$resource' 依赖于 '$dependency',但该资源尚未部署。" -ForegroundColor Red
$isValid = $false
}
}
$deploymentSet[$resource] = $true
}

if ($isValid) {
Write-Host "部署顺序有效。" -ForegroundColor Green
} else {
throw "部署顺序无效。请检查资源依赖关系。"
}
}

# 如果提供了输出路径,更新定义文件
if ($OutputPath) {
$definitionFile = Join-Path -Path $OutputPath -ChildPath "$($InfrastructureDefinition.EnvironmentName).json"
$InfrastructureDefinition | ConvertTo-Json -Depth 10 | Out-File -FilePath $definitionFile -Encoding UTF8
Write-Host "已更新基础设施定义: $definitionFile" -ForegroundColor Green
}

return $InfrastructureDefinition
}
catch {
Write-Error "生成部署顺序时出错: $_"
}
}
}

部署基础设施资源:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
# 部署基础设施资源
function Deploy-InfrastructureResource {
param(
[Parameter(Mandatory)]
[PSObject]$Resource,

[Parameter(Mandatory)]
[PSObject]$InfrastructureDefinition,

[switch]$WhatIf,

[PSObject]$DeploymentContext = @{}
)

try {
$resourceName = $Resource.Name
$resourceType = $Resource.ResourceType

Write-Host "开始部署资源: $resourceName (类型: $resourceType)" -ForegroundColor Cyan

switch ($resourceType) {
"VirtualMachine" {
if ($WhatIf) {
Write-Host "[WhatIf] 将创建虚拟机 '$resourceName' (大小: $($Resource.Size), OS: $($Resource.OSType)-$($Resource.OSVersion))" -ForegroundColor Yellow
} else {
# 这里是虚拟机部署的实际代码
# 示例: 使用 Azure PowerShell 模块创建虚拟机
Write-Host "正在创建虚拟机 '$resourceName'..." -ForegroundColor White

# 模拟部署
Start-Sleep -Seconds 2

# 返回部署结果
$deploymentResult = [PSCustomObject]@{
ResourceName = $resourceName
ResourceType = $resourceType
Status = "Success"
DeploymentId = [guid]::NewGuid().ToString()
DeploymentTime = Get-Date
Properties = @{
IPAddress = "10.0.0.$((Get-Random -Minimum 2 -Maximum 255))"
FQDN = "$resourceName.example.com"
}
}

Write-Host "虚拟机 '$resourceName' 部署成功" -ForegroundColor Green
return $deploymentResult
}
}
"VirtualNetwork" {
if ($WhatIf) {
Write-Host "[WhatIf] 将创建虚拟网络 '$resourceName' (地址空间: $($Resource.AddressSpace))" -ForegroundColor Yellow
} else {
# 这里是虚拟网络部署的实际代码
Write-Host "正在创建虚拟网络 '$resourceName'..." -ForegroundColor White

# 模拟部署
Start-Sleep -Seconds 1

# 返回部署结果
$deploymentResult = [PSCustomObject]@{
ResourceName = $resourceName
ResourceType = $resourceType
Status = "Success"
DeploymentId = [guid]::NewGuid().ToString()
DeploymentTime = Get-Date
Properties = @{
AddressSpace = $Resource.AddressSpace
SubnetCount = $Resource.Subnets.Count
}
}

Write-Host "虚拟网络 '$resourceName' 部署成功" -ForegroundColor Green
return $deploymentResult
}
}
default {
Write-Warning "不支持的资源类型: $resourceType"
}
}

if ($WhatIf) {
return [PSCustomObject]@{
ResourceName = $resourceName
ResourceType = $resourceType
Status = "WhatIf"
}
}
}
catch {
Write-Error "部署资源 '$resourceName' 时出错: $_"
return [PSCustomObject]@{
ResourceName = $resourceName
ResourceType = $resourceType
Status = "Failed"
Error = $_.ToString()
}
}
}

执行完整基础设施部署:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
# 部署完整基础设施
function Deploy-Infrastructure {
param(
[Parameter(Mandatory)]
[PSObject]$InfrastructureDefinition,

[switch]$WhatIf,

[switch]$Force,

[string]$DeploymentLogPath,

[scriptblock]$OnSuccessAction,

[scriptblock]$OnFailureAction
)

try {
$environmentName = $InfrastructureDefinition.EnvironmentName
$deploymentResults = @()
$deploymentContext = @{}
$deploymentStart = Get-Date
$deploymentSuccess = $true

Write-Host "开始部署环境: $environmentName" -ForegroundColor Cyan

# 检查是否有部署顺序
if ($InfrastructureDefinition.DeploymentOrder.Count -eq 0) {
Write-Warning "部署顺序为空。正在尝试生成部署顺序..."
$InfrastructureDefinition = Set-DeploymentOrder -InfrastructureDefinition $InfrastructureDefinition -Validate
}

# 创建资源映射
$resourceMap = @{}
foreach ($vmResource in $InfrastructureDefinition.Resources.VirtualMachines) {
$resourceMap[$vmResource.Name] = $vmResource
}

foreach ($netResource in $InfrastructureDefinition.Resources.NetworkResources) {
$resourceMap[$netResource.Name] = $netResource
}

# 按照部署顺序部署资源
foreach ($resourceName in $InfrastructureDefinition.DeploymentOrder) {
$resource = $resourceMap[$resourceName]

if (-not $resource) {
Write-Warning "资源 '$resourceName' 在部署顺序中但未找到资源定义。跳过。"
continue
}

$result = Deploy-InfrastructureResource -Resource $resource -InfrastructureDefinition $InfrastructureDefinition -WhatIf:$WhatIf -DeploymentContext $deploymentContext
$deploymentResults += $result

# 如果部署失败且未强制继续,则终止部署
if ($result.Status -eq "Failed" -and -not $Force) {
Write-Error "资源 '$resourceName' 部署失败。终止部署。"
$deploymentSuccess = $false
break
}

# 更新部署上下文
if ($result.Status -eq "Success") {
$deploymentContext[$resourceName] = $result
}
}

$deploymentEnd = Get-Date
$deploymentDuration = $deploymentEnd - $deploymentStart

# 生成部署摘要
$deploymentSummary = [PSCustomObject]@{
EnvironmentName = $environmentName
StartTime = $deploymentStart
EndTime = $deploymentEnd
Duration = $deploymentDuration
Status = if ($deploymentSuccess) { "Success" } else { "Failed" }
ResourceCount = $deploymentResults.Count
SuccessCount = ($deploymentResults | Where-Object { $_.Status -eq "Success" }).Count
FailedCount = ($deploymentResults | Where-Object { $_.Status -eq "Failed" }).Count
WhatIfCount = ($deploymentResults | Where-Object { $_.Status -eq "WhatIf" }).Count
DetailedResults = $deploymentResults
}

# 保存部署日志
if ($DeploymentLogPath) {
$logFile = Join-Path -Path $DeploymentLogPath -ChildPath "Deployment_$environmentName`_$(Get-Date -Format 'yyyyMMdd_HHmmss').json"

# 创建目录(如果不存在)
if (-not (Test-Path -Path $DeploymentLogPath)) {
New-Item -Path $DeploymentLogPath -ItemType Directory -Force | Out-Null
}

$deploymentSummary | ConvertTo-Json -Depth 10 | Out-File -FilePath $logFile -Encoding UTF8
Write-Host "部署日志已保存至: $logFile" -ForegroundColor Green
}

# 部署成功或失败时执行的操作
if ($deploymentSuccess -and $OnSuccessAction) {
& $OnSuccessAction -DeploymentSummary $deploymentSummary
}
elseif (-not $deploymentSuccess -and $OnFailureAction) {
& $OnFailureAction -DeploymentSummary $deploymentSummary
}

# 输出部署摘要
Write-Host "部署摘要:" -ForegroundColor Cyan
Write-Host " 环境: $environmentName" -ForegroundColor White
Write-Host " 状态: $($deploymentSummary.Status)" -ForegroundColor $(if ($deploymentSummary.Status -eq "Success") { "Green" } else { "Red" })
Write-Host " 持续时间: $($deploymentDuration.TotalMinutes) 分钟" -ForegroundColor White
Write-Host " 资源总数: $($deploymentSummary.ResourceCount)" -ForegroundColor White
Write-Host " 成功: $($deploymentSummary.SuccessCount)" -ForegroundColor Green
Write-Host " 失败: $($deploymentSummary.FailedCount)" -ForegroundColor $(if ($deploymentSummary.FailedCount -gt 0) { "Red" } else { "White" })
Write-Host " WhatIf: $($deploymentSummary.WhatIfCount)" -ForegroundColor Yellow

return $deploymentSummary
}
catch {
Write-Error "部署环境 '$environmentName' 时出错: $_"
}
}

现在,让我们看一个使用示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
# 定义输出路径
$outputPath = "C:\IaC\Definitions"

# 创建一个新的环境定义
$envDef = New-InfrastructureDefinition -EnvironmentName "DevTest" -EnvironmentType "Development" -OutputPath $outputPath -Description "开发测试环境"

# 添加网络资源
$subnets = @(
[PSCustomObject]@{ Name = "Frontend"; AddressPrefix = "10.0.1.0/24" },
[PSCustomObject]@{ Name = "Backend"; AddressPrefix = "10.0.2.0/24" },
[PSCustomObject]@{ Name = "Database"; AddressPrefix = "10.0.3.0/24" }
)

$envDef = Add-NetworkResource -InfrastructureDefinition $envDef -NetworkName "DevVNet" -AddressSpace "10.0.0.0/16" -Subnets $subnets -OutputPath $outputPath

# 添加虚拟机资源
$envDef = Add-VMResource -InfrastructureDefinition $envDef -VMName "WebServer01" -Size "Standard_B2s" -OSType "Windows" -OSVersion "2022-Datacenter" -NetworkName "DevVNet" -SubnetName "Frontend" -DependsOn @("DevVNet") -OutputPath $outputPath

$envDef = Add-VMResource -InfrastructureDefinition $envDef -VMName "AppServer01" -Size "Standard_B2s" -OSType "Windows" -OSVersion "2022-Datacenter" -NetworkName "DevVNet" -SubnetName "Backend" -DependsOn @("DevVNet", "WebServer01") -OutputPath $outputPath

$envDef = Add-VMResource -InfrastructureDefinition $envDef -VMName "DbServer01" -Size "Standard_B2ms" -OSType "Windows" -OSVersion "2022-Datacenter" -NetworkName "DevVNet" -SubnetName "Database" -DependsOn @("DevVNet") -OutputPath $outputPath

# 生成部署顺序
$envDef = Set-DeploymentOrder -InfrastructureDefinition $envDef -Validate -OutputPath $outputPath

# 预览部署(WhatIf)
$deploymentPreview = Deploy-Infrastructure -InfrastructureDefinition $envDef -WhatIf -DeploymentLogPath "C:\IaC\Logs"

# 实际部署
$deploymentResult = Deploy-Infrastructure -InfrastructureDefinition $envDef -DeploymentLogPath "C:\IaC\Logs"

这些PowerShell函数提供了一个强大的基础设施即代码解决方案,可以帮助自动化环境部署流程。随着基础设施复杂性的增加,您可以扩展这些函数来支持更多的资源类型和部署场景。结合版本控制系统如Git,这种方法能够确保环境配置的一致性和可重复性,从而提高IT运维的效率和可靠性。

PowerShell 技能连载 - 云原生配置管理

在云原生环境中,自动化资源配置管理至关重要。以下脚本实现Kubernetes部署模板生成与应用:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
function New-K8sDeployment {
[CmdletBinding()]
param(
[Parameter(Mandatory=$true)]
[string]$AppName,

[ValidateRange(1,10)]
[int]$Replicas = 3,

[ValidateSet('development','production')]
[string]$Environment = 'production'
)

$yaml = @"
apiVersion: apps/v1
kind: Deployment
metadata:
name: $AppName-$Environment
spec:
replicas: $Replicas
selector:
matchLabels:
app: $AppName
template:
metadata:
labels:
app: $AppName
env: $Environment
spec:
containers:
- name: $AppName
image: registry/vichamp/$AppName:latest
resources:
limits:
memory: "512Mi"
cpu: "500m"
"@

try {
$tempFile = New-TemporaryFile
$yaml | Out-File $tempFile.FullName

kubectl apply -f $tempFile.FullName

[PSCustomObject]@{
AppName = $AppName
Environment = $Environment
Manifest = $yaml
Status = 'Applied'
}
}
catch {
Write-Error "Kubernetes部署失败: $_"
}
finally {
Remove-Item $tempFile.FullName -ErrorAction SilentlyContinue
}
}

实现原理:

  1. 使用here-string动态生成标准YAML部署模板
  2. 通过环境参数控制副本数量和部署环境
  3. 自动创建临时文件执行kubectl apply命令
  4. 返回包含应用状态的定制对象
  5. 完善的错误处理与临时文件清理机制

使用示例:

1
New-K8sDeployment -AppName 'order-service' -Environment 'production' -Replicas 5

最佳实践:

  1. 与CI/CD流水线集成实现自动部署
  2. 添加资源请求/限制验证逻辑
  3. 实现部署历史版本回滚功能
  4. 集成Prometheus监控指标

注意事项:
• 需要配置kubectl访问权限
• 建议添加YAML语法验证
• 生产环境需设置严格的资源限制

PowerShell 技能连载 - Excel 处理技巧

在 PowerShell 中处理 Excel 文件是一项常见任务,本文将介绍一些实用的 Excel 处理技巧。

首先,让我们看看基本的 Excel 操作:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
# 创建 Excel 信息获取函数
function Get-ExcelInfo {
param(
[string]$ExcelPath
)

try {
$excel = New-Object -ComObject Excel.Application
$excel.Visible = $false
$workbook = $excel.Workbooks.Open($ExcelPath)

$info = [PSCustomObject]@{
FileName = Split-Path $ExcelPath -Leaf
SheetCount = $workbook.Sheets.Count
SheetNames = $workbook.Sheets | ForEach-Object { $_.Name }
UsedRange = $workbook.Sheets(1).UsedRange.Address
}

$workbook.Close($false)
$excel.Quit()
[System.Runtime.Interopservices.Marshal]::ReleaseComObject($excel)

return $info
}
catch {
Write-Host "获取 Excel 信息失败:$_"
}
}

Excel 数据导出:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
# 创建 Excel 数据导出函数
function Export-ExcelData {
param(
[string]$InputPath,
[string]$OutputPath,
[string]$SheetName,
[int]$StartRow = 1,
[int]$EndRow
)

try {
$excel = New-Object -ComObject Excel.Application
$excel.Visible = $false
$workbook = $excel.Workbooks.Open($InputPath)
$sheet = $workbook.Sheets($SheetName)

if (-not $EndRow) {
$EndRow = $sheet.UsedRange.Rows.Count
}

$data = @()
for ($row = $StartRow; $row -le $EndRow; $row++) {
$rowData = @()
for ($col = 1; $col -le $sheet.UsedRange.Columns.Count; $col++) {
$rowData += $sheet.Cells($row, $col).Text
}
$data += $rowData -join ","
}

$data | Out-File $OutputPath -Encoding UTF8

$workbook.Close($false)
$excel.Quit()
[System.Runtime.Interopservices.Marshal]::ReleaseComObject($excel)

Write-Host "数据导出完成:$OutputPath"
}
catch {
Write-Host "导出失败:$_"
}
}

Excel 数据导入:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
# 创建 Excel 数据导入函数
function Import-ExcelData {
param(
[string]$InputPath,
[string]$OutputPath,
[string]$SheetName = "Sheet1",
[string[]]$Headers
)

try {
$excel = New-Object -ComObject Excel.Application
$excel.Visible = $false
$workbook = $excel.Workbooks.Add()
$sheet = $workbook.Sheets(1)
$sheet.Name = $SheetName

# 写入表头
for ($i = 0; $i -lt $Headers.Count; $i++) {
$sheet.Cells(1, $i + 1) = $Headers[$i]
}

# 写入数据
$row = 2
Get-Content $InputPath | ForEach-Object {
$values = $_ -split ","
for ($col = 0; $col -lt $values.Count; $col++) {
$sheet.Cells($row, $col + 1) = $values[$col]
}
$row++
}

# 调整列宽
$sheet.UsedRange.EntireColumn.AutoFit()

$workbook.SaveAs($OutputPath)
$workbook.Close($true)
$excel.Quit()
[System.Runtime.Interopservices.Marshal]::ReleaseComObject($excel)

Write-Host "数据导入完成:$OutputPath"
}
catch {
Write-Host "导入失败:$_"
}
}

Excel 数据合并:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
# 创建 Excel 数据合并函数
function Merge-ExcelData {
param(
[string[]]$InputFiles,
[string]$OutputPath,
[string]$SheetName = "Sheet1"
)

try {
$excel = New-Object -ComObject Excel.Application
$excel.Visible = $false
$workbook = $excel.Workbooks.Add()
$sheet = $workbook.Sheets(1)
$sheet.Name = $SheetName

$currentRow = 1
$headersWritten = $false

foreach ($file in $InputFiles) {
$sourceWorkbook = $excel.Workbooks.Open($file)
$sourceSheet = $sourceWorkbook.Sheets(1)

if (-not $headersWritten) {
# 复制表头
$sourceSheet.Range($sourceSheet.UsedRange.Rows(1).Address).Copy($sheet.Cells($currentRow, 1))
$headersWritten = $true
$currentRow++
}

# 复制数据
$lastRow = $sourceSheet.UsedRange.Rows.Count
if ($lastRow -gt 1) {
$sourceSheet.Range($sourceSheet.UsedRange.Rows(2).Address + ":" + $sourceSheet.UsedRange.Rows($lastRow).Address).Copy($sheet.Cells($currentRow, 1))
$currentRow += $lastRow - 1
}

$sourceWorkbook.Close($false)
}

# 调整列宽
$sheet.UsedRange.EntireColumn.AutoFit()

$workbook.SaveAs($OutputPath)
$workbook.Close($true)
$excel.Quit()
[System.Runtime.Interopservices.Marshal]::ReleaseComObject($excel)

Write-Host "数据合并完成:$OutputPath"
}
catch {
Write-Host "合并失败:$_"
}
}

这些技巧将帮助您更有效地处理 Excel 文件。记住,在处理 Excel 时,始终要注意内存管理和资源释放。同时,建议在处理大型 Excel 文件时使用流式处理方式,以提高性能。

PowerShell 技能连载 - 资产管理

在系统管理中,资产管理对于确保资源的有效利用和成本控制至关重要。本文将介绍如何使用PowerShell构建一个资产管理系统,包括资产发现、跟踪和优化等功能。

资产发现

首先,让我们创建一个用于管理资产发现的函数:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
function Discover-SystemAssets {
[CmdletBinding()]
param(
[Parameter(Mandatory = $true)]
[string]$DiscoveryID,

[Parameter()]
[string[]]$AssetTypes,

[Parameter()]
[ValidateSet("Full", "Quick", "Custom")]
[string]$DiscoveryMode = "Full",

[Parameter()]
[hashtable]$DiscoveryConfig,

[Parameter()]
[string]$LogPath
)

try {
$discoverer = [PSCustomObject]@{
DiscoveryID = $DiscoveryID
StartTime = Get-Date
DiscoveryStatus = @{}
Assets = @{}
Issues = @()
}

# 获取发现配置
$config = Get-DiscoveryConfig -DiscoveryID $DiscoveryID

# 管理发现
foreach ($type in $AssetTypes) {
$status = [PSCustomObject]@{
Type = $type
Status = "Unknown"
Config = @{}
Assets = @{}
Issues = @()
}

# 应用发现配置
$typeConfig = Apply-DiscoveryConfig `
-Config $config `
-Type $type `
-Mode $DiscoveryMode `
-Settings $DiscoveryConfig

$status.Config = $typeConfig

# 发现系统资产
$assets = Discover-AssetInventory `
-Type $type `
-Config $typeConfig

$status.Assets = $assets
$discoverer.Assets[$type] = $assets

# 检查资产问题
$issues = Check-AssetIssues `
-Assets $assets `
-Config $typeConfig

$status.Issues = $issues
$discoverer.Issues += $issues

# 更新发现状态
if ($issues.Count -gt 0) {
$status.Status = "Warning"
}
else {
$status.Status = "Success"
}

$discoverer.DiscoveryStatus[$type] = $status
}

# 记录发现日志
if ($LogPath) {
$discoverer | ConvertTo-Json -Depth 10 | Out-File -FilePath $LogPath
}

# 更新发现器状态
$discoverer.EndTime = Get-Date

return $discoverer
}
catch {
Write-Error "资产发现失败:$_"
return $null
}
}

资产跟踪

接下来,创建一个用于管理资产跟踪的函数:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
function Track-SystemAssets {
[CmdletBinding()]
param(
[Parameter(Mandatory = $true)]
[string]$TrackingID,

[Parameter()]
[string[]]$TrackingTypes,

[Parameter()]
[ValidateSet("Usage", "Cost", "Lifecycle")]
[string]$TrackingMode = "Usage",

[Parameter()]
[hashtable]$TrackingConfig,

[Parameter()]
[string]$ReportPath
)

try {
$tracker = [PSCustomObject]@{
TrackingID = $TrackingID
StartTime = Get-Date
TrackingStatus = @{}
Tracking = @{}
Metrics = @()
}

# 获取跟踪配置
$config = Get-TrackingConfig -TrackingID $TrackingID

# 管理跟踪
foreach ($type in $TrackingTypes) {
$status = [PSCustomObject]@{
Type = $type
Status = "Unknown"
Config = @{}
Tracking = @{}
Metrics = @()
}

# 应用跟踪配置
$typeConfig = Apply-TrackingConfig `
-Config $config `
-Type $type `
-Mode $TrackingMode `
-Settings $TrackingConfig

$status.Config = $typeConfig

# 跟踪系统资产
$tracking = Track-AssetMetrics `
-Type $type `
-Config $typeConfig

$status.Tracking = $tracking
$tracker.Tracking[$type] = $tracking

# 生成跟踪指标
$metrics = Generate-TrackingMetrics `
-Tracking $tracking `
-Config $typeConfig

$status.Metrics = $metrics
$tracker.Metrics += $metrics

# 更新跟踪状态
if ($metrics.Count -gt 0) {
$status.Status = "Active"
}
else {
$status.Status = "Inactive"
}

$tracker.TrackingStatus[$type] = $status
}

# 生成报告
if ($ReportPath) {
$report = Generate-TrackingReport `
-Tracker $tracker `
-Config $config

$report | ConvertTo-Json -Depth 10 | Out-File -FilePath $ReportPath
}

# 更新跟踪器状态
$tracker.EndTime = Get-Date

return $tracker
}
catch {
Write-Error "资产跟踪失败:$_"
return $null
}
}

资产优化

最后,创建一个用于管理资产优化的函数:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
function Optimize-SystemAssets {
[CmdletBinding()]
param(
[Parameter(Mandatory = $true)]
[string]$OptimizationID,

[Parameter()]
[string[]]$OptimizationTypes,

[Parameter()]
[ValidateSet("Cost", "Performance", "Utilization")]
[string]$OptimizationMode = "Cost",

[Parameter()]
[hashtable]$OptimizationConfig,

[Parameter()]
[string]$ReportPath
)

try {
$optimizer = [PSCustomObject]@{
OptimizationID = $OptimizationID
StartTime = Get-Date
OptimizationStatus = @{}
Optimizations = @{}
Actions = @()
}

# 获取优化配置
$config = Get-OptimizationConfig -OptimizationID $OptimizationID

# 管理优化
foreach ($type in $OptimizationTypes) {
$status = [PSCustomObject]@{
Type = $type
Status = "Unknown"
Config = @{}
Optimizations = @{}
Actions = @()
}

# 应用优化配置
$typeConfig = Apply-OptimizationConfig `
-Config $config `
-Type $type `
-Mode $OptimizationMode `
-Settings $OptimizationConfig

$status.Config = $typeConfig

# 优化系统资产
$optimizations = Optimize-AssetUsage `
-Type $type `
-Config $typeConfig

$status.Optimizations = $optimizations
$optimizer.Optimizations[$type] = $optimizations

# 执行优化动作
$actions = Execute-OptimizationActions `
-Optimizations $optimizations `
-Config $typeConfig

$status.Actions = $actions
$optimizer.Actions += $actions

# 更新优化状态
if ($actions.Count -gt 0) {
$status.Status = "Optimized"
}
else {
$status.Status = "NoAction"
}

$optimizer.OptimizationStatus[$type] = $status
}

# 生成报告
if ($ReportPath) {
$report = Generate-OptimizationReport `
-Optimizer $optimizer `
-Config $config

$report | ConvertTo-Json -Depth 10 | Out-File -FilePath $ReportPath
}

# 更新优化器状态
$optimizer.EndTime = Get-Date

return $optimizer
}
catch {
Write-Error "资产优化失败:$_"
return $null
}
}

使用示例

以下是如何使用这些函数来管理资产的示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
# 发现系统资产
$discoverer = Discover-SystemAssets -DiscoveryID "DISCOVERY001" `
-AssetTypes @("Hardware", "Software", "Network", "Storage") `
-DiscoveryMode "Full" `
-DiscoveryConfig @{
"Hardware" = @{
"Categories" = @("Server", "Desktop", "Mobile")
"Attributes" = @("CPU", "Memory", "Storage")
"Filter" = "Status = Active"
"Retention" = 7
}
"Software" = @{
"Categories" = @("OS", "Application", "Driver")
"Attributes" = @("Version", "License", "InstallDate")
"Filter" = "Status = Installed"
"Retention" = 7
}
"Network" = @{
"Categories" = @("Device", "Connection", "Protocol")
"Attributes" = @("IP", "MAC", "Speed")
"Filter" = "Status = Connected"
"Retention" = 7
}
"Storage" = @{
"Categories" = @("Disk", "Volume", "Share")
"Attributes" = @("Size", "Free", "Type")
"Filter" = "Status = Online"
"Retention" = 7
}
} `
-LogPath "C:\Logs\asset_discovery.json"

# 跟踪系统资产
$tracker = Track-SystemAssets -TrackingID "TRACKING001" `
-TrackingTypes @("Usage", "Cost", "Lifecycle") `
-TrackingMode "Usage" `
-TrackingConfig @{
"Usage" = @{
"Metrics" = @("CPU", "Memory", "Storage", "Network")
"Threshold" = 80
"Interval" = 60
"Report" = $true
}
"Cost" = @{
"Metrics" = @("License", "Maintenance", "Support")
"Threshold" = 1000
"Interval" = 30
"Report" = $true
}
"Lifecycle" = @{
"Metrics" = @("Age", "Warranty", "Depreciation")
"Threshold" = 365
"Interval" = 90
"Report" = $true
}
} `
-ReportPath "C:\Reports\asset_tracking.json"

# 优化系统资产
$optimizer = Optimize-SystemAssets -OptimizationID "OPTIMIZATION001" `
-OptimizationTypes @("Cost", "Performance", "Utilization") `
-OptimizationMode "Cost" `
-OptimizationConfig @{
"Cost" = @{
"Metrics" = @("License", "Maintenance", "Support")
"Threshold" = 1000
"Actions" = @("Renew", "Upgrade", "Terminate")
"Report" = $true
}
"Performance" = @{
"Metrics" = @("CPU", "Memory", "Storage", "Network")
"Threshold" = 80
"Actions" = @("Scale", "Upgrade", "Migrate")
"Report" = $true
}
"Utilization" = @{
"Metrics" = @("Usage", "Efficiency", "Availability")
"Threshold" = 60
"Actions" = @("Consolidate", "Optimize", "Decommission")
"Report" = $true
}
} `
-ReportPath "C:\Reports\asset_optimization.json"

最佳实践

  1. 实施资产发现
  2. 跟踪资产使用
  3. 优化资产利用
  4. 保持详细的资产记录
  5. 定期进行资产评估
  6. 实施优化策略
  7. 建立成本控制
  8. 保持系统文档更新

PowerShell 技能连载 - 视频处理技巧

在 PowerShell 中处理视频文件是一项有趣的任务,本文将介绍一些实用的视频处理技巧。

首先,让我们看看基本的视频操作:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
# 创建视频信息获取函数
function Get-VideoInfo {
param(
[string]$VideoPath
)

try {
# 使用 ffprobe 获取视频信息
$ffprobe = "ffprobe"
$info = & $ffprobe -v quiet -print_format json -show_format -show_streams $VideoPath | ConvertFrom-Json

$videoStream = $info.streams | Where-Object { $_.codec_type -eq "video" }
$audioStream = $info.streams | Where-Object { $_.codec_type -eq "audio" }

return [PSCustomObject]@{
FileName = Split-Path $VideoPath -Leaf
Duration = [math]::Round([double]$info.format.duration, 2)
Size = [math]::Round([double]$info.format.size / 1MB, 2)
Bitrate = [math]::Round([double]$info.format.bit_rate / 1000, 2)
Format = $info.format.format_name
VideoCodec = $videoStream.codec_name
VideoResolution = "$($videoStream.width)x$($videoStream.height)"
AudioCodec = $audioStream.codec_name
AudioChannels = $audioStream.channels
}
}
catch {
Write-Host "获取视频信息失败:$_"
}
}

视频格式转换:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
# 创建视频格式转换函数
function Convert-VideoFormat {
param(
[string]$InputPath,
[string]$OutputPath,
[ValidateSet("mp4", "avi", "mkv", "mov")]
[string]$TargetFormat,
[ValidateSet("high", "medium", "low")]
[string]$Quality = "medium"
)

try {
$ffmpeg = "ffmpeg"
$qualitySettings = @{
"high" = "-crf 17"
"medium" = "-crf 23"
"low" = "-crf 28"
}

$command = "$ffmpeg -i `"$InputPath`" $($qualitySettings[$Quality]) `"$OutputPath`""
Invoke-Expression $command

Write-Host "格式转换完成:$OutputPath"
}
catch {
Write-Host "转换失败:$_"
}
}

视频剪辑:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# 创建视频剪辑函数
function Split-Video {
param(
[string]$InputPath,
[string]$OutputFolder,
[double]$StartTime,
[double]$Duration
)

try {
$ffmpeg = "ffmpeg"
$fileName = [System.IO.Path]::GetFileNameWithoutExtension($InputPath)
$extension = [System.IO.Path]::GetExtension($InputPath)
$outputPath = Join-Path $OutputFolder "$fileName`_split$extension"

$command = "$ffmpeg -i `"$InputPath`" -ss $StartTime -t $Duration `"$outputPath`""
Invoke-Expression $command

Write-Host "视频剪辑完成:$outputPath"
}
catch {
Write-Host "剪辑失败:$_"
}
}

视频压缩:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
# 创建视频压缩函数
function Compress-Video {
param(
[string]$InputPath,
[string]$OutputPath,
[ValidateSet("high", "medium", "low")]
[string]$Quality = "medium",
[int]$MaxWidth = 1920
)

try {
$ffmpeg = "ffmpeg"
$qualitySettings = @{
"high" = "-crf 23"
"medium" = "-crf 28"
"low" = "-crf 33"
}

$command = "$ffmpeg -i `"$InputPath`" -vf scale=$MaxWidth`:-1 $($qualitySettings[$Quality]) `"$OutputPath`""
Invoke-Expression $command

Write-Host "视频压缩完成:$OutputPath"
}
catch {
Write-Host "压缩失败:$_"
}
}

视频帧提取:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
# 创建视频帧提取函数
function Extract-VideoFrames {
param(
[string]$InputPath,
[string]$OutputFolder,
[double]$Interval = 1.0,
[ValidateSet("jpg", "png")]
[string]$Format = "jpg"
)

try {
$ffmpeg = "ffmpeg"
if (-not (Test-Path $OutputFolder)) {
New-Item -ItemType Directory -Path $OutputFolder | Out-Null
}

$fileName = [System.IO.Path]::GetFileNameWithoutExtension($InputPath)
$outputPattern = Join-Path $OutputFolder "$fileName`_%d.$Format"

$command = "$ffmpeg -i `"$InputPath`" -vf fps=1/$Interval `"$outputPattern`""
Invoke-Expression $command

Write-Host "帧提取完成:$OutputFolder"
}
catch {
Write-Host "帧提取失败:$_"
}
}

这些技巧将帮助您更有效地处理视频文件。记住,在处理视频时,始终要注意文件格式的兼容性和视频质量。同时,建议在处理大型视频文件时使用流式处理方式,以提高性能。

PowerShell 技能连载 - Kubernetes 管理技巧

在 PowerShell 中管理 Kubernetes 是一项重要任务,本文将介绍一些实用的 Kubernetes 管理技巧。

首先,让我们看看基本的 Kubernetes 操作:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
# 创建 Kubernetes 集群管理函数
function Manage-K8sCluster {
param(
[string]$ClusterName,
[string]$ResourceGroup,
[string]$Location,
[string]$NodeCount,
[string]$NodeSize,
[ValidateSet('Create', 'Update', 'Delete', 'Start', 'Stop')]
[string]$Action
)

try {
Import-Module Az.Aks

switch ($Action) {
'Create' {
New-AzAksCluster -Name $ClusterName -ResourceGroupName $ResourceGroup -Location $Location -NodeCount $NodeCount -NodeSize $NodeSize
Write-Host "Kubernetes 集群 $ClusterName 创建成功"
}
'Update' {
Update-AzAksCluster -Name $ClusterName -ResourceGroupName $ResourceGroup -NodeCount $NodeCount
Write-Host "Kubernetes 集群 $ClusterName 更新成功"
}
'Delete' {
Remove-AzAksCluster -Name $ClusterName -ResourceGroupName $ResourceGroup -Force
Write-Host "Kubernetes 集群 $ClusterName 删除成功"
}
'Start' {
Start-AzAksCluster -Name $ClusterName -ResourceGroupName $ResourceGroup
Write-Host "Kubernetes 集群 $ClusterName 已启动"
}
'Stop' {
Stop-AzAksCluster -Name $ClusterName -ResourceGroupName $ResourceGroup
Write-Host "Kubernetes 集群 $ClusterName 已停止"
}
}
}
catch {
Write-Host "Kubernetes 集群操作失败:$_"
}
}

Kubernetes 资源部署:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
# 创建 Kubernetes 资源部署函数
function Deploy-K8sResource {
param(
[string]$Namespace,
[string]$ManifestPath,
[string]$Context,
[switch]$DryRun
)

try {
Import-Module Kubernetes

if ($DryRun) {
$result = kubectl apply -f $ManifestPath -n $Namespace --context $Context --dry-run=client
Write-Host "部署预览:"
$result
}
else {
$result = kubectl apply -f $ManifestPath -n $Namespace --context $Context
Write-Host "资源已部署到命名空间 $Namespace"
}

return [PSCustomObject]@{
Namespace = $Namespace
ManifestPath = $ManifestPath
Context = $Context
Result = $result
}
}
catch {
Write-Host "资源部署失败:$_"
}
}

Kubernetes 日志收集:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
# 创建 Kubernetes 日志收集函数
function Get-K8sLogs {
param(
[string]$Namespace,
[string]$Pod,
[string]$Container,
[int]$Lines = 100,
[datetime]$Since,
[string]$OutputPath
)

try {
Import-Module Kubernetes

$logParams = @(
"logs",
$Pod,
"-n", $Namespace,
"--tail=$Lines"
)

if ($Container) {
$logParams += "-c", $Container
}

if ($Since) {
$logParams += "--since=$($Since.ToString('yyyy-MM-ddTHH:mm:ssZ'))"
}

$logs = kubectl $logParams

if ($OutputPath) {
$logs | Out-File -FilePath $OutputPath -Encoding UTF8
}

return [PSCustomObject]@{
Pod = $Pod
Namespace = $Namespace
Container = $Container
LogCount = $logs.Count
OutputPath = $OutputPath
}
}
catch {
Write-Host "日志收集失败:$_"
}
}

Kubernetes 资源监控:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
# 创建 Kubernetes 资源监控函数
function Monitor-K8sResources {
param(
[string]$Namespace,
[string]$ResourceType,
[int]$Duration = 3600,
[int]$Interval = 60
)

try {
Import-Module Kubernetes

$metrics = @()
$endTime = Get-Date
$startTime = $endTime.AddSeconds(-$Duration)

while ($startTime -lt $endTime) {
$resourceMetrics = switch ($ResourceType) {
"Pod" {
kubectl top pods -n $Namespace
}
"Node" {
kubectl top nodes
}
"Deployment" {
kubectl top deployment -n $Namespace
}
default {
throw "不支持的资源类型:$ResourceType"
}
}

$metrics += [PSCustomObject]@{
Time = $startTime
ResourceType = $ResourceType
Metrics = $resourceMetrics
}

$startTime = $startTime.AddSeconds($Interval)
Start-Sleep -Seconds $Interval
}

return [PSCustomObject]@{
Namespace = $Namespace
ResourceType = $ResourceType
Duration = $Duration
Interval = $Interval
Metrics = $metrics
}
}
catch {
Write-Host "资源监控失败:$_"
}
}

Kubernetes 问题诊断:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
# 创建 Kubernetes 问题诊断函数
function Debug-K8sIssues {
param(
[string]$Namespace,
[string]$Pod,
[string]$OutputPath
)

try {
Import-Module Kubernetes

$diagnostics = @{
PodStatus = kubectl get pod $Pod -n $Namespace -o yaml
PodDescription = kubectl describe pod $Pod -n $Namespace
PodEvents = kubectl get events -n $Namespace --field-selector involvedObject.name=$Pod
PodLogs = kubectl logs $Pod -n $Namespace
}

if ($OutputPath) {
$diagnostics | ConvertTo-Json -Depth 10 | Out-File -FilePath $OutputPath -Encoding UTF8
}

return [PSCustomObject]@{
Pod = $Pod
Namespace = $Namespace
Diagnostics = $diagnostics
OutputPath = $OutputPath
}
}
catch {
Write-Host "问题诊断失败:$_"
}
}

这些技巧将帮助您更有效地管理 Kubernetes。记住,在处理 Kubernetes 时,始终要注意安全性和性能。同时,建议使用适当的错误处理和日志记录机制来跟踪所有操作。

PowerShell 技能连载 - Kubernetes 管理技巧

在 PowerShell 中管理 Kubernetes 集群是一项重要任务,本文将介绍一些实用的 Kubernetes 管理技巧。

首先,让我们看看基本的 Kubernetes 操作:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
# 创建 Kubernetes 集群信息获取函数
function Get-K8sClusterInfo {
param(
[string]$Context
)

try {
$kubectl = "kubectl"
if ($Context) {
$kubectl += " --context=$Context"
}

$nodes = & $kubectl get nodes -o json | ConvertFrom-Json
$pods = & $kubectl get pods --all-namespaces -o json | ConvertFrom-Json

return [PSCustomObject]@{
NodeCount = $nodes.items.Count
PodCount = $pods.items.Count
Namespaces = ($pods.items | Select-Object -ExpandProperty metadata | Select-Object -ExpandProperty namespace -Unique).Count
NodeStatus = $nodes.items | ForEach-Object {
[PSCustomObject]@{
Name = $_.metadata.name
Status = $_.status.conditions | Where-Object { $_.type -eq "Ready" } | Select-Object -ExpandProperty status
Version = $_.status.nodeInfo.kubeletVersion
}
}
}
}
catch {
Write-Host "获取集群信息失败:$_"
}
}

Kubernetes 资源部署:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
# 创建 Kubernetes 资源部署函数
function Deploy-K8sResource {
param(
[string]$ManifestPath,
[string]$Namespace,
[string]$Context,
[switch]$DryRun
)

try {
$kubectl = "kubectl"
if ($Context) {
$kubectl += " --context=$Context"
}
if ($Namespace) {
$kubectl += " -n $Namespace"
}
if ($DryRun) {
$kubectl += " --dry-run=client"
}

$command = "$kubectl apply -f `"$ManifestPath`""
Invoke-Expression $command

Write-Host "资源部署完成"
}
catch {
Write-Host "部署失败:$_"
}
}

Kubernetes 日志收集:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
# 创建 Kubernetes 日志收集函数
function Get-K8sLogs {
param(
[string]$PodName,
[string]$Namespace,
[string]$Container,
[int]$Lines = 100,
[string]$Context,
[datetime]$Since
)

try {
$kubectl = "kubectl"
if ($Context) {
$kubectl += " --context=$Context"
}
if ($Namespace) {
$kubectl += " -n $Namespace"
}
if ($Container) {
$kubectl += " -c $Container"
}
if ($Since) {
$kubectl += " --since=$($Since.ToString('yyyy-MM-ddTHH:mm:ssZ'))"
}

$command = "$kubectl logs $PodName --tail=$Lines"
$logs = Invoke-Expression $command

return [PSCustomObject]@{
PodName = $PodName
Container = $Container
Logs = $logs
Timestamp = Get-Date
}
}
catch {
Write-Host "日志收集失败:$_"
}
}

Kubernetes 资源监控:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
# 创建 Kubernetes 资源监控函数
function Monitor-K8sResources {
param(
[string]$Namespace,
[string]$Context,
[int]$Interval = 60,
[int]$Duration = 3600
)

try {
$kubectl = "kubectl"
if ($Context) {
$kubectl += " --context=$Context"
}
if ($Namespace) {
$kubectl += " -n $Namespace"
}

$startTime = Get-Date
$metrics = @()

while ((Get-Date) - $startTime).TotalSeconds -lt $Duration {
$pods = & $kubectl get pods -o json | ConvertFrom-Json
$nodes = & $kubectl get nodes -o json | ConvertFrom-Json

$metrics += [PSCustomObject]@{
Timestamp = Get-Date
PodCount = $pods.items.Count
NodeCount = $nodes.items.Count
PodStatus = $pods.items | Group-Object { $_.status.phase } | ForEach-Object {
[PSCustomObject]@{
Status = $_.Name
Count = $_.Count
}
}
NodeStatus = $nodes.items | Group-Object { $_.status.conditions | Where-Object { $_.type -eq "Ready" } | Select-Object -ExpandProperty status } | ForEach-Object {
[PSCustomObject]@{
Status = $_.Name
Count = $_.Count
}
}
}

Start-Sleep -Seconds $Interval
}

return $metrics
}
catch {
Write-Host "监控失败:$_"
}
}

Kubernetes 故障排查:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
# 创建 Kubernetes 故障排查函数
function Debug-K8sIssues {
param(
[string]$PodName,
[string]$Namespace,
[string]$Context,
[switch]$IncludeEvents,
[switch]$IncludeLogs
)

try {
$kubectl = "kubectl"
if ($Context) {
$kubectl += " --context=$Context"
}
if ($Namespace) {
$kubectl += " -n $Namespace"
}

$diagnostics = @{
PodStatus = & $kubectl get pod $PodName -o json | ConvertFrom-Json
PodDescription = & $kubectl describe pod $PodName
}

if ($IncludeEvents) {
$diagnostics.Events = & $kubectl get events --field-selector involvedObject.name=$PodName
}

if ($IncludeLogs) {
$diagnostics.Logs = & $kubectl logs $PodName
}

return [PSCustomObject]$diagnostics
}
catch {
Write-Host "故障排查失败:$_"
}
}

这些技巧将帮助您更有效地管理 Kubernetes 集群。记住,在处理 Kubernetes 资源时,始终要注意集群的安全性和稳定性。同时,建议在处理大型集群时使用适当的资源限制和监控机制。

PowerShell 技能连载 - AI 集成技巧

在 PowerShell 中集成 AI 功能是一项前沿任务,本文将介绍一些实用的 AI 集成技巧。

首先,让我们看看如何与 OpenAI API 进行交互:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
# 创建 OpenAI 交互函数
function Invoke-OpenAIAPI {
param(
[string]$ApiKey,
[string]$Prompt,
[ValidateSet('gpt-4', 'gpt-3.5-turbo')]
[string]$Model = 'gpt-3.5-turbo',
[float]$Temperature = 0.7,
[int]$MaxTokens = 500
)

try {
$headers = @{
'Content-Type' = 'application/json'
'Authorization' = "Bearer $ApiKey"
}

$body = @{
model = $Model
messages = @(
@{
role = "user"
content = $Prompt
}
)
temperature = $Temperature
max_tokens = $MaxTokens
} | ConvertTo-Json

$response = Invoke-RestMethod -Uri "https://api.openai.com/v1/chat/completions" -Method Post -Headers $headers -Body $body
return $response.choices[0].message.content
}
catch {
Write-Host "OpenAI API 调用失败:$_"
}
}

使用 AI 生成 PowerShell 脚本:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
# 创建 AI 脚本生成函数
function New-AIScript {
param(
[string]$ApiKey,
[string]$Description,
[string]$OutputPath
)

try {
$prompt = @"
生成一个 PowerShell 脚本,完成以下功能:$Description

要求:
1. 脚本应包含详细的注释
2. 包含适当的错误处理
3. 遵循 PowerShell 最佳实践
4. 只返回脚本代码,不要额外的解释
"@

$script = Invoke-OpenAIAPI -ApiKey $ApiKey -Prompt $prompt -MaxTokens 2000

if ($OutputPath) {
$script | Out-File -FilePath $OutputPath -Encoding UTF8
Write-Host "脚本已保存至:$OutputPath"
}

return $script
}
catch {
Write-Host "AI 脚本生成失败:$_"
}
}

利用 AI 进行日志分析:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
# 创建 AI 日志分析函数
function Analyze-LogsWithAI {
param(
[string]$ApiKey,
[string]$LogFilePath,
[string]$OutputPath,
[switch]$IncludeRecommendations
)

try {
$logs = Get-Content -Path $LogFilePath -Raw

# 将日志截断到合理的大小
if ($logs.Length -gt 4000) {
$logs = $logs.Substring(0, 4000) + "... [日志截断]"
}

$promptSuffix = ""
if ($IncludeRecommendations) {
$promptSuffix = "并提供解决方案建议。"
}

$prompt = @"
分析以下系统日志,识别可能的错误、警告和问题模式$promptSuffix

日志内容:
$logs
"@

$analysis = Invoke-OpenAIAPI -ApiKey $ApiKey -Prompt $prompt -MaxTokens 1500

if ($OutputPath) {
$analysis | Out-File -FilePath $OutputPath -Encoding UTF8
Write-Host "分析结果已保存至:$OutputPath"
}

return $analysis
}
catch {
Write-Host "AI 日志分析失败:$_"
}
}

AI 辅助的自动化故障排除:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
# 创建 AI 故障排除函数
function Start-AITroubleshooting {
param(
[string]$ApiKey,
[string]$Issue,
[switch]$RunDiagnostics
)

try {
$systemInfo = Get-ComputerInfo | ConvertTo-Json

if ($RunDiagnostics) {
$eventLogs = Get-WinEvent -LogName Application -MaxEvents 20 | Select-Object TimeCreated, LevelDisplayName, Message | ConvertTo-Json
$services = Get-Service | Where-Object { $_.Status -eq 'Stopped' -and $_.StartType -eq 'Automatic' } | ConvertTo-Json

$diagnosticInfo = @"
系统信息:
$systemInfo

最近事件日志:
$eventLogs

已停止的自动启动服务:
$services
"@
} else {
$diagnosticInfo = "系统信息:$systemInfo"
}

$prompt = @"
我有以下系统问题:$Issue

基于以下系统信息,提供排查步骤和可能的解决方案:

$diagnosticInfo
"@

$troubleshooting = Invoke-OpenAIAPI -ApiKey $ApiKey -Prompt $prompt -MaxTokens 2000 -Model 'gpt-4'

return $troubleshooting
}
catch {
Write-Host "AI 故障排除失败:$_"
}
}

使用 AI 优化 PowerShell 脚本性能:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
# 创建 AI 脚本优化函数
function Optimize-ScriptWithAI {
param(
[string]$ApiKey,
[string]$ScriptPath,
[string]$OutputPath,
[switch]$IncludeExplanation
)

try {
$script = Get-Content -Path $ScriptPath -Raw

$promptSuffix = ""
if ($IncludeExplanation) {
$promptSuffix = "并解释所做的改动和优化理由。"
}

$prompt = @"
优化以下 PowerShell 脚本的性能和代码质量$promptSuffix

脚本内容:
$script
"@

$optimizedScript = Invoke-OpenAIAPI -ApiKey $ApiKey -Prompt $prompt -MaxTokens 2000 -Model 'gpt-4'

if ($OutputPath) {
$optimizedScript | Out-File -FilePath $OutputPath -Encoding UTF8
Write-Host "优化后的脚本已保存至:$OutputPath"
}

return $optimizedScript
}
catch {
Write-Host "AI 脚本优化失败:$_"
}
}

这些技巧将帮助您更有效地在 PowerShell 中集成 AI 功能。记住,在处理 AI 相关任务时,始终要注意 API 密钥的安全性和成本控制。同时,建议使用适当的错误处理和日志记录机制来跟踪所有操作。

PowerShell 技能连载 - 补丁管理

在系统管理中,补丁管理对于确保系统安全性和稳定性至关重要。本文将介绍如何使用PowerShell构建一个补丁管理系统,包括补丁扫描、评估和部署等功能。

补丁扫描

首先,让我们创建一个用于管理补丁扫描的函数:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
function Scan-SystemPatches {
[CmdletBinding()]
param(
[Parameter(Mandatory = $true)]
[string]$ScanID,

[Parameter()]
[string[]]$ScanTypes,

[Parameter()]
[ValidateSet("Full", "Quick", "Custom")]
[string]$ScanMode = "Full",

[Parameter()]
[hashtable]$ScanConfig,

[Parameter()]
[string]$LogPath
)

try {
$scanner = [PSCustomObject]@{
ScanID = $ScanID
StartTime = Get-Date
ScanStatus = @{}
Patches = @{}
Issues = @()
}

# 获取扫描配置
$config = Get-ScanConfig -ScanID $ScanID

# 管理扫描
foreach ($type in $ScanTypes) {
$status = [PSCustomObject]@{
Type = $type
Status = "Unknown"
Config = @{}
Patches = @{}
Issues = @()
}

# 应用扫描配置
$typeConfig = Apply-ScanConfig `
-Config $config `
-Type $type `
-Mode $ScanMode `
-Settings $ScanConfig

$status.Config = $typeConfig

# 扫描系统补丁
$patches = Scan-PatchData `
-Type $type `
-Config $typeConfig

$status.Patches = $patches
$scanner.Patches[$type] = $patches

# 检查扫描问题
$issues = Check-ScanIssues `
-Patches $patches `
-Config $typeConfig

$status.Issues = $issues
$scanner.Issues += $issues

# 更新扫描状态
if ($issues.Count -gt 0) {
$status.Status = "Warning"
}
else {
$status.Status = "Success"
}

$scanner.ScanStatus[$type] = $status
}

# 记录扫描日志
if ($LogPath) {
$scanner | ConvertTo-Json -Depth 10 | Out-File -FilePath $LogPath
}

# 更新扫描器状态
$scanner.EndTime = Get-Date

return $scanner
}
catch {
Write-Error "补丁扫描失败:$_"
return $null
}
}

补丁评估

接下来,创建一个用于管理补丁评估的函数:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
function Assess-SystemPatches {
[CmdletBinding()]
param(
[Parameter(Mandatory = $true)]
[string]$AssessmentID,

[Parameter()]
[string[]]$AssessmentTypes,

[Parameter()]
[ValidateSet("Security", "Compatibility", "Dependency")]
[string]$AssessmentMode = "Security",

[Parameter()]
[hashtable]$AssessmentConfig,

[Parameter()]
[string]$ReportPath
)

try {
$assessor = [PSCustomObject]@{
AssessmentID = $AssessmentID
StartTime = Get-Date
AssessmentStatus = @{}
Assessment = @{}
Findings = @()
}

# 获取评估配置
$config = Get-AssessmentConfig -AssessmentID $AssessmentID

# 管理评估
foreach ($type in $AssessmentTypes) {
$status = [PSCustomObject]@{
Type = $type
Status = "Unknown"
Config = @{}
Assessment = @{}
Findings = @()
}

# 应用评估配置
$typeConfig = Apply-AssessmentConfig `
-Config $config `
-Type $type `
-Mode $AssessmentMode `
-Settings $AssessmentConfig

$status.Config = $typeConfig

# 评估系统补丁
$assessment = Assess-PatchData `
-Type $type `
-Config $typeConfig

$status.Assessment = $assessment
$assessor.Assessment[$type] = $assessment

# 生成评估结果
$findings = Generate-AssessmentFindings `
-Assessment $assessment `
-Config $typeConfig

$status.Findings = $findings
$assessor.Findings += $findings

# 更新评估状态
if ($findings.Count -gt 0) {
$status.Status = "High"
}
else {
$status.Status = "Low"
}

$assessor.AssessmentStatus[$type] = $status
}

# 生成报告
if ($ReportPath) {
$report = Generate-AssessmentReport `
-Assessor $assessor `
-Config $config

$report | ConvertTo-Json -Depth 10 | Out-File -FilePath $ReportPath
}

# 更新评估器状态
$assessor.EndTime = Get-Date

return $assessor
}
catch {
Write-Error "补丁评估失败:$_"
return $null
}
}

补丁部署

最后,创建一个用于管理补丁部署的函数:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
function Deploy-SystemPatches {
[CmdletBinding()]
param(
[Parameter(Mandatory = $true)]
[string]$DeploymentID,

[Parameter()]
[string[]]$DeploymentTypes,

[Parameter()]
[ValidateSet("Automatic", "Manual", "Scheduled")]
[string]$DeploymentMode = "Automatic",

[Parameter()]
[hashtable]$DeploymentConfig,

[Parameter()]
[string]$ReportPath
)

try {
$deployer = [PSCustomObject]@{
DeploymentID = $DeploymentID
StartTime = Get-Date
DeploymentStatus = @{}
Deployment = @{}
Results = @()
}

# 获取部署配置
$config = Get-DeploymentConfig -DeploymentID $DeploymentID

# 管理部署
foreach ($type in $DeploymentTypes) {
$status = [PSCustomObject]@{
Type = $type
Status = "Unknown"
Config = @{}
Deployment = @{}
Results = @()
}

# 应用部署配置
$typeConfig = Apply-DeploymentConfig `
-Config $config `
-Type $type `
-Mode $DeploymentMode `
-Settings $DeploymentConfig

$status.Config = $typeConfig

# 部署系统补丁
$deployment = Deploy-PatchData `
-Type $type `
-Config $typeConfig

$status.Deployment = $deployment
$deployer.Deployment[$type] = $deployment

# 生成部署结果
$results = Generate-DeploymentResults `
-Deployment $deployment `
-Config $typeConfig

$status.Results = $results
$deployer.Results += $results

# 更新部署状态
if ($results.Count -gt 0) {
$status.Status = "Success"
}
else {
$status.Status = "Failed"
}

$deployer.DeploymentStatus[$type] = $status
}

# 生成报告
if ($ReportPath) {
$report = Generate-DeploymentReport `
-Deployer $deployer `
-Config $config

$report | ConvertTo-Json -Depth 10 | Out-File -FilePath $ReportPath
}

# 更新部署器状态
$deployer.EndTime = Get-Date

return $deployer
}
catch {
Write-Error "补丁部署失败:$_"
return $null
}
}

使用示例

以下是如何使用这些函数来管理补丁的示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
# 扫描系统补丁
$scanner = Scan-SystemPatches -ScanID "SCAN001" `
-ScanTypes @("Security", "Critical", "Optional", "Driver") `
-ScanMode "Full" `
-ScanConfig @{
"Security" = @{
"Source" = @("Windows Update", "WSUS", "SCCM")
"Filter" = "Severity = Critical"
"Report" = $true
}
"Critical" = @{
"Source" = @("Windows Update", "WSUS", "SCCM")
"Filter" = "Type = Critical"
"Report" = $true
}
"Optional" = @{
"Source" = @("Windows Update", "WSUS", "SCCM")
"Filter" = "Type = Optional"
"Report" = $true
}
"Driver" = @{
"Source" = @("Windows Update", "WSUS", "SCCM")
"Filter" = "Type = Driver"
"Report" = $true
}
} `
-LogPath "C:\Logs\patch_scan.json"

# 评估系统补丁
$assessor = Assess-SystemPatches -AssessmentID "ASSESSMENT001" `
-AssessmentTypes @("Security", "Critical", "Optional", "Driver") `
-AssessmentMode "Security" `
-AssessmentConfig @{
"Security" = @{
"Impact" = @("Vulnerability", "Compliance", "Risk")
"Priority" = "High"
"Report" = $true
}
"Critical" = @{
"Impact" = @("Vulnerability", "Compliance", "Risk")
"Priority" = "High"
"Report" = $true
}
"Optional" = @{
"Impact" = @("Vulnerability", "Compliance", "Risk")
"Priority" = "Medium"
"Report" = $true
}
"Driver" = @{
"Impact" = @("Vulnerability", "Compliance", "Risk")
"Priority" = "Low"
"Report" = $true
}
} `
-ReportPath "C:\Reports\patch_assessment.json"

# 部署系统补丁
$deployer = Deploy-SystemPatches -DeploymentID "DEPLOYMENT001" `
-DeploymentTypes @("Security", "Critical", "Optional", "Driver") `
-DeploymentMode "Automatic" `
-DeploymentConfig @{
"Security" = @{
"Method" = @("Download", "Install", "Verify")
"Schedule" = "Immediate"
"Timeout" = 120
"Report" = $true
}
"Critical" = @{
"Method" = @("Download", "Install", "Verify")
"Schedule" = "Immediate"
"Timeout" = 120
"Report" = $true
}
"Optional" = @{
"Method" = @("Download", "Install", "Verify")
"Schedule" = "OffHours"
"Timeout" = 120
"Report" = $true
}
"Driver" = @{
"Method" = @("Download", "Install", "Verify")
"Schedule" = "OffHours"
"Timeout" = 120
"Report" = $true
}
} `
-ReportPath "C:\Reports\patch_deployment.json"

最佳实践

  1. 实施补丁扫描
  2. 评估补丁影响
  3. 管理补丁部署
  4. 保持详细的补丁记录
  5. 定期进行补丁审查
  6. 实施回滚策略
  7. 建立补丁控制
  8. 保持系统文档更新

PowerShell 技能连载 - 正则表达式实战

正则表达式基础

1
2
3
4
5
6
7
# 邮箱验证模式
$emailPattern = '^[\w-]+(\.[\w-]+)*@([\w-]+\.)+[a-zA-Z]{2,7}$'

# 匹配操作
if ('user@domain.com' -match $emailPattern) {
Write-Output "有效邮箱地址"
}

高级应用场景

  1. 批量重命名文件

    1
    2
    Get-ChildItem *.log | 
    Rename-Item -NewName { $_.Name -replace '_\d{8}_','_$(Get-Date -f yyyyMMdd)_' }
  2. 日志分析提取

    1
    2
    3
    4
    5
    6
    7
    Select-String -Path *.log -Pattern 'ERROR (\w+): (.+)' | 
    ForEach-Object {
    [PSCustomObject]@{
    Code = $_.Matches.Groups[1].Value
    Message = $_.Matches.Groups[2].Value
    }
    }

最佳实践

  1. 使用命名捕获组增强可读性:

    1
    2
    3
    4
    $logEntry = '2024-04-22 14:35 [WARN] Disk space below 10%'
    if ($logEntry -match '(?<Date>\d{4}-\d{2}-\d{2}).+\[(?<Level>\w+)\] (?<Message>.+)') {
    $matches['Level']
    }
  2. 预编译常用模式提升性能:

    1
    2
    3
    4
    $ipPattern = [regex]::new('^\d{1,3}(\.\d{1,3}){3}$')
    if ($ipPattern.IsMatch('192.168.1.1')) {
    # IP地址验证逻辑
    }
  3. 多行模式处理复杂文本:

    1
    2
    $multiLineText = Get-Content -Raw data.txt
    $matches = $multiLineText | Select-String -Pattern '(?s)<start>(.*?)<end>'