我在尝试使用PowerShell所需状态配置脚本来配置内部应用程序时遇到了很多麻烦.问题的根源是我似乎无法将配置数据传递给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"
}
}
}
Run Code Online (Sandbox Code Playgroud)
作为参考,我的配置数据如下所示:
$config = @{
AllNodes = @(
@{
NodeName = "*"
ConfigFolder = "C:\myapp\config"
ConfigFile = "C:\myapp\config\config.txt"
}
@{
NodeName = "ServerA"
Enabled = "true"
}
@{
NodeName = "ServerB"
Enabled = "false"
}
)
}
Run Code Online (Sandbox Code Playgroud)
我正在使用DSC进行以下操作:
$mof = MyApp -ConfigurationData $config;
Start-DscConfiguration MyApp –Wait –Verbose;
Run Code Online (Sandbox Code Playgroud)
当我应用此配置时,它很乐意创建该文件夹,但无法对配置文件执行任何操作.看看下面的输出,很明显,因为$ Node变量在ConfigurationFile/TestScript范围内是null,但我不知道如何从该块中引用它.
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.
Run Code Online (Sandbox Code Playgroud)
我已经烧了一整天在线搜索这个特定的问题,但所有变量,参数和配置数据的例子都使用File和Registry资源或其他非脚本资源,我已经在"ConfigurationFolder"中工作了"阻止我的剧本.我坚持的是如何从像"ConfigurationFile"这样的脚本资源中引用配置数据.
我画了一个完整的空白,所以任何帮助将不胜感激.如果所有其他方法都失败了,我可能需要为每个服务器创建一个单独的"配置"脚本并对这些值进行硬编码,如果可能的话我真的不想这样做.
干杯,
麦克风
小智 34
改变这个:$Node.ConfigFolder到$using:Node.ConfigFolder.
如果您有一个被调用的变量,$Foo并且您希望将其传递给脚本DSC资源,那么请使用$using:Foo
mcl*_*ton 10
根据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;
}
Run Code Online (Sandbox Code Playgroud)
我的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);
}
Run Code Online (Sandbox Code Playgroud)
您必须注意配置数据中的引号和转义,因为Format-DscScriptBlock只执行文字替换,但这对我的目的来说已经足够了.
解决此问题的一种非常优雅的方法是使用常规{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))
Run Code Online (Sandbox Code Playgroud)
此外,通过简单地使用文本编辑器查看生成的.mof文件,一个很好的方法来确定您是否正确执行此操作; 如果你看一下生成的TestScript/GetScript/SetScript成员,你会发现代码片段确实是一个字符串.$占位符值应该已经在那里被替换.
小智 7
ConfigurationData仅在编译MOF文件时存在,而不是在DSC引擎应用脚本时的运行时.Script资源的SetScript,GetScript和TestScript属性实际上是字符串,而不是脚本块.
可以生成这些脚本字符串(已经扩展了ConfigurationData中的所有必需数据),但是必须小心正确使用转义符,子表达式和引号.
我在原始的TechNet主题上发布了一个简短的例子,网址是http://social.technet.microsoft.com/Forums/en-US/2eb97d67-f1fb-4857-8840-de9c4cb9cae0/dsc-configuration-data-for-脚本资源?论坛= winserverpowershell
| 归档时间: |
|
| 查看次数: |
17679 次 |
| 最近记录: |