*意识到这已经很老了,但只是偶然发现它并想为您的 DSC 变大/笨拙的场景提供建议。
我首先将您的节点定义文件与配置文件分开,然后映射一个引用。我将我的文件并排保存,所以我会参考如下。我不会进入加密,好的 MS 指导。
$File = 'WebApp\NodeDefinitions.psd1'
$Parent = Split-Path -Parent $PSScriptRoot
$Path = Join-Path $Parent $File
WebApp -RunAs $RunAs -ConfigurationData "$Path" -OutputPath $localpath -verbose
现在,为了让事情变得更加动态,您可以在节点定义文件中创建数组或哈希表集合,如下所示,用于文件夹、站点等。 *我确实必须更改 xcertificatedsc 以使其传递一组帐户,如果您需要帮助,这并不难。
@{
NodeName = "Vm-Web-1"
Role = "DevWeb","Web","WS","SMP"
IUSRS = "Domain\User1$","Domain\User2$"
Folders = @(
("Dir1","F:\inetpub\wwwroot\SomeApp","Present"),
("Dir2","F:\inetpub\wwwroot\SomeApp2","Present"),
("Dir3","F:\inetpub\wwwroot\SomeApp2","Absent") #If something's moved or a mistake
)
Sites = @(
@("MyApp1","Domain\User1$","Present"),
@("MyApp2","Domain\User2$","Present")
)
CertPerms= @{
"somecert@domain.com" = @("Domain\User1$","Domain\User2$")
}
},
然后我在我的配置中引入非节点数据,以便网站更便携,我们稍后将加入配置 ps1 文件。我还将展示如何迭代文件夹创建。
@{
Name = "MyApp1"
PoolConfigName = "ApMyApp1"
PoolName = "ApMyApp1"
PoolRtVer = "v4.0"
SiteConfigName = "WaMyApp1"
SitePath = "ApMyApp1"
SiteName = "ApMyApp1"
SiteDepends = "[File]Dir1"
},
@{
Name = "MyApp2"
PoolConfigName = "ApMyApp2"
PoolName = "ApMyApp2"
PoolRtVer = "v4.0"
SiteConfigName = "WaMyApp2"
SitePath = "ApMyApp2"
SiteName = "ApMyApp2"
SiteDepends = "[File]Dir2"
},
要遍历文件夹,只需在 nodedefintion 文件中引用数组的元素
Foreach($Folder in $Node.Folders){
File $Folder[0]
{
Ensure = $Folder[2]
Type = "Directory"
DestinationPath = $Folder[1]
}
}
站点加入稍微复杂一些,我对当前引用元素而不是更易于阅读的名称的情况并不太满意,但它确实有效。加入节点/非节点数据后,脚本的下一部分用于较少使用的参数。例如,我们不会在始终运行模式下引入很多池(除非在相关应用程序的 web.config 中验证了正确的页面初始化)。如果我正在引入一个站点并且相关服务帐户在域上未处于活动状态,我将确保相关池已停止,因此它不会淹没 iis 工作进程。否则,您应该能够绘制出节点部分(数组引用)与非节点站点数据中设置的内容。
Foreach($SiteName in $Node.Sites){
$Site = $ConfigurationData.Sites.Where{$_.Name -eq $SiteName[0]}
if ([string]::IsNullOrWhiteSpace($Site.PoolIdleTO))
{
$PoolIdleTO = 20
}
else
{
$PoolIdleTO = $Site.PoolIdleTO
}
if ([string]::IsNullOrWhiteSpace($Site.PoolStartMode))
{
$PoolStartMode = "OnDemand"
}
else
{
$PoolStartMode = $Site.PoolStartMode
}
if ([string]::IsNullOrWhiteSpace($SiteName[3]))
{
$State = "Started"
}
else
{
$State = $SiteName[3]
}
xWebAppPool $Site.PoolConfigName
{
Name = $Site.PoolName
Ensure = $SiteName[2]
State = $State
autoStart = $true
enable32BitAppOnWin64 = $false
enableConfigurationOverride = $true
managedPipelineMode = "Integrated"
managedRuntimeVersion = $Site.PoolRtVer
startMode = $PoolStartMode
queueLength = 1000
cpuAction = "KillW3wp"
cpuLimit = 95000
cpuResetInterval = (New-TimeSpan -Minutes 1).ToString()
cpuSmpAffinitized = $false
cpuSmpProcessorAffinityMask = 4294967295
cpuSmpProcessorAffinityMask2 = 4294967295
identityType = 'SpecificUser'
Credential = New-Object System.Management.Automation.PSCredential($SiteName[1], (ConvertTo-SecureString $Node.GmsaPwd.ToString() -AsPlainText -Force))
idleTimeout = (New-TimeSpan -Minutes $PoolIdleTO).ToString()
idleTimeoutAction = 'Suspend'
loadUserProfile = $false
logEventOnProcessModel = 'IdleTimeout'
logonType = 'LogonBatch'
manualGroupMembership = $false
maxProcesses = 1
pingingEnabled = $true
pingInterval = (New-TimeSpan -Seconds 30).ToString()
pingResponseTime = (New-TimeSpan -Seconds 90).ToString()
setProfileEnvironment = $false
shutdownTimeLimit = (New-TimeSpan -Seconds 90).ToString()
startupTimeLimit = (New-TimeSpan -Seconds 90).ToString()
orphanActionExe = ''
orphanActionParams = ''
orphanWorkerProcess = $false
loadBalancerCapabilities = 'HttpLevel'
rapidFailProtection = $true
rapidFailProtectionInterval = (New-TimeSpan -Minutes 1).ToString()
rapidFailProtectionMaxCrashes = 5
autoShutdownExe = 'C:\Windows\System32\iisreset.exe'
autoShutdownParams = ''
disallowOverlappingRotation = $false
disallowRotationOnConfigChange = $false
logEventOnRecycle = 'Time,Requests,Schedule,Memory,IsapiUnhealthy,OnDemand,ConfigChange,PrivateMemory'
restartMemoryLimit = 3221225472
restartPrivateMemoryLimit = 8000000
restartRequestsLimit = 20000000
restartTimeLimit = (New-TimeSpan -Minutes 0).ToString()
restartSchedule = "00:00:00"
DependsOn = '[WindowsFeature]IIS'
}
<#!!!Imperative method (runs immediately) to ensure service accounts get IIS metabase access!!#
#Need to move this into the function with a flag, obviously there'll be looping challenges...
Invoke-Command -Session (New-PSSession -ComputerName $Node.NodeName -Credential $RunAs -SessionOption (New-PSSessionOption -SkipCACheck -SkipCNCheck -SkipRevocationCheck)) -ScriptBlock {
param ([string] $User)
C:\Windows\Microsoft.NET\Framework64\v4.0.30319\aspnet_regiis.exe -ga $User
} -ArgumentList $SiteName[1]
#>
cIisAccess "IisMetabaseAccess$($Site.SiteConfigName + $SiteName[1])"
{
Account = $SiteName[1]
Ensure="Present"
}
xWebApplication $Site.SiteConfigName
{
Website = "Default Web Site"
Name = $Site.SiteName
WebAppPool = $Site.PoolName
PhysicalPath = $Node.DfSitePath + $Site.SitePath
Ensure = $SiteName[2]
PreloadEnabled = $true
DependsOn = "[xWebAppPool]$($Site.PoolConfigName)",$($Site.SiteDepends)
}
}
需要注意的一点是我使用 GMSA,因此没有密码,并且使用了 kerberos 令牌。由于 PSCredential 的要求,您仍然需要虚假密码参考,因此您可以像下面这样向您的 allnodes 数据添加一些内容以供参考:
GmsaPwd = "none"
还有很多关于使用角色的指导,但下面是一个简单的参考。
Node $AllNodes.Where{$_.Role -contains "Web"}.NodeName
{
#Embed site/folder iterators here if preferred
}