【问题标题】:PowerShell DSC - how to pass configuration parameters to ScriptResources?PowerShell DSC - 如何将配置参数传递给 ScriptResources?
【发布时间】:2014-04-28 16:57:19
【问题描述】:

我在尝试让 PowerShell Desired State Configuration 脚本工作以配置内部应用程序时遇到了很多麻烦。问题的根源是我似乎无法将配置数据传递到 ScriptResource 中(至少不是我尝试这样做的方式)。

我的脚本应该为我们的内部应用程序创建一个配置文件夹,然后将一些设置写入文件:

configuration MyApp {
    param (
        [string[]] $ComputerName = $env:ComputerName
    )
    node $ComputerName {

        File ConfigurationFolder {
            Type = "Directory"
            DestinationPath = $Node.ConfigFolder
            Ensure = "Present"
        }

        Script ConfigurationFile {
            SetScript = {
                write-verbose "running ConfigurationFile.SetScript";
                write-verbose "folder = $($Node.ConfigFolder)";
                write-verbose "filename = $($Node.ConfigFile)";
                [System.IO.File]::WriteAllText($Node.ConfigFile, "enabled=" + $Node.Enabled);
            }
            TestScript = {
                write-verbose "running ConfigurationFile.TestScript";
                write-verbose "folder = $($Node.ConfigFolder)";
                write-verbose "filename = $($Node.ConfigFile)";
                return (Test-Path $Node.ConfigFile);
            }
            GetScript = { @{Configured = (Test-Path $Node.ConfigFile)} }         
            DependsOn = "[File]ConfigurationFolder"
        }

    }
}

作为参考,我的配置数据如下所示:

$config = @{
    AllNodes = @(
        @{
            NodeName = "*"
            ConfigFolder = "C:\myapp\config"
            ConfigFile = "C:\myapp\config\config.txt"
        }
        @{
            NodeName = "ServerA"
            Enabled = "true"
        }
        @{
            NodeName = "ServerB"
            Enabled = "false"
        }
    )
}

我正在使用以下内容应用 DSC:

$mof = MyApp -ConfigurationData $config;
Start-DscConfiguration MyApp –Wait –Verbose;

当我应用此配置时,它会愉快地创建文件夹,但无法对配置文件执行任何操作。查看下面的输出,很明显这是因为 $Node 变量在 ConfigurationFile / TestScript 范围内为空,但我不知道如何从该块中引用它。

LCM:  [ Start  Resource ]  [[Script]ConfigurationFile]
LCM:  [ Start  Test     ]  [[Script]ConfigurationFile]
                           [[Script]ConfigurationFile] running ConfigurationFile.TestScript
                           [[Script]ConfigurationFile] node is null = True
                           [[Script]ConfigurationFile] folder =
                           [[Script]ConfigurationFile] filename =
LCM:  [ End    Test     ]  [[Script]ConfigurationFile]  in 0.4850 seconds.

我已经花了一整天的时间在网上搜索这个特定问题,但是所有变量、参数和配置数据的示例都使用文件和注册表资源或其他非脚本资源,我已经开始使用这些资源了我脚本中的“ConfigurationFolder”块。我坚持的是如何从脚本资源中引用配置数据,比如我的“ConfigurationFile”。

我已经画了一个完整的空白,所以任何帮助将不胜感激。如果一切都失败了,我可能必须为每个服务器创建一个单独的“配置”脚本并对值进行硬编码,如果可能的话,我真的不想这样做。

干杯,

迈克

【问题讨论】:

    标签: powershell dsc


    【解决方案1】:

    将这个:$Node.ConfigFolder 更改为 $using:Node.ConfigFolder

    如果您有一个名为 $Foo 的变量,并且希望将其传递给脚本 DSC 资源,请使用 $using:Foo

    【讨论】:

    【解决方案2】:

    根据 David 的回答,我编写了一个实用函数,它将我的脚本块转换为字符串,然后执行非常简单的搜索和替换以扩展对配置数据的引用,如下所示。

    function Format-DscScriptBlock()
    {
        param(
            [parameter(Mandatory=$true)]
            [System.Collections.Hashtable] $node,
            [parameter(Mandatory=$true)]
            [System.Management.Automation.ScriptBlock] $scriptBlock
        )
        $result = $scriptBlock.ToString();
        foreach( $key in $node.Keys )
        {
            $result = $result.Replace("`$Node.$key", $node[$key]);
        }
        return $result;
    }
    

    然后我的 SetScript 变成:

    SetScript = Format-DscScriptBlock -Node $Node -ScriptBlock {
                    write-verbose "running ConfigurationFile.SetScript";
                    write-verbose "folder = $Node.ConfigFolder";
                    write-verbose "filename = $Node.ConfigFile)";
                    [System.IO.File]::WriteAllText("$Node.ConfigFile", "enabled=" + $Node.Enabled);
                }
    

    您必须注意配置数据中的引号和转义,因为 Format-DscScriptBlock 仅执行文字替换,但这对我的目的来说已经足够了。

    【讨论】:

      【解决方案3】:

      解决这个问题的一个非常优雅的方法是使用常规的{0} 占位符。通过应用-f 运算符,可以将占位符替换为其实际值。

      这种方法的唯一缺点是,除了占位符(例如哈希表或 for 循环)之外,您不能使用花括号 { },因为 -f 运算符要求花括号包含整数。

      您的代码如下所示:

              SetScript = ({ 
                  Set-ItemProperty "IIS:\AppPools\{0}" "managedRuntimeVersion" "v4.0"
                  Set-ItemProperty "IIS:\AppPools\{0}" "managedPipelineMode" 1 # 0 = Integrated, 1 = Classic
              } -f @($ApplicationPoolName))
      

      此外,确定您是否正确执行此操作的一个好方法是使用文本编辑器查看生成的 .mof 文件;如果您查看生成的 TestScript / GetScript / SetScript 成员,您会发现代码片段确实是一个字符串。 $placeholder 值应该已经被替换了。

      【讨论】:

      • 其实你可以使用花括号,你只需要将它们加倍(所以{变成{{}变成}})。
      • 谢谢,我会使用这个而不是 $using 方法,因为它将整个 psd 对象存储在 MOF 中,而这个存储所需的值。绝对优雅,因为它是一个数组,所以我可以使用 {0}、{1} 等。
      【解决方案4】:

      ConfigurationData 仅在编译 MOF 文件时存在,而不是在 DSC 引擎应用您的脚本时的运行时存在。 Script 资源的 SetScript、GetScript 和 TestScript 属性实际上是字符串,而不是脚本块。

      可以生成这些脚本字符串(您的 ConfigurationData 中的所有必需数据都已展开),但您必须小心正确使用转义、子表达式和引号。

      我在http://social.technet.microsoft.com/Forums/en-US/2eb97d67-f1fb-4857-8840-de9c4cb9cae0/dsc-configuration-data-for-script-resources?forum=winserverpowershell 的原始 TechNet 线程上发布了一个简短的示例

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2019-10-21
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-08-23
        • 1970-01-01
        相关资源
        最近更新 更多