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

[玩转系统] 使用 PowerShell PSake 自动执行任务 [演练]

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

使用 PowerShell PSake 自动执行任务 [演练]


现在您已经了解了如何使用 PowerShell 脚本自动执行任务。
太棒了!但现在你已经得到了一堆杂乱无章的脚本和模块,还有手动脚本执行、计划任务等等的大杂烩。是时候给混乱带来一些秩序并实施称为 PowerShell PSake 的自动化编排引擎了。

PSake 是一个编写为 PowerShell 模块的编排引擎,它可以为您的脚本添加顺序,并让您完全控制什么时间以及在什么条件下运行。尽管 PSake 是一个构建自动化工具,其主要用例是在构建脚本中(通常由发布自动化场景中的构建服务器执行),但它在日常脚本场景中通常被忽视。让我们改变这一点。

在本教程中,您将了解 PSake 的工作原理以及一些可供您立即付诸实践的精彩示例!

先决条件

这篇文章将是一个教程,希望您能遵循。如果您想完全按照所介绍的方式进行操作,请确保您拥有:

  • Windows PowerShell 3+。本教程使用Windows PowerShell v5.1
  • 来自 Github 的 PSake zip 文件。本教程使用v4.9.0。

设置 PSake 模块

假设您的本地计算机上有来自 GitHub 的 PSake 项目,您首先需要执行几个步骤来进行设置。

  1. 解压从 GitHub 下载的 PSake zip 文件。
  2. 将提取的 ZIP 文件内容内的 src 文件夹移动到 $env:PSModulePath 下的路径,以确保 PowerShell 知道新模块。
  3. src文件夹重命名为PSake。
  4. 现在运行Get-Module PSake -ListAvailable 以确认它显示。如果您没有收到错误,则可以继续。

相关:了解和构建 PowerShell 模块

创建基本的 PowerShell PSake 脚本

要理解 PSake,您需要构建一些东西。让我们构建一个简单的 PSake 脚本来看看它能做什么。

  1. 使用单个任务创建名为 psakefile.ps1 的脚本。任务至少应该有一个名称和一个操作块。名称psakefile.ps1不是强制性的,但它是引擎期望的默认名称。

PSake 任务的基本形式与 PowerShell 函数非常相似:
一个或多个命令的容器,这些命令一起执行时可实现特定目标。这些命令进入传递给 Action 参数的脚本块。任务比函数有很多优点。在阅读过程中您将了解这些优势。

下面是一个带有简单任务的 psakefile.ps1 示例:

task HelloWorld -Action {
    Write-Host '*** Hello World ***' -ForegroundColor Yellow
}

2. 现在您已经构建了 PSake 文件,您可以使用 Invoke-PSake 命令从 PowerShell 控制台调用它,并将任务名称作为值传递给TaskList 参数。

Invoke-PSake 是 PSake 的执行引擎。此命令触发 psakefile.ps1 中定义的任务。您可以将任务名称或以逗号分隔的任务列表传递给 TaskList 参数。如果您正在执行多个任务,则每个任务都将按照您将其传递给 TaskList 的顺序执行,无论它们在 psakefile.ps1 中的位置如何。

以下是触发 HelloWorld 任务的方法:

Invoke-PSake -BuildFile C:\Work\psakefile.ps1 -TaskList 'HelloWorld'

只要保留名称 psakefile.ps1,并且将控制台设置为它所在的文件夹,您就可以省略 BuildFile 参数及其值。

  1. 运行 Invoke-PSake 将在控制台显示 PSake 输出。当您执行 psakefile.ps1 中的任务时,您将看到类似于以下内容的输出。

[玩转系统] 使用 PowerShell PSake 自动执行任务 [演练]

输出由以下部分组成:

  1. 有关 PSake 版本的详细信息。
  2. 每个构建任务在运行之前的名称(PSake 将每个任务视为构建任务)。在示例中:以青色执行 HelloWorld
  3. 任务产生的任何输出。在示例中:Hello World 为黄色。
  4. 成功/失败消息。在示例中:psake 成功... 呈绿色。
  5. 时间摘要(名为构建时间报告),其中包含每个任务的持续时间以及整个脚本的总持续时间。

使用 PSake 安装 SQL

在上一节中,您没有做太多事情,只是调用了一个虚拟 PSake 脚本。现在,基于这些知识并创建一个安装 SQL 的 PSake 脚本!

在此示例中,您将创建一个 PSake 脚本:

  1. 验证计算机上的可用磁盘空间。
  2. 从本地存储库下载 SQL ZIP 文件。
  3. 提取 ZIP 文件。
  4. 在 C 或 D 驱动器(两者中存在的一个)上运行安装。

接下来让我们看看如何利用 PSake 来完成这项工作。

设计构建块

PSake 就是关于编排任务的。每个任务都应该有自己唯一的名称,并且理想情况下应该执行单个原子操作,如 PowerShell 函数。使用这个概念,您可以描述以下步骤来为每个步骤构建任务。

  1. 验证磁盘空间
  2. 下载Sql
  3. 提取Sql
  4. 安装SqlDriveC
  5. 安装SqlDriveD

在这个阶段,您实际上并没有构建代码来执行任何操作;您只是在构建代码。您只需构建任务并创建 PSake 文件即可。您会注意到以下任务中的 Write-Host 引用;您稍后将添加到任务中。

您应该始终对每个任务使用 Description 参数。 Description 参数在执行任务和查看代码时提供有关每个任务的更多信息。

task ValidateDiskSpace -Description 'Validate Disk Free Space' -Action {
	
	Write-Host "`n   *** Checking disk free space ***`n" -ForegroundColor Yellow
	
}

task DownloadSql -Description 'Download SQL Setup' -Action {
	
	Write-Host "`n   *** Downloading SQL Setup from LAN ***`n" -ForegroundColor Yellow
	
}

task ExtractSql -Description 'Extract SQL Setup' -Action {
	
	Write-Host "`n   *** Extracting SQL Setup files ***`n" -ForegroundColor Yellow
	
}

task InstallSqlDriveC -Description 'Install SQL on C:' -Action {
	
	Write-Host "`n   *** Installing SQL Server on C drive ... please wait... ***`n" -ForegroundColor Yellow

}

task InstallSqlDriveD -Description 'Install SQL on D:' -Action {
	
	Write-Host "`n   *** Installing SQL Server on D drive ... please wait... ***`n" -ForegroundColor Yellow
	
}

定义任务执行顺序

您现在拥有一个包含一组任务的 PSake 文件。此时,您可以立即运行所有任务,也可以选择使用 Invoke-PSake 命令仅执行其中一些任务。

您可以使用 Invoke-PSakeTaskList 参数调用某些(或所有任务),就像您之前在简单的例子。如果要调用多个任务,请创建一个数组,并将每个任务的名称定义为一项,如下所示。

Invoke-PSake 将按照数组中定义的顺序运行每个任务。

$taskList = @()

$taskList += 'ValidateDiskSpace'
$taskList += 'DownloadSql'
$taskList += 'ExtractSql'
$taskList += 'InstallSqlDriveC'
$taskList += 'InstallSqlDriveD'

Invoke-PSake -TaskList $taskList

当您运行上面的代码时,您应该得到如下结果:

[玩转系统] 使用 PowerShell PSake 自动执行任务 [演练]

添加前提条件

也许仅当满足特定条件时您才需要执行某些操作。例如,在本教程的示例 SQL 安装脚本中,您可能需要在执行调用所述安装程序的任务之前测试存储安装程序的卷是否可用。

您可以使用 PreCondition 参数执行一段代码,该代码返回布尔值 True 或 False,指示该任务是否运行。

请注意下面示例中的 $installSqlOn_C_Drive$installSqlOn_D_Drive 变量。当Invoke-PSake调用此脚本时,这些变量将包含 True 或 False 值,具体取决于 C 或 D 卷是否存在。

在每个 task 行上,您可以看到每个任务都有一个 PreCondition 脚本块参数,其中包含这些变量的值。在运行时,InstallSqlDriveCInstallSqlDriveD 任务将运行,具体取决于这些变量。

$installSqlOn_C_Drive = (Test-Path -Path 'C:') -and (-not (Test-Path -Path 'D:'))
$installSqlOn_D_Drive = (-not (Test-Path -Path 'C:')) -and (Test-Path -Path 'D:')

task InstallSqlDriveC -Description 'Install SQL on C:' -PreCondition { $installSqlOn_C_Drive } -Action {
	
	Write-Host "`n   *** Installing SQL Server on C drive ... please wait... ***`n" -ForegroundColor Yellow
	
}

task InstallSqlDriveD -Description 'Install SQL on D:' -PreCondition { $installSqlOn_D_Drive } -Action {
	
	Write-Host "`n   *** Installing SQL Server on D drive ... please wait... ***`n" -ForegroundColor Yellow
	
}

任务参数

除了 ActionDescription 之外,任务还支持以下参数:

  • PreCondition - 返回布尔值的脚本块。如果为 False,则跳过特定任务。 (上面显示了一个使用示例)。
  • PostCondition - 验证步骤。返回布尔值的脚本块。 False 表示验证未能导致整个脚本停止。
  • PreAction - 在任务之前运行的脚本块。
  • PostAction - 任务成功完成后立即运行的脚本块。
  • ContinueOnError - 切换参数。如果使用,任务运行时可能发生的任何错误都不会导致整个脚本中断。
  • Depends - 在执行当前任务之前必须运行的任务名称(或任务名称列表)。 PSake 将使用此信息以正确的顺序执行任务依赖项。例如,如果任务 A 依赖于任务 B,则 PSake 引擎将在 A 之前运行 B。

乍一听,依赖机制听起来是个好主意。它有助于按逻辑顺序设置任务。但是,使用 Depends 参数将不同的任务粘合在一起,使得以后难以独立测试。但是,由于用户可以显式设置任务执行顺序并在调用 PSake 文件时传递此顺序 → 可以完全避免使用 Depends 参数。

接下来让我们看一下其中一些任务参数的用法示例:

添加前置操作和后置条件

使用上面示例中的 InstallSqlDriveD 任务作为起点,您可能还有其他安装请求。

也许您需要记录安装开始和结束的时间。您需要将这些时间记录到两个名为 SqlSetupStartDateSqlSetupEndDate 的环境变量中。其次,安装完成后,您需要验证D:\TempSqlFiles文件夹不存在。

幸运的是,PSake 任务参数 PreActionPostAction PostCondition (分别)完全满足这些新要求。以下是如何完成此操作的示例:

task InstallSqlDriveD -Description 'Install SQL on D:' -PreAction {

     Write-Host '*** Writing SQL install start time to env. var. SqlSetupStartDate ***' -ForegroundColor Yellow
     $date = Get-Date -Format 'yyyy-MM-dd HH:mm:ss'
[Environment]::SetEnvironmentVariable('SqlSetupStartDate',$date,'Machine')

 } -PreCondition { 

     $installSqlOn_D_Drive

 } -Action {  
  
     Write-Host '*** Installing SQL Server on D drive... please wait... ***' -ForegroundColor Yellow 

} -PostAction {     

    Write-Host '*** Writing SQL install end time to env. var. SqlSetupEndDate ***' -ForegroundColor Yellow     
    $date = Get-Date -Format 'yyyy-MM-dd HH:mm:ss'
[Environment]::SetEnvironmentVariable('SqlSetupEndDate',$date,'Machine') 

} -PostCondition { 
    
Write-Host '*** Verifying temp files deleted ***' -ForegroundColor Yellow
     # in case if the folder exits this will return False, causing the whole script to stop
     (-not (Test-Path -Path 'D:\TempSqlFiles'))

 }

在 Pester 测试中运行 PSake 脚本

无论您在哪里可以调用 PowerShell 脚本,都可以调用 PSake 文件。如果您使用 Pester 构建基础设施测试,则可以在测试中调用 PSake。

相关:为 PowerShell 编写 Pester 测试

例如,也许您有一个 Pester 测试来确认运行 DownloadSql 任务后文件夹中是否存在 SQL 安装 ZIP 文件。在这种情况下,您可以构建一个简单的 Pester 测试,并在测试中调用 DownloadSql 任务,并在运行后立即检查 ZIP 文件。

Describe 'SQL install with PSake' {

    It 'Downloads Sql files' {

        $setup = 'C:\Downloads\SqlSetup.zip'

        if(Test-Path -Path $setup)
        {
            Remove-Item -Path $setup
        }

        # the single task under test here is DownloadSql
        Invoke-PSake -BuildFile C:\Work\psakefile.ps1 -TaskList DownloadSql
        
        $setup | Should -Exist
    }
}

将参数传递给任务

一旦开始使用 PSake,您可能想要参数化一些任务。通常,使用 PowerShell 函数和脚本,您将向函数/脚本传递各种命名参数; PSake 是不同的。

要将参数传递到 PSake 文件,您可以使用 Properties 块来定义键/值对,然后 PSake 在文件中的每个任务中提供这些键/值对。

请务必在 PSake 文件顶部定义 Properties 块。所有 PSake 操作都是从上到下读取的。

例如,要将动态 SqlYearSqlVersion 变量传递给 PSake 文件中的每个任务,您可以定义它们如下所示。

Properties {
    $SqlYear = '2017'
    $SqlVersion = '14.0'
}

task -Name DownloadSql -Action {
    
    Write-Host "SQL version to install: SQL $SqlYear (version $SqlVersion)"

}

然后,当您使用 Invoke-PSake 调用 PSake 文件时,您将看到以下输出。请注意,$SqlYear$SqlVersion 变量已使用 属性块。

psake version 4.9.1
Copyright (c) 2010-2018 James Kovacs & Contributors

Executing DownloadSql
SQL version to install: SQL 2017 (version 14.0)

psake succeeded executing C:\Work\PSakefile.ps1

--------------------------------------------------
Build Time Report
--------------------------------------------------

Name        Duration
----        --------
DownloadSql 00:00:00
------      --------
Total:      00:00:00

使用 Properties 参数

如果您希望通过传统参数将参数传递给任务,PSake 可以提供帮助。您仍然需要将 Properties 块保留在 psakefile.ps1 的顶部,如上例所示,但 PSake 允许您覆盖这些值。

为此,请使用您要覆盖的每个键/值对定义一个哈希表。然后,将哈希表传递给 Properties 参数。 PSake 引擎将使用传入哈希表中的值,而不是在 psakefile.ps1 脚本中的 Properties 块中指定的值。

请注意 Properties Properties 参数之间的语法差异。在 Properties 块上,每一行都是一个变量,因此以美元符号为前缀,而 Properties 参数是一个哈希表,因此每个项目都是一个键,并且编写时没有领先$。另一个区别是哈希表前面带有@字符。

下面您可以看到使用 Properties 参数的示例。

$myNewProperties = @{
    SqlYear = '2019'
    SqlVersion = '15.0'
}

Invoke-PSake -TaskList DownloadSql -Properties $myNewProperties

PSake 任务模块化:任务作为文件

在某些时候,您的 PSake 文件可能会呈指数级增长,尤其是当您需要编排大型自动化任务时。为了确保您可以管理所有这些任务,您应该专注于模块化或拆分任务,以使事情更易于管理。

相关:如何在重构 PowerShell 脚本时幸存下来

在本教程的示例中,您正在处理五个任务:

  • 验证磁盘空间
  • 下载Sql
  • 提取Sql
  • 安装SqlDriveC
  • 安装SqlDriveD

这些任务中的每一个都在单个 pssakefile.ps1 脚本内定义。如果您预计随着时间的推移添加更多的任务,您应该将这些任务分成单独的文件,每个任务都放在其中,例如ValidateDiskSpace.ps1DownloadSql.ps1InstallSqlDriveD.ps1InstallSqlDriveD.ps1等。

例如 InstallSqlDriveD.ps1 将仅包含以下代码:

task InstallSqlDriveD -Description 'Install SQL on D:' -PreCondition { $installSqlOn_D_Drive } -Action {
	
	Write-Host "`n   *** Installing SQL Server on D drive ... please wait... ***`n" -ForegroundColor Yellow
	
}

任务移出后,使用 Include 函数将文件导入到 psakefile.ps1 中。完成此操作后,psakefile.ps1 内容将缩减为以下代码:

$installSqlOn_C_Drive = $true
$installSqlOn_D_Drive = $false

Include "$PSScriptRoot\ValidateDiskSpace.ps1"
Include "$PSScriptRoot\DownloadSql.ps1"
Include "$PSScriptRoot\ExtractSql.ps1"
Include "$PSScriptRoot\InstallSqlOnC.ps1"
Include "$PSScriptRoot\InstallSqlOnD.ps1"

Invoke-PSake触发psakefile.ps1脚本时,Invoke-PSake不知道也不关心任务是在psake文件中还是由包含方法。

下一步

PSake 是一个功能强大的脚本编排器,可用于多种用途:软件构建、CI/CD、包部署、安装程序创建等。你的想象力是唯一的限制。习惯使用 PSake 构建大型脚本会迫使您思考任务(代码构建块)。任务的概念是利用 PowerShell 语法,通过使用任务,您可以丰富现有的命令行知识。

使用 PSake 生成的代码变得更具可读性、可维护性并且更易于测试。经过一些练习后,您会发现将步骤划分为不同的任务可以更轻松地编写脚本。从中长期来看,少量的额外工作会带来巨大的回报。

您认为 PSake 在哪些方面适合您的工作项目?

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

取消回复欢迎 发表评论:

关灯