当前位置:网站首页 > 更多 > 玩电脑 > 正文

[玩转系统] PowerShell 最佳实践:是的,它们存在 [指南]

作者:精品下载站 日期:2024-12-14 13:01:37 浏览:13 分类:玩电脑

PowerShell 最佳实践:是的,它们存在 [指南]


优雅、美观的代码清晰易读、易于管理,并且可以轻松使用 PowerShell 最佳实践添加功能。这是每个 PowerShell 开发人员的梦想。这是可能的。

虽然完美代码是情人眼里出西施,但这位拥有 12 年以上经验的 PowerShell 开发人员总是会回到一个概念:抽象。抽象。软件开发人员对这个术语打哈欠并说:“好吧,废话!”,但许多系统管理员和 IT 专业人员却摸不着头脑。

在本文中,您将了解什么是抽象以及如何将此编码方法应用于您编写的任何 PowerShell 代码。敬请关注!

理解抽象(在代码中)

[玩转系统] PowerShell 最佳实践:是的,它们存在 [指南]

简而言之,抽象意味着编写不直接与某些事物交互的代码,并且是几种 PowerShell 最佳实践之一。抽象意味着在“层”中编写代码,然后相互引用,最终围绕一个概念构建整个框架。

在编写代码时考虑到抽象可以帮助您松散耦合的代码随时间轻松更改,这是最好的 PowerShell 最佳实践之一。通过构建抽象层,您可以标准化您可能认为是混乱的代码。它可以帮助您组织甚至构建您无能为力的丑陋代码的接口。

构建“可移植代码”

将脚本或模块移动到另一台计算机并真正成功运行需要付出多少努力?需要更改多少代码?一、十、一百行?如果您发现自己陷入了这种或那种环境依赖性,那么您就没有充分利用抽象。

假设您有一行仅将文件保存到磁盘。该行是否以某种方式包装在函数中,或者是否裸露在您直接调用的脚本中?如果是后者,你可能做错了。

PS> Add-Content -Path 'somefile.txt' -Value 'XXXXX'

也许上面的行位于名为 idontknowbetter.ps1 的脚本中。当您想要执行某些操作时,可以直接从 PowerShell 控制台调用此脚本。

.\idontknowbetter.ps1

在当前的背景下,它运作良好。它将预期内容添加到 somefile.txt 文件中。有一天,您被调到一个新团队,拥有新的服务器场、新的 PC 和新的一切。您随身携带脚本是因为您要在新团队中执行类似的任务。需要修改脚本中的代码吗?当然,你知道! somefile.txt 位于不同的位置。

您必须对 PowerShell 代码进行的更改越多,您做的错误就越多。您应该专注于使代码在许多不同的上下文和用例中具有弹性。最好的方法是通过参数。

现在,如果您将该代码放在包含在如下函数中的模块中会怎样?您现在不是直接调用脚本,而是间接向该文件添加内容。您已经“抽象”了向该特定文件添加内容。现在,您不再直接调用脚本,而是调用 New-Stuff 函数来处理它。

## ImSmart.psm1

function New-Stuff {
	param(
		[Parameter()]
		[string]$FilePath
	)
	
	## do some stuff here to get the value
	Add-Content -Path $FilePath -Value 'XXXXX'

	## maybe do some stuff down here
}

为什么这个背景很重要?因为当您转到另一个团队时,您根本不必更改任何代码。您只需更改参数值即可。您将“执行”与“调用”分开,使代码灵活且可移植。将事物分开是 PowerShell 最佳实践中的一项重要任务。

标准化

抽象的另一个巨大好处是标准化,这是 PowerShell 最佳实践的另一个。使用上面的示例,现在您可能需要执行一些其他相关任务。 New-Stuff 函数向文件添加一些内容。也许现在您需要一个类似的函数来读取该文件。您决定创建一个名为 Remove-Stuff 的函数。您已经可以开始看到标准化的实施。名词是一样的!

## ImSmart.psm1

function New-Stuff {
	param(
		[Parameter()]
		[string]$FilePath
	)
	
	## do some stuff here to get the value
	Add-Content -Path $FilePath -Value 'XXXXX'

	## maybe do some stuff down here
}

function Remove-Stuff {
	param(
		[Parameter()]
		[string]$FilePath
	)
	
	## Remove some value here and add it to the file's contents

	Set-Content -Path $FilePath -Value 'XXXXX'

	## maybe do some stuff down here
}

您现在可以运行 New-StuffRemove-Stuff 来执行某些操作。这些名称非常有意义,您甚至可以期望其他函数是 Set-StuffUpdate-Stuff 等。

您正在标准化代码。您正在创建一个遵循可预测模式的文件界面。

构建虚拟机管理工具

当涉及到 PowerShell 最佳实践时,这种空中楼阁的抽象概念有时很难让您理解。让我们构建一个小演示项目,希望能让大家理解这一 PowerShell 最佳实践之一。

假设您已经构建了一些启动、停止和管理 Hyper-V 虚拟机 (VM) 的脚本。您的团队管理公司的虚拟机管理程序之一,在本例中为 Hyper-V。

由于 VM 是 Hyper-V,因此您决定使用 HyperV PowerShell 模块。该模块仅专注于 Hyper-V VM。也许您有一些如下所示的代码:

#requires -Module HyperV
[CmdletBinding()]
param(
	[Parameter(Mandatory)]
	[string]$VmName
)

## Use the Start-Vm cmdlet in the HyperV module to start a VM
Start-Vm -Name $VmName

## Do some stuff to the VM here

## Use the Stop-Vm cmdlet in the HyperV module to stop the VM
Stop-Vm -Name $VmName

这个脚本运行得很好。 您已经创建了一个参数,这是一个很好的开始。此参数允许您针对许多不同的虚拟机运行此脚本,而无需更改脚本内的任何代码。好工作!

通过此脚本,您已经创建了一层抽象。您决定需要一个脚本来调用这些命令并在其间运行一些其他代码,而不是直接在 PowerShell 控制台上运行 Start-VmStop-VM。您创建了它,现在,您只需运行 .\Set-MyVM.ps1Start-VM 和 Stop-VM 或类似的东西。

您没有直接调用 StartStop-VM cmdlet。您已经抽象了这样做的需要,而只是与脚本交互,而不是与 cmdlet 本身交互。 PowerShell 工作最佳实践!

利用抽象来发挥你的优势

有一天,您的老板过来告诉您,您的团队现在继承了公司的 VMWare 集群。呃哦!现在您认为需要创建一组全新的脚本或模块来管理 VMWare 虚拟机。您可能必须这样做,但您可以决定将 VMware 功能集成到当前的解决方案中。

注意代码中的模式。这个新需求是否可以轻松地与现有解决方案配合使用,而不是构建全新的代码库?两种需求可以共享哪些功能?

虚拟机就是虚拟机,对吗? VMware VM 和 Hyper-V VM 类似;它们只是运行在不同的虚拟机管理程序上。他们之间有什么共同点?您可以启动和停止这两种虚拟机。牢记这些 PowerShell 最佳实践!

遵循 PowerShell 最佳实践,而不是创建另一个脚本,为什么不将它们集成到当前的通用 Set-MyVM.ps1 脚本中。一种方法是添加一个名为 Hypervisor 的参数。获得该 HyperVisor 参数后,您就可以构建所需的逻辑来确定您的脚本是否应运行 HyperV 代码的某些 VMWare 代码。

请注意,以下代码片段有一个名为 VMWare 的必需模块。您需要确保您的脚本现在支持这两种情况。此外,它现在还具有一些 switch 语句形式的条件逻辑,可根据所选虚拟机管理程序的类型执行一些不同的操作。

#requires -Module HyperV, VmWare
[CmdletBinding()]
param(
	[Parameter(Mandatory)]
	[string]$VmName,

	[Parameter()]
	[ValidateSet('HyperV','VmWare')]
	[string]$Hypervisor
)

switch ($Hypervisor) {
	'HyperV' {
		## Use the Start-Vm cmdlet in the HyperV module to start a VM
		Start-Vm -Name $VmName

		## Do some stuff to the VM here

		## Use the Stop-Vm cmdlet in the HyperV module to stop the VM
		Stop-Vm -Name $VmName
		break
	}
	'VmWare' {
		## Use whatever command the VmWare module has in it to start the VM
		Start-VmWareVm -Name $VmName

		## do stuff to the VmWare VM

		## Use whatever command the VmWare module has in it to stop the VM
		Stop-VmWareVm -Name $VmName
		break
	}
	default {
		"The hypervisor you passed [$_] is not supported"
	}
}

或者,如果可能的话,这是更好的方法,您可以动态地找出传递的虚拟机类型,然后根据该代码的结果决定要运行的代码。这就是 PowerShell 最佳实践思维。

始终尝试尽可能多地抽象概念,作为 PowrShell 最佳实践的要素之一。如果您可以在代码中得出值,则不要创建参数。如果不需要,不要强迫运行脚本的人运行必要的命令。您可能没有抽象出足够的任务。

请参阅下面的示例,了解如何动态地找出虚拟机管理程序。请注意,现在您将决策权留给了代码(这总是更好)。该脚本现在会自动知道虚拟机正在哪个虚拟机管理程序上运行。

#requires -Module HyperV, VmWare
[CmdletBinding()]
param(
	[Parameter(Mandatory)]
	[string]$VmName
)

function Get-Hypervisor {
	## simple helper function to determine the hypervisor
	param(
		[Parameter()]
		[string]$VmName
	)
	
	## Some code here to figure out what type of hypervisor this VM is running on

	## Return either 'HyperV' or 'VmWare'

}

$hypervisor = Get-Hypervisor -VmName $VmName

switch ($Hypervisor) {
	'HyperV' {
		## Use the Start-Vm cmdlet in the HyperV module to start a VM
		Start-Vm -Name $VmName

		## Do some stuff to the VM here

		## Use the Stop-Vm cmdlet in the HyperV module to stop the VM
		Stop-Vm -Name $VmName
		break
	}
	'VmWare' {
		## Use whatever command the VmWare module has in it to start the VM
		Start-VmWareVm -Name $VmName

		## do stuff to the VmWare VM

		## Use whatever command the VmWare module has in it to stop the VM
		Stop-VmWareVm -Name $VmName
		break
	}
	default {
		"The hypervisor you passed [$_] is not supported"
	}
}

您现在已经发现了 Hyper-V 和 VMWare VM 之间的共性,并构建了一个解决方案来管理它们!您现在已经创建了一个抽象层,允许您使用单个脚本管理两种不同的虚拟机类型。

结论

抽象、标准化、解耦和其他软件开发术语的概念一开始有点难以掌握。为什么?因为这些方法并不是黑白分明的。它们是更高层次的设计考虑。

您可能会认为自己不需要关心这些胡言乱语,但事实并非如此。你会像我一样学习;艰难的方式。您将编写数千个脚本来重新发明轮子,努力进行更改,并且花费的时间比您应有的时间要长得多。

在编写遵循 PowerShell 最佳实践的代码时,请始终牢记抽象概念。始终识别模式。始终尝试尽可能标准化。构建这样的代码一开始花费更长的时间,但您最终将获得漂亮的代码重用和构建整个解决方案而不是脚本的回报。

您需要 登录账户 后才能发表评论

取消回复欢迎 发表评论:

关灯