Exchange 2010 Powershell指令碼攻略(七)
CollectReplicationMetrics
param(
[string] $DagName,
[string[]] $DatabaseNames,
[string] $ReportAlias,
[string] $TemporaryDataPath,
[string] $ReportPath,
[TimeSpan] $Duration = [TimeSpan]::Parse("1.00:00:00"),
[TimeSpan] $Frequency = [TimeSpan]::FromSeconds(10),
[switch] $Verbose,
[switch] $ProcessOnly)
Set-StrictMode -Version 2.0
# Define all the script-wide variables
$LocalMachine = [environment]::MachineName
# Dag object for which perf info should be collected
$Dag = $null
#List of databases for which performance counter to be collected
$Databases = @()
# Hash table to servers to databases applicable for the servers
$ServerDatabaseHash = @{}
#
# Define all helper functions for Collect Replication Metrics script
#
function NonBoring-Sleep
{
param ([int] $Seconds)
if ($Verbose)
{
$crChar = [char]::ConvertFromUtf32(13)
$currentTime = [DateTime]::Now
$targetTime = $currentTime.AddSeconds($Seconds)
while ($currentTime -lt $targetTime)
{
$diff = $targetTime - $currentTime
$outputStr = [string]::Format("{0}Time remaining until next collection: {1:D2}:{2:D2}:{3:D2}", $crChar, $diff.Hours, $diff.Minutes, $diff.Seconds)
write-host $outputStr -ForegroundColor Yellow -NoNewline
start-sleep -Seconds 1
$currentTime = [DateTime]::Now
}
write-host "$crChar $crChar" -NoNewline
}
else
{
start-sleep -Seconds:$Seconds
}
}
function ShowError([string] $errorString)
{
write-error $errorString -ErrorAction:Stop
}
function LoadSnapin
{
$snapIn = Get-PSSnapin Microsoft.Exchange.Management.PowerShell.E2010 -ErrorAction:SilentlyContinue
if ($snapIn -eq $null)
{
Add-PSSnapin Microsoft.Exchange.Management.PowerShell.E2010
}
}
# Function declarations
function Trace([string] $traceString)
{
if ($Verbose)
{
write-host $traceString
}
}
function FindLocalDagName
{
$dagName = $null
$mbxServer = Get-MailboxServer $LocalMachine -ErrorAction:SilentlyContinue
if ($mbxServer -ne $Null)
{
$dagId = $mbxServer.DatabaseAvailabilityGroup
if ($dagId -ne $Null)
{
$dagName = $dagId.Name
}
else
{
ShowError("$LocalMachine is a standalone exchange server. It is not part of any database availability group")
}
}
else
{
ShowError("$LocalMachine is not a mailbox server")
}
return $dagName
}
function FindDag
{
param([string] $DagName)
$dag = $null
if ($DagName)
{
$dag = Get-DatabaseAvailabilityGroup $DagName -ErrorAction:SilentlyContinue
}
if ($dag -eq $Null)
{
ShowError("Unable to find database availability group named $DagName")
}
return $dag
}
function DetermineServersAndDatabases
{
param ([string[]] $databaseNames, [ref] $databases, [ref] $serverDbTable)
$serverHash = @{}
$databaseHash = @{}
$filteredDatabaseHash = @{}
if ($databaseNames -ne $Null)
{
# If database is specified then find all the databases that match the wildcard
# that is specified in the argslist. Also make sure that a database appears
# only once in the list
foreach ($dbName in $databaseNames)
{
foreach ($db in get-mailboxdatabase $dbName -ErrorAction:SilentlyContinue)
{
if ($databaseHash[$db.Name] -eq $null)
{
$databaseHash[$db.Name] = $db
}
}
}
}
# Make sure that the matching databases are configured in the dag
foreach ($server in $dag.Servers)
{
$serverHash[$server.Name] = @()
foreach ($db in get-mailboxdatabase -Server:$server.Name -ErrorAction:SilentlyContinue)
{
if (($databaseNames -eq $null) -or ($databaseHash[$db.Name] -ne $null))
{
$filteredDatabaseHash[$db.Name] = $db
$serverHash[$server.Name] += $db
}
}
}
if ($filteredDatabaseHash.Count -eq 0)
{
ShowError("There are no databases to monitor for database availability group $(dag.Name)")
}
$databases.Value = $filteredDatabaseHash.Values
$serverDbTable.Value = $serverHash
}
function Write-CounterCsvHeader
{
param($outputFile)
$csvHeaderLine = "Iteration,SampleTime,Database,MountStatus,CopyStatus,CopyQueueLength,LogGenerationRate,LogReplayRate"
$csvHeaderLine > $outputFile
}
function Write-ServerCsvHeader
{
param($outputFile)
$csvHeaderLine = "Iteration,SampleTime,IsReachable"
$csvHeaderLine > $outputFile
}
function Save-CounterInCsvFormat
{
param($iteration, $sampleTime, $dbName, $dbPerfMap, $outputFile)
$arrList = new-object System.Collections.ArrayList
# Iteration number of the collection
[void] $arrList.Add($iteration)
$strTime = Get-CustomDateString ($sampleTime)
# Time when the sample was collected
[void] $arrList.Add($strTime)
# Database name
[void] $arrList.Add($dbName)
# MountStatus => Mounted,Dismounted,Unavailable
$mountStatus = "Unavailable"
$copyStatus = new-object System.Collections.ArrayList
$entry = $dbMap[$dbName]
if ($entry)
{
if (Get-BooleanState ($entry.AmPerf) ("Database Mounted"))
{
$mountStatus = "Mounted"
}
else
{
$mountStatus = "Dismounted"
}
if ($entry.ReplPerf)
{
if (Get-BooleanState ($entry.ReplPerf) ("Initializing"))
{
[void] $copyStatus.Add("Initializing")
}
if (Get-BooleanState ($entry.ReplPerf) ("Suspended"))
{
[void] $copyStatus.Add("Suspended")
}
if (Get-BooleanState ($entry.ReplPerf) ("FailedSuspended"))
{
[void] $copyStatus.Add("FailedSuspended")
}
if (Get-BooleanState ($entry.ReplPerf) ("Resynchronizing"))
{
[void] $copyStatus.Add("Resynchronizing")
}
if (Get-BooleanState ($entry.ReplPerf) ("Disconnected"))
{
[void] $copyStatus.Add("Disconnected")
}
}
else
{
[void] $copyStatus.Add("Unavailable")
}
}
# Append mount status
[void] $arrList.Add($mountStatus)
# Append copy status
[void] $arrList.Add([string]::Join(":",$copyStatus.ToArray()))
if ($entry -and $entry.ReplPerf)
{
[void] $arrList.Add($entry.ReplPerf["CopyQueueLength"])
[void] $arrList.Add($entry.ReplPerf["log generation rate on source (generations/sec)"])
[void] $arrList.Add($entry.ReplPerf["log replay rate (generations/sec)"])
}
else
{
[void] $arrList.Add([string]::Empty)
[void] $arrList.Add([string]::Empty)
[void] $arrList.Add([string]::Empty)
}
$csvLine = [string]::Join(",",$arrList)
$csvLine >> $outputFile
}
function Create-EmptyServerRecord
{
param ([string] $serverName)
$record = new-object object
$emptyTs = new-object TimeSpan
add-member -inputobject $record -MemberType NoteProperty "Name" -Value $serverName
add-member -inputobject $record -MemberType NoteProperty "DurationMeasured" -Value $emptyTs
add-member -inputobject $record -MemberType NoteProperty "DurationUnavailable" -Value $emptyTs
add-member -inputobject $record -MemberType NoteProperty "AverageDurationMounted" -Value $emptyTs
add-member -inputobject $record -MemberType NoteProperty "AverageDurationDismounted" -Value $emptyTs
add-member -InputObject $record -MemberType NoteProperty "AverageLogReplayRate" -Value 0
add-member -InputObject $record -MemberType NoteProperty "PeakLogReplayRate" -Value 0
add-member -InputObject $record -MemberType NoteProperty "DbInfo" -Value @{}
add-member -InputObject $record -MemberType NoteProperty "ServerInfo" -Value $null
return $record
}
function Create-EmptyDatabaseRecord
{
param ([string] $databaseName)
$record = new-object object
$emptyTs = new-object TimeSpan
add-member -InputObject $record -MemberType NoteProperty "Name" -Value $databaseName
add-member -InputObject $record -MemberType NoteProperty "TotalEntriesProcessed" -Value ([int] 0)
add-member -InputObject $record -MemberType NoteProperty "DurationMountStatusMounted" -Value $emptyTs
add-member -InputObject $record -MemberType NoteProperty "DurationMountStatusDismounted" -Value $emptyTs
add-member -InputObject $record -MemberType NoteProperty "DurationMountStatusUnavailable" -Value $emptyTs
add-member -InputObject $record -MemberType NoteProperty "DurationCopyStatusUnavailable" -Value $emptyTs
add-member -InputObject $record -MemberType NoteProperty "DurationCopyStatusResynchronizing" -Value $emptyTs
add-member -InputObject $record -MemberType NoteProperty "DurationCopyStatusFailed" -Value $emptyTs
add-member -InputObject $record -MemberType NoteProperty "DurationCopyStatusSuspended" -Value $emptyTs
add-member -InputObject $record -MemberType NoteProperty "DurationCopyStatusFailedSuspended" -Value $emptyTs
add-member -InputObject $record -MemberType NoteProperty "DurationCopyStatusDisconnected" -Value $emptyTs
add-member -InputObject $record -MemberType NoteProperty "TotalLogGenerationRate" -Value 0
add-member -InputObject $record -MemberType NoteProperty "AverageLogGenerationRate" -Value 0
add-member -InputObject $record -MemberType NoteProperty "PeakLogGenerationRate" -Value 0
add-member -InputObject $record -MemberType NoteProperty "TotalLogReplayRate" -Value 0
add-member -InputObject $record -MemberType NoteProperty "AverageLogReplayRate" -Value 0
add-member -InputObject $record -MemberType NoteProperty "PeakLogReplayRate" -Value 0
add-member -InputObject $record -MemberType NoteProperty "DurationOutOfCriteria" -Value $emptyTs
add-member -InputObject $record -MemberType NoteProperty "AverageDurationOutOfCriteria" -Value $emptyTs
add-member -InputObject $record -MemberType NoteProperty "PrevPerfEntry" -Value $null
return $record
}
function Populate-ServerADInfo
{
param ($svrRecord)
$svrRecord.ServerInfo = get-mailboxserver $svrRecord.Name
}
function Get-ElsapedTimeBetweenIterations
{
param ($prevTimeStr, $currentTimeStr)
if ($prevTimeStr -match "(d+)/(d+)/(d+)-(d+):(d+):(d+)")
{
$prevSampleTime = new-object datetime $matches[1],$matches[2],$matches[3],$matches[4],$matches[5],$matches[6]
}
if ($currentTimeStr -match "(d+)/(d+)/(d+)-(d+):(d+):(d+)")
{
$newSampleTime = new-object datetime $matches[1],$matches[2],$matches[3],$matches[4],$matches[5],$matches[6]
}
$duration = $newSampleTime - $prevSampleTime
return $duration
}
function Update-CopystatusDurations
{
param ($dbRecord, $newPerfEntry, $duration)
foreach ($cpStatusName in $newPerfEntry.CopyStatus.Split(","))
{
if ($cpStatusName)
{
$memberName = "DurationCopyStatus" + $cpStatusName
$dbRecord.$memberName += $duration
}
}
}
function Update-MountStatusDurations
{
param ($dbRecord, $newPerfEntry, $duration)
foreach ($mountStatusName in $newPerfEntry.MountStatus.Split(","))
{
$memberName = "DurationMountStatus" + $mountStatusName
$dbRecord.$memberName += $duration
}
}
function PredictTime-ByTransition
{
param($prevData, $currentData, $perfMemberName)
[int] $predictedMs = 0
if ($currentData.$perfMemberName -gt 0)
{
if (($prevData -eq $null) -or ($prevData.$perfMemberName -eq 0))
{
$predictedMs += ($Frequency.TotalMilliseconds)/2
}
else
{
$predictedMs += $Frequency.TotalMilliseconds
}
}
else
{
if (($prevData -eq $null) -or ($prevData.$perfMemberName -gt 0))
{
$predictedMs += ($Frequency.TotalMilliseconds)/2
}
}
return $predictedMs
}
function Parse-Counter
{
param ($sample)
$counterDetails = $null
if ($sample.Path -imatch "+(.*?)+(.*?)((.*))+(.*)")
{
$counterDetails = new-object object
Add-Member -InputObject $counterDetails -MemberType NoteProperty "MachineName" -Value $matches[1]
Add-Member -InputObject $counterDetails -MemberType NoteProperty "Category" -Value $matches[2]
Add-Member -InputObject $counterDetails -MemberType NoteProperty "InstanceName" -Value $matches[3]
Add-Member -InputObject $counterDetails -MemberType NoteProperty "CounterName" -Value $matches[4]
Add-Member -InputObject $counterDetails -MemberType NoteProperty "CounterValue" -Value ([int] $sample.CookedValue)
}
return $counterDetails
}
function Convert-CountersToMap
{
param($instanceMap, $categoryMemberName, $counterInfo)
if ($counterInfo)
{
foreach ($sample in $counterInfo.CounterSamples)
{
$counterDetails = Parse-Counter ($sample)
if ($counterDetails)
{
$instanceName = $counterDetails.InstanceName
$counterCategory = $counterDetails.Category
$counterName = $counterDetails.CounterName
$counterValue = $counterDetails.CounterValue
$pairMember = $instanceMap[$instanceName]
if ($pairMember -ne $null)
{
$pairMember.$($categoryMemberName)[$counterName] = $counterValue
}
}
}
}
}
function Get-BooleanState
{
param($perfMap, $counterName)
$isFound = $false
if (($perfMap -ne $null) -and ($perfMap[$counterName] -gt 0))
{
return $true
}
return $false
}
function Get-CustomDateString
{
param($sampleTime)
$str = $sampleTime.ToString("yyyy/MM/dd-hh:mm:ss")
return $str
}
function Get-TempDbOutputFile
{
param($serverName)
$outputFile = "$($TemporaryDataPath)$($serverName)_DatabaseInfo.csv"
return $outputFile
}
function Get-TempServerOutputFile
{
param($serverName)
$outputFile = "$($TemporaryDataPath)$($serverName)_ServerInfo.csv"
return $outputFile
}
# Load the exchange snapin so that we can use the exchange cmdlets in this script
LoadSnapin
$scriptStartTime = get-date
$scriptStartTimeStr = $scriptStartTime.ToString("yyy_MM_dd_hh_mm_ss")
if ($DagName)
{
# If DatabaseAvailabilityGroup is specified, then use that. Otherwise default
# to the database availability group which has the local node as a member
$Dag = FindDag -DagName:$DagName
}
else
{
$DagName = FindLocalDagName
$Dag = FindDag -DagName:$DagName
}
# If Database (array) is specified, then use that. Otherwise default to all
# the databases in the current dag
DetermineServersAndDatabases $DatabaseNames ([ref] $Databases) ([ref] $ServerDatabaseHash)
# If temp path is not specified, then assume a default one
if ([string]::IsNullOrEmpty($TemporaryDataPath))
{
$TemporaryDataPath = "$env:SystemDriveTempCollectReplicationMetrics$($scriptStartTime.ToString('yyy_MM_dd_hh_mm_ss'))"
}
# If report path is not specified in the command line then produce the results in the current directory
if (!$ReportPath)
{
$ReportPath = "."
}
# Keep the final report in the following directory
$DatabaseReportFile = $ReportPath+"DB_CollectReplicationMetrics_$($dag)_$scriptStartTimeStr.csv"
$ServerReportFile = $ReportPath+"SERVER_CollectReplicationMetrics_$($dag)_$scriptStartTimeStr.csv"
# Create temp directory if it doesn't exist already
if (!(Test-Path $TemporaryDataPath))
{
$dummy = new-item -ItemType Directory -Path:$TemporaryDataPath
}
if (!$ProcessOnly)
{
$currentTime = [DateTime]::Now
$endTime = $currentTime + $Duration
$iteration = 0
foreach ($serverName in $ServerDatabaseHash.Keys)
{
$outputFile = "$($TemporaryDataPath)$($serverName)_DatabaseInfo.csv"
$serverOutputFile = "$($TemporaryDataPath)$($serverName)_ServerInfo.csv"
Write-CounterCsvHeader $outputFile
Write-ServerCsvHeader $serverOutputFile
}
# Now start perfmon collection for the requested duration
while ($currentTime -lt $endTime)
{
write-host "Collecting samples at $currentTime"
$iteration++
$collectionInitiatedTime = [DateTime]::Now
foreach ($serverName in $ServerDatabaseHash.Keys)
{
Trace("Retrieving performance counters from $serverName")
$outputFile = Get-TempDbOutputFile $serverName
$serverOutputFile = Get-TempServerOutputFile $serverName
$sampleTime = [DateTime]::Now
$amCounterInfo = $null
$replCounterInfo = $null
$isServerReachable = 0
# Get core counter to find if machine is accessible
$procCounterInfo = get-counter "processor(_total)% processor time" -ComputerName:$serverName -MaxSamples:1 -ErrorAction:SilentlyContinue
if ($procCounterInfo)
{
$isServerReachable = 1
# Get AM counters for all the databases to optimize multiple trips for each database
$amCounterInfo = get-counter "MSExchange Active Manager(*)*" -ComputerName:$serverName -MaxSamples:1 -ErrorAction:SilentlyContinue
$replCounterInfo= get-counter "MSExchange Replication(*)*" -ComputerName:$serverName -MaxSamples:1 -ErrorAction:SilentlyContinue
}
$strTime = Get-CustomDateString ($sampleTime)
"$iteration,$strTime,$isServerReachable" >> $serverOutputFile
# Initialize db map with perf counter categories
$dbMap = @{}
foreach ($dbObj in $Databases)
{
$obj = new-object object
add-member -InputObject $obj -MemberType NoteProperty "AmPerf" -Value @{}
add-member -InputObject $obj -MemberType NoteProperty "ReplPerf" -Value @{}
$dbMap[$dbObj.Name] = $obj
}
# Convert retrieved counters to a convenient map
Convert-CountersToMap ($dbMap) ("AmPerf") ($amCounterInfo)
Convert-CountersToMap ($dbMap) ("ReplPerf") ($replCounterInfo)
foreach ($db in $ServerDatabaseHash[$serverName])
{
Save-CounterInCsvFormat ($iteration) ($sampleTime) ($db.Name) ($dbMap) ($outputFile)
}
}
$collectionCompletedTime = [DateTime]::Now
$elaspedCollectionDuration = $collectionCompletedTime - $collectionInitiatedTime
$durationToSleep = 0
if ($elaspedCollectionDuration -lt $Frequency)
{
$durationToSleep = ($Frequency - $elaspedCollectionDuration).TotalSeconds
}
if ($durationToSleep)
{
# Just make the sleep little bit interesting by providing some text mode fun
NonBoring-Sleep -Seconds $durationToSleep
}
$currentTime = [DateTime]::Now
}
write-host ""
}
$serverResults = @{}
# Crunch the data and prepare a datastructure that holds the
# required results
foreach ($serverName in $ServerDatabaseHash.Keys)
{
# Just create bunch of NoteProperties for convenience
$svrRecord = Create-EmptyServerRecord $serverName
# Fill svrrecord with the output of get-mailboxserver since we need
# some of these properties later
Populate-ServerADInfo $svrRecord
# Process all the databases on this server
$dbDataFile = Get-TempDbOutputFile $serverName
$serverDataFile = Get-TempServerOutputFile $serverName
foreach ($dbData in import-csv $dbDataFile)
{
# Create per db record if it doesn't exist already
$dbRecord = $svrRecord.DbInfo[$dbData.Database]
if ($dbRecord -eq $null)
{
$dbRecord = Create-EmptyDatabaseRecord $dbData.Database
$svrRecord.DbInfo[$dbData.Database] = $dbRecord
}
# Find out how much time elasped between the runs
$duration = $Frequency
if ($dbRecord.PrevPerfEntry -ne $null)
{
$duration = Get-ElsapedTimeBetweenIterations ($dbRecord.PrevPerfEntry.SampleTime) ($dbData.SampleTime)
}
Update-CopystatusDurations ($dbRecord) ($dbData) ($duration)
Update-MountStatusDurations ($dbRecord) ($dbData) ($duration)
$dbRecord.TotalLogGenerationRate += $dbData.LogGenerationRate
if ($dbData.LogGenerationRate -gt $dbRecord.PeakLogGenerationRate)
{
$dbRecord.PeakLogGenerationRate = $dbData.LogGenerationRate
}
$dbRecord.TotalLogGenerationRate += $dbData.LogGenerationRate
if ($dbData.LogReplayRate -gt $dbRecord.PeakLogReplayRate)
{
$dbRecord.PeakLogReplayRate = $dbData.LogReplayRate
}
if (($dbData.CopyQueueLength+1) -gt [int] $svrRecord.ServerInfo.AutoDatabaseMountDial)
{
$dbRecord.DurationOutOfCriteria += $duration
}
$dbRecord.TotalEntriesProcessed++
$dbRecord.PrevPerfEntry = $dbData
}
$totalPerServerMountedDuration = [TimeSpan]::FromSeconds(0)
$totalPerServerDismountedDuration = [TimeSpan]::FromSeconds(0)
$totalPerServerEntries = 0
$totalPerServerLogReplayRate = 0
$perServerPeakLogReplayRate = 0
# Calculate the per-db average info
foreach($dbName in $svrRecord.DbInfo.Keys)
{
$dbRecord = $svrRecord.DbInfo[$dbName]
$dbRecord.AverageLogGenerationRate = $dbRecord.TotalLogGenerationRate / $dbRecord.TotalEntriesProcessed
$dbRecord.AverageLogReplayRate = $dbRecord.TotalLogReplayRate / $dbRecord.TotalEntriesProcessed
$totalPerServerMountedDuration += $dbRecord.DurationMountStatusMounted
$totalPerServerDismountedDuration += $dbRecord.DurationMountStatusDismounted
$totalPerServerLogReplayRate += $dbRecord.TotalLogReplayRate
if ($dbRecord.PeakLogReplayRate -gt $perServerPeakLogReplayRate)
{
$perServerPeakLogReplayRate = $dbRecord.PeakLogReplayRate
}
$totalPerServerEntries += $dbRecord.TotalEntriesProcessed
}
# Calculate per-server average info
$svrRecord.AverageDurationMounted = [TimeSpan]::FromSeconds($totalPerServerMountedDuration.TotalSeconds / $totalPerServerEntries)
$svrRecord.AverageDurationDismounted = [TimeSpan]::FromSeconds($totalPerServerDismountedDuration.TotalSeconds / $totalPerServerEntries)
$svrRecord.AverageLogReplayRate = $totalPerServerLogReplayRate / $totalPerServerEntries
$svrRecord.PeakLogReplayRate = $perServerPeakLogReplayRate
$serverPrevEntry = $null
# Crunch the data from the per-server file
foreach($serverEntry in import-csv $serverDataFile)
{
$duration = $Frequency
if ($serverPrevEntry -ne $null)
{
$duration = Get-ElsapedTimeBetweenIterations ($serverPrevEntry.SampleTime) ($serverEntry.SampleTime)
}
$svrRecord.DurationMeasured += $duration
if (!$serverEntry.IsReachable)
{
$svrRecord.DurationUnavailable += $duration
}
$serverPrevEntry = $serverEntry
}
$serverResults[$serverName] = $svrRecord
}
# Write headers for server report file
$serverHeader = new-object System.Collections.ArrayList
[void] $serverHeader.Add("ServerName")
[void] $serverHeader.Add("HoursMeasured")
[void] $serverHeader.Add("HoursUnavailable")
[void] $serverHeader.Add("AverageMountedMinutes")
[void] $serverHeader.Add("AverageLogReplayRate")
[void] $serverHeader.Add("PeakLogReplayRate")
[string]::Join(",",$serverHeader) > $ServerReportFile
# Write headers for database report file
$dbHeader = new-object System.Collections.ArrayList
[void] $dbHeader.Add("ServerName")
[void] $dbHeader.Add("DatabaseName")
[void] $dbHeader.Add("HoursMounted")
[void] $dbHeader.Add("MinutesUnavailabe")
[void] $dbHeader.Add("MinutesResynchronizing")
[void] $dbHeader.Add("MinutesFailed")
[void] $dbHeader.Add("MinutesSuspended")
[void] $dbHeader.Add("MinutesFailedSuspended")
[void] $dbHeader.Add("MinutesDisconnected")
[void] $dbHeader.Add("AverageLogGenerationRate")
[void] $dbHeader.Add("PeakLogGenerationRate")
[void] $dbHeader.Add("AverageLogReplayRate")
[void] $dbHeader.Add("PeakLogReplayRate")
[void] $dbHeader.Add("OutofCriteriaSeconds")
[void] $dbHeader.Add("AverageOutofCriteriaSeconds")
[string]::Join(",",$dbHeader) > $DatabaseReportFile
# Reports are now ready in-memory. Dump those into a csv file
foreach ($serverName in $serverResults.Keys)
{
$svrRec = $serverResults[$serverName]
$serverData = new-object System.Collections.ArrayList
[void] $serverData.Add($svrRec.Name)
[void] $serverData.Add([string]::Format("{0:0.###}", $svrRec.DurationMeasured.TotalHours))
[void] $serverData.Add([string]::Format("{0:0.###}", $svrRec.DurationUnavailable.TotalHours))
[void] $serverData.Add([string]::Format("{0:0.###}", $svrRec.AverageDurationMounted.TotalMinutes))
[void] $serverData.Add($svrRec.AverageLogReplayRate)
[void] $serverData.Add($svrRec.PeakLogReplayRate)
[string]::Join(",", $serverData) >> $ServerReportFile
$dbRecords = $svrRec.DbInfo
foreach ($dbName in $dbRecords.Keys)
{
$dbRec = $svrRec.DbInfo[$dbName]
$dbData = new-object System.Collections.ArrayList
[void] $dbData.Add($svrRec.Name)
[void] $dbData.Add($dbRec.Name)
[void] $dbData.Add([string]::Format("{0:0.###}", $dbRec.DurationMountStatusMounted.TotalHours))
[void] $dbData.Add([string]::Format("{0:0.###}", $dbRec.DurationCopyStatusUnavailable.TotalMinutes))
[void] $dbData.Add([string]::Format("{0:0.###}", $dbRec.DurationCopyStatusResynchronizing.TotalMinutes))
[void] $dbData.Add([string]::Format("{0:0.###}", $dbRec.DurationCopyStatusFailed.TotalMinutes))
[void] $dbData.Add([string]::Format("{0:0.###}", $dbRec.DurationCopyStatusSuspended.TotalMinutes))
[void] $dbData.Add([string]::Format("{0:0.###}", $dbRec.DurationCopyStatusFailedSuspended.TotalMinutes))
[void] $dbData.Add([string]::Format("{0:0.###}", $dbRec.DurationCopyStatusDisconnected.TotalMinutes))
[void] $dbData.Add($dbRec.AverageLogGenerationRate)
[void] $dbData.Add($dbRec.PeakLogGenerationRate)
[void] $dbData.Add($dbRec.AverageLogReplayRate)
[void] $dbData.Add($dbRec.PeakLogReplayRate)
[void] $dbData.Add($dbRec.DurationOutOfCriteria.TotalSeconds)
[void] $dbData.Add($dbRec.AverageDurationOutOfCriteria.TotalSeconds)
[string]::Join(",", $dbData) >> $DatabaseReportFile
}
}
if ($Verbose)
{
write-host ""
write-host "Database report"
write-host "==============="
$dbReport = import-csv $DatabaseReportFile
$dbReport | ft
write-host "Server report"
write-host "============="
$serverReport = import-csv $ServerReportFile
$serverReport | ft
}
[@more@]來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/23700676/viewspace-1052333/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- Exchange 2010 Powershell指令碼攻略(十五)指令碼
- Exchange 2010 Powershell指令碼攻略(十四)指令碼
- Exchange 2010 Powershell指令碼攻略(十三)指令碼
- Exchange 2010 Powershell指令碼攻略(十二)指令碼
- Exchange 2010 Powershell指令碼攻略(十一)指令碼
- Exchange 2010 Powershell指令碼攻略(十)指令碼
- Exchange 2010 Powershell指令碼攻略(九)指令碼
- Exchange 2010 Powershell指令碼攻略(八)指令碼
- Exchange 2010 Powershell指令碼攻略(六)指令碼
- Exchange 2010 Powershell指令碼攻略(五)指令碼
- Exchange 2010 Powershell指令碼攻略(四)指令碼
- Exchange 2010 Powershell指令碼攻略(三)指令碼
- Exchange 2010 Powershell指令碼攻略(二)指令碼
- Exchange 2010 Powershell指令碼攻略(一)指令碼
- powershell指令碼指令碼
- PowerShell 指令碼中的密碼指令碼密碼
- PowerShell 指令碼執行策略指令碼
- powershell重新命名指令碼指令碼
- Exchange 2010搭建
- Bash指令碼debug攻略指令碼
- 開機自啟動Powershell指令碼指令碼
- linux shell 指令碼攻略筆記Linux指令碼筆記
- 【黑客基礎】Windows PowerShell 指令碼學習(上)黑客Windows指令碼
- 最簡單的一個powershell的指令碼指令碼
- Exchange 2010需要的網路埠
- 微軟宣佈全新命令列+指令碼工具:PowerShell 7微軟命令列指令碼
- 五個實用的SQL Server PowerShell指令碼OMSQLServer指令碼
- 利用powershell指令碼Windows hosts記錄替換IP指令碼Windows
- Win10使用Powershell提示禁止執行指令碼怎麼辦 Win10使用Powershell提示禁止執行指令碼如何解決Win10指令碼
- shell指令碼攻略--DNS正向解析一鍵部署指令碼DNS
- 利用 Powershell 編寫簡單的瀏覽器指令碼瀏覽器指令碼
- 【連結】LINUX SHELL指令碼攻略筆記[速查]Linux指令碼筆記
- 《Linux Shell指令碼攻略(第2版)》書評Linux指令碼
- nuget打包檔案丟失如何使用powershell指令碼解決指令碼
- 使用VSCode遠端除錯惡意Powershell指令碼VSCode除錯指令碼
- 【VMware VCF】使用 PowerShell 指令碼管理 SDDC Manager 中的軟體包。指令碼
- PowerShell 指令碼來監控 CPU、記憶體和磁碟使用情況:指令碼記憶體
- linux shell 指令碼攻略學習6-xargs詳解Linux指令碼