DSC 脚本资源

适用于:Windows PowerShell 4.0、Windows PowerShell 5.x

Windows PowerShell Desired State Configuration(DSC)中的 Script 资源提供了在目标节点上运行 Windows PowerShell 脚本块的机制。 Script 资源使用 GetScriptSetScript,并 TestScript 包含用于执行相应 DSC 状态操作的脚本块的属性。

提示

如果可能,最佳做法是使用定义的 DSC 资源而不是此资源。 Script 资源存在一些缺点,使得测试、维护和预测更加困难。

与其他 DSC 资源不同,Script 资源的每个属性都是键属性,并且此资源的 Get 方法只能返回当前状态的单个字符串。 不能保证此资源是幂等实现的,或者它将在任何系统上按预期工作,因为它使用自定义代码。 在目标系统上调用的情况下,无法对其进行测试。

在使用 Script 资源之前,请考虑是否可以改为 创作资源。 使用定义完善的 DSC 资源可使配置更易于读取和维护。

注意

此 DSC 资源的本文档介绍 PowerShell 7.2 之前随附的版本。 PSDscResources 模块包含Microsoft正式支持的新的和更新的 DSC 资源。 PowerShell 库中提供了 PSDscResources 模块。

有关详细信息和更新的文档,请参阅 PSDscResources 参考文档

语法

Script [string] #ResourceName
{
    GetScript = [string]
    SetScript = [string]
    TestScript = [string]
    [ Credential = [PSCredential] ]
    [ DependsOn = [string[]] ]
    [ PsDscRunAsCredential = [PSCredential] ]
}

注意

GetScript TestScriptSetScript 块存储为字符串。

性能

财产 描述
GetScript 返回节点的当前状态的脚本块。
SetScript DSC 在节点未处于所需状态时用来强制实施符合性的脚本块。
TestScript 一个脚本块,用于确定节点是否处于所需状态。
凭据 指示用于运行此脚本的凭据(如果需要凭据)。

通用属性

财产 描述
DependsOn 指示在配置此资源之前,必须运行另一个资源的配置。
PsDscRunAsCredential 设置用于运行整个资源的凭据。

注意

PsDscRunAsCredential common 属性已添加到 WMF 5.0 中,以允许在其他凭据的上下文中运行任何 DSC 资源。 有关详细信息,请参阅 将凭据用于 DSC 资源

其他信息

GetScript

DSC 不使用 GetScriptGet-DscConfiguration cmdlet 的输出执行 GetScript 来检索节点的当前状态。 GetScript 如果指定返回值,则返回值必须是包含其值为 String 的 Result 键的哈希表。

TestScript

DSC 执行 TestScript 以确定是否应运行 SetScript。 如果 TestScript 返回 $false,DSC 将执行 SetScript 将节点恢复为所需状态。 它必须返回布尔值。 $true 的结果表明节点符合,并且不应执行 SetScript

Test-DscConfiguration cmdlet 执行 TestScript 以检索节点符合 Script 资源。 但是,在这种情况下,无论 TestScript 块返回什么,SetScript 都不会运行。

注意

TestScript 的所有输出都是其返回值的一部分。 PowerShell 将未压缩的输出解释为非零,这意味着无论节点的状态如何,TestScript 都会返回 $true。 这会导致不可预知的结果、误报,并在故障排除过程中造成困难。

SetScript

SetScript 修改节点以强制实施所需状态。 如果 TestScript 脚本块返回 $false,DSC 将调用 SetScriptSetScript 不应有返回值。

例子

示例 1:使用脚本资源编写示例文本

此示例测试每个节点上是否存在 C:\TempFolder\TestFile.txt。 如果不存在,则使用 SetScript创建它。 GetScript 返回文件的内容,并且不使用其返回值。

Configuration ScriptTest
{
    Import-DscResource -ModuleName 'PSDesiredStateConfiguration'

    Node localhost
    {
        Script ScriptExample
        {
            SetScript = {
                $sw = New-Object System.IO.StreamWriter("C:\TempFolder\TestFile.txt")
                $sw.WriteLine("Some sample string")
                $sw.Close()
            }
            TestScript = { Test-Path "C:\TempFolder\TestFile.txt" }
            GetScript = { @{ Result = (Get-Content C:\TempFolder\TestFile.txt) } }
        }
    }
}

示例 2:使用脚本资源比较版本信息

此示例从创作计算机上的文本文件中检索符合 版本信息,并将其存储在 $version 变量中。 生成节点的 MOF 文件时,DSC 会将每个脚本块中的 $using:version 变量替换为 $version 变量的值。 在执行期间,合规 版本存储在每个节点上的文本文件中,并在后续执行时进行比较和更新。

$version = Get-Content 'version.txt'

Configuration ScriptTest
{
    Import-DscResource -ModuleName 'PSDesiredStateConfiguration'

    Node localhost
    {
        Script UpdateConfigurationVersion
        {
            GetScript = {
                $currentVersion = Get-Content (Join-Path -Path $env:SYSTEMDRIVE -ChildPath 'version.txt')
                return @{ 'Result' = "$currentVersion" }
            }
            TestScript = {
                # Create and invoke a scriptblock using the $GetScript automatic variable, which contains a string representation of the GetScript.
                $state = [scriptblock]::Create($GetScript).Invoke()

                if( $state.Result -eq $using:version )
                {
                    Write-Verbose -Message ('{0} -eq {1}' -f $state.Result,$using:version)
                    return $true
                }
                Write-Verbose -Message ('Version up-to-date: {0}' -f $using:version)
                return $false
            }
            SetScript = {
                $using:version | Set-Content -Path (Join-Path -Path $env:SYSTEMDRIVE -ChildPath 'version.txt')
            }
        }
    }
}

示例 3:在脚本资源中使用参数

此示例通过使用 using 范围从脚本资源中访问参数。 ConfigurationData 可以采用类似的方式进行访问。 与示例 2 一样,实现需要将版本存储在目标节点上的本地文件中。 本地路径和版本都是可配置的,将代码与配置数据分离。

Configuration ScriptTest
{
    param
    (
        [Version]
        $Version,

        [string]
        $FilePath
    )

    Import-DscResource -ModuleName 'PSDesiredStateConfiguration'

    Node localhost
    {
        Script UpdateConfigurationVersion
        {
            GetScript = {
                $currentVersion = Get-Content -Path $using:FilePath
                return @{ 'Result' = "$currentVersion" }
            }
            TestScript = {
                # Create and invoke a scriptblock using the $GetScript automatic variable,
                # which contains a string representation of the GetScript.
                $state = [scriptblock]::Create($GetScript).Invoke()

                if( $state['Result'] -eq $using:Version )
                {
                    Write-Verbose -Message ('{0} -eq {1}' -f $state['Result'],$using:version)
                    return $true
                }

                Write-Verbose -Message ('Version up-to-date: {0}' -f $using:version)
                return $false
            }
            SetScript = {
                Set-Content -Path $using:FilePath -Value $using:Version
            }
        }
    }
}

生成的 MOF 文件包括通过 using 范围访问的变量及其值。 它们将注入到每个脚本块中,该块使用变量。 为了简洁起见,将删除测试和设置脚本:

instance of MSFT_ScriptResource as $MSFT_ScriptResource1ref
{
 GetScript = "$FilePath ='C:\\Config.ini'\n\n $currentVersion = Get-Content -Path $FilePath\n return @{ 'Result' = \"$currentVersion\" }\n";
 TestScript = ...;
 SetScript = ...;
};

已知限制

  • 使用拉取或推送服务器模型时,在脚本资源中传递的凭据并不总是可靠的。 在这种情况下,请使用完整资源,而不是使用脚本资源。