Скрипт Powershell для мониторинга отставания DFSR

Не вопрос. Просто делюсь. Извиняюсь, если это неправильное место проведения и / или метод, но я много взял с этих форумов и просто хотел бы немного рассказать на тот случай, если кто-то еще захочет выучить PS и сделать что-то даже полезное в PS. Извините, но мне пришлось запустить скрипт через редактор. Во всяком случае здесь это:

###################################################################################################
#  File:    DFSR-check-3-show-backlog.ps1
#  Desc:    Simple monitor of DFSR backlog.
#
#  Vers   Date      Who Description
#  ----   ----      --- -----------
#  v0.01  11-Aug-2016   sdo Initial draft, based on commands from BM.
#  v0.02  12-Aug-2016   sdo Use "Out-String" to trim the blank lines of the table.
#  v0.03  12-Aug-2016   sdo Extract count from verbose output if "100" items are returned.
#  v0.04  12-Aug-2016   sdo Write to a log file.
#  v0.05  12-Aug-2016   sdo Only display when different or every 100 entries.
#  v0.06  12-Aug-2016   sdo Same layout and counter as other two scripts.
#  v0.07  12-Aug-2016   sdo If the return backlog value is "", make it "0".
#  v0.08  12-Aug-2016   sdo If display is "0,0", make it "-", which is easier to see activity.
#  v0.09  12-Aug-2016   sdo Round anything > 100 to units of 100.
#  v0.10  12-Aug-2016   sdo Use a function so that display updates less often.
###################################################################################################


###################################################################################################
# Functions...

Function fn_count( $p1 ) {
  $return = [string]$p1
  if ( $return -eq "" ) {Return "0"}
  if ( fn_is_numeric( $return ) ) {
    $number = [int]$return
    switch ($number) {
    {$_ -ge 100}  {$return = $(([math]::Round($_ / 100)) * 100) ; $return=[string]$return+"+" ; Return $return }
    {$_ -ge   1}  {Return "<100" }
    {$_ -eq   0}  {Return    "0" }
    }
  }
  Return $return
}

Function fn_display_header {
  ""
  "           Disp    Cnt  AppAxx          AppBxxxWorking  AppCxxxx        AppKxx          AppTxxxFiles"
  "          =====  =====  ======          ==============  ========        ======          ============"
}

Function fn_is_numeric( $p1 ) {
  Return ( $( $p1.Trim() ) -Match "^[-+]?([0-9]*\.[0-9]+|[0-9]+\.?)$" )
}


###################################################################################################
# Main code...

$script_spec = $PSCommandPath
$script_path = [System.IO.Path]::GetDirectoryName(            $script_spec         )
$script_name = [System.IO.Path]::GetFileNameWithoutExtension( $script_spec         )
$script_log  = [System.IO.Path]::ChangeExtension(             $script_spec, ".log" )

$Host.UI.RawUI.WindowTitle = $script_name

$line    = ""
$z_count = 0
$z_lines = 0


fn_display_header
fn_display_header | Out-File $script_log -Append

while ($true) {
  $prev = $line

  $z_count++
  if ( ($z_count % 100) -eq 0) {$prev = ""}


###################################################################################################
# Establish whether DFSR is up/enabled/available, or unknown...

  $set = $( DFSRDiag backlog /rgname:AppAxx         /rfname:AppAxx         /sendingmember:ZZZPAAACSFT001 /receivingmember:ZZZPAAACSFT002 )
  if ($LastExitCode -eq 0) {$AppAxx_Diag = "ok"} else {$AppAxx_Diag = "UNKNOWN"}

  $set = $( DFSRDiag backlog /rgname:AppBxxxWorking /rfname:AppBxxxWorking /sendingmember:ZZZPAAACSFT001 /receivingmember:ZZZPAAACSFT002 )
  if ($LastExitCode -eq 0) {$AppBxxxWorking_Diag = "ok"} else {$AppBxxxWorking_Diag = "UNKNOWN"}

  $set = $( DFSRDiag backlog /rgname:AppCxxxx       /rfname:AppCxxxx       /sendingmember:ZZZPAAACSFT001 /receivingmember:ZZZPAAACSFT002 )
  if ($LastExitCode -eq 0) {$AppCxxxx_Diag = "ok"} else {$AppCxxxx_Diag = "UNKNOWN"}

  $set = $( DFSRDiag backlog /rgname:AppKxx         /rfname:AppKxx         /sendingmember:ZZZPAAACSFT001 /receivingmember:ZZZPAAACSFT002 )
  if ($LastExitCode -eq 0) {$AppKxx_Diag = "ok"} else {$AppKxx_Diag = "UNKNOWN"}

  $set = $( DFSRDiag backlog /rgname:AppTxxxFiles   /rfname:AppTxxxFiles   /sendingmember:ZZZPAAACSTA003 /receivingmember:ZZZPAAACSTA004 )
  if ($LastExitCode -eq 0) {$AppTxxxFiles_Diag = "ok"} else {$AppTxxxFiles_Diag = "UNKNOWN"}


###################################################################################################
# Get DFSR back-log counts, from both sides... or report the "unknown" from the diagnostics...

  if ($AppAxx_Diag -eq "ok") {
    $verbose = $( $set = $(Get-DFSRBackLog -Verbose -SourceComputerName ZZZPAAACSFT001 -DestinationComputerName ZZZPAAACSFT002 -GroupName AppAxx -ErrorAction SilentlyContinue | Select FullPathname ) ) 4>&1
    if ($?) {$count = [string]$set.Count} else {$count = "ERROR"}
    if ($count -ne "ERROR") {
      if ($count -ne "100") { $count = fn_count( $count ) } else {
        $verbose = [string]$verbose ; $count = $verbose.Split(" ")[-1] ; $count = fn_count($count) } }
    $AppAxx_Display = $count

    $verbose = $( $set = $(Get-DFSRBackLog -Verbose -SourceComputerName ZZZPAAACSFT002 -DestinationComputerName ZZZPAAACSFT001 -GroupName AppAxx -ErrorAction SilentlyContinue | Select FullPathname ) ) 4>&1
    if ($?) {$count = [string]$set.Count} else {$count = "ERROR"}
    if ($count -ne "ERROR") {
      if ($count -ne "100") { $count = fn_count( $count ) } else {
        $verbose = [string]$verbose ; $count = $verbose.Split(" ")[-1] ; $count = fn_count($count) } }
    $AppAxx_Display = $AppAxx_Display + "," + $count
  } else {
    $AppAxx_Display = $AppAxx_Diag
  }


  if ($AppBxxxWorking_Diag -eq "ok") {
    $verbose = $( $set = $( Get-DFSRBackLog -Verbose -SourceComputerName ZZZPAAACSFT001 -DestinationComputerName ZZZPAAACSFT002 -GroupName AppBxxxWorking -ErrorAction SilentlyContinue | Select FullPathname ) ) 4>&1
    if ($?) {$count = [string]$set.Count} else {$count = "ERROR"}
    if ($count -ne "ERROR") {
      if ($count -ne "100") { $count = fn_count( $count ) } else {
        $verbose = [string]$verbose ; $count = $verbose.Split(" ")[-1] ; $count = fn_count($count) } }
    $AppBxxxWorking_Display = $count

    $verbose = $( $set = $( Get-DFSRBackLog -Verbose -SourceComputerName ZZZPAAACSFT002 -DestinationComputerName ZZZPAAACSFT001 -GroupName AppBxxxWorking -ErrorAction SilentlyContinue | Select FullPathname ) ) 4>&1
    if ($?) {$count = [string]$set.Count} else {$count = "ERROR"}
    if ($count -ne "ERROR") {
      if ($count -ne "100") { $count = fn_count( $count ) } else {
        $verbose = [string]$verbose ; $count = $verbose.Split(" ")[-1] ; $count = fn_count($count) } }
    $AppBxxxWorking_Display = $AppBxxxWorking_Display + "," + $count
  } else {
    $AppBxxxWorking_Display = $AppBxxxWorking_Diag
  }


  if ($AppCxxxx_Diag -eq "ok") {
    $verbose = $( $set = $( Get-DFSRBackLog -Verbose -SourceComputerName ZZZPAAACSFT001 -DestinationComputerName ZZZPAAACSFT002 -GroupName AppCxxxx -ErrorAction SilentlyContinue | Select FullPathname ) ) 4>&1
    if ($?) {$count = [string]$set.Count} else {$count = "ERROR"}
    if ($count -ne "ERROR") {
      if ($count -ne "100") { $count = fn_count( $count ) } else {
        $verbose = [string]$verbose ; $count = $verbose.Split(" ")[-1] ; $count = fn_count($count) } }
    $AppCxxxx_Display = $count

    $verbose = $( $set = $( Get-DFSRBackLog -Verbose -SourceComputerName ZZZPAAACSFT002 -DestinationComputerName ZZZPAAACSFT001 -GroupName AppCxxxx -ErrorAction SilentlyContinue | Select FullPathname ) ) 4>&1
    if ($?) {$count = [string]$set.Count} else {$count = "ERROR"}
    if ($count -ne "ERROR") {
      if ($count -ne "100") { $count = fn_count( $count ) } else {
        $verbose = [string]$verbose ; $count = $verbose.Split(" ")[-1] ; $count = fn_count($count) } }
    $AppCxxxx_Display = $AppCxxxx_Display + "," + $count
  } else {
    $AppCxxxx_Display = $AppCxxxx_Diag
  }


  if ($AppKxx_Diag -eq "ok") {
    $verbose = $( $set = $( Get-DFSRBackLog -Verbose -SourceComputerName ZZZPAAACSFT001 -DestinationComputerName ZZZPAAACSFT002 -GroupName AppKxx -ErrorAction SilentlyContinue | Select FullPathname ) ) 4>&1
    if ($?) {$count = [string]$set.Count} else {$count = "ERROR"}
    if ($count -ne "ERROR") {
      if ($count -ne "100") { $count = fn_count( $count ) } else {
        $verbose = [string]$verbose ; $count = $verbose.Split(" ")[-1] ; $count = fn_count($count) } }
    $AppKxx_Display = $count

    $verbose = $( $set = $( Get-DFSRBackLog -Verbose -SourceComputerName ZZZPAAACSFT002 -DestinationComputerName ZZZPAAACSFT001 -GroupName AppKxx -ErrorAction SilentlyContinue | Select FullPathname ) ) 4>&1
    if ($?) {$count = [string]$set.Count} else {$count = "ERROR"}
    if ($count -ne "ERROR") {
      if ($count -ne "100") { $count = fn_count( $count ) } else {
        $verbose = [string]$verbose ; $count = $verbose.Split(" ")[-1] ; $count = fn_count($count) } }
    $AppKxx_Display = $AppKxx_Display + "," + $count
  } else {
    $AppKxx_Display = $AppKxx_Diag
  }


  if ($AppTxxxFiles_Diag -eq "ok") {
    $verbose = $( $set = $( Get-DFSRBackLog -Verbose -SourceComputerName ZZZPAAACSTA003 -DestinationComputerName ZZZPAAACSTA004 -GroupName AppTxxxFiles -ErrorAction SilentlyContinue | Select FullPathname ) ) 4>&1
    if ($?) {$count = [string]$set.Count} else {$count = "ERROR"}
    if ($count -ne "ERROR") {
      if ($count -ne "100") { $count = fn_count( $count ) } else {
        $verbose = [string]$verbose ; $count = $verbose.Split(" ")[-1] ; $count = fn_count($count) } }
    $AppTxxxFiles_Display = $count

    $verbose = $( $set = $( Get-DFSRBackLog -Verbose -SourceComputerName ZZZPAAACSTA004 -DestinationComputerName ZZZPAAACSTA003 -GroupName AppTxxxFiles -ErrorAction SilentlyContinue | Select FullPathname ) ) 4>&1
    if ($?) {$count = [string]$set.Count} else {$count = "ERROR"}
    if ($count -ne "ERROR") {
      if ($count -ne "100") { $count = fn_count( $count ) } else {
        $verbose = [string]$verbose ; $count = $verbose.Split(" ")[-1] ; $count = fn_count($count) } }
    $AppTxxxFiles_Display = $AppTxxxFiles_Display + "," + $count
  } else {
    $AppTxxxFiles_Display = $AppTxxxFiles_Diag
  }


###################################################################################################
# Build the table for display...

  if ($AppAxx_Display         -eq "0,0") {$AppAxx_Display         = "-"}
  if ($AppBxxxWorking_Display -eq "0,0") {$AppBxxxWorking_Display = "-"}
  if ($AppCxxxx_Display       -eq "0,0") {$AppCxxxx_Display       = "-"}
  if ($AppKxx_Display         -eq "0,0") {$AppKxx_Display         = "-"}
  if ($AppTxxxFiles_Display   -eq "0,0") {$AppTxxxFiles_Display   = "-"}

  $table = @()
  $table = New-Object PSObject -Property @{
    AppAxx         = $AppAxx_Display
    AppBxxxWorking = $AppBxxxWorking_Display
    AppCxxxx       = $AppCxxxx_Display
    AppKxx         = $AppKxx_Display
    AppTxxxFiles   = $AppTxxxFiles_Display
  }

  $line = ( $table | Format-Table -HideTableHeaders `
     @{ expression = { $_.AppAxx         } ; width = 15 } `
    ,@{ expression = { $_.AppBxxxWorking } ; width = 15 } `
    ,@{ expression = { $_.AppCxxxx       } ; width = 15 } `
    ,@{ expression = { $_.AppKxx         } ; width = 15 } `
    ,@{ expression = { $_.AppTxxxFiles   } ; width = 15 } `
  | Out-String ).Trim()


  if ($line -ne $prev) {
    $z_lines++

    if ( ($z_lines % 10) -eq 0 ) {
      fn_display_header
      fn_display_header | Out-File $script_log -Append
    }

    $display = $(Get-Date -Format T) + "  " + $("{0:F0}" -f $z_lines).PadLeft(5) + "  " + $("{0:F0}" -f $z_count).PadLeft(5) + "  " + $line

    $display
    $display | Out-File $script_log -Append
  }

  Start-Sleep -Seconds 10
}

exit

1 ответ

Решение

Это не совсем "конкретный вопрос", поэтому я собираюсь действовать так, как если бы это был CodeReview.StackExchange.

  • $count = fn_count( $count ) - вызовы функций в PowerShell не используются () - если вы не хотите передавать массивы в качестве параметров - они просто действуют как командлеты. $count = fn_count $count
  • fn_is_numeric( $p1 ) - использовать [int]::TryParse() или приведите к [int] и поймайте ошибки.
  • fn_count( $p1 ) - сомнительный стиль именования в избыточном стиле Visual Basic, объявление параметров старого стиля, бесполезное имя параметра
  • fn_count - какие. Эта функция имеет слово return 14 раз в 11 строк. Он преобразуется в строку, что вы также делаете во время вызова, и делает целую кучу вещей, чтобы просто сдавить последние две цифры до 00 или сказать <100 или 0. И это глючит - введите 170, и он скажет 200+.
  • [System.IO.Path]::GetDirectoryName() и друзья -> [IO.FileInfo] а также .Directory
  • Массы скопированного кода -> 5 строк настройки и ForEach петля
  • Используйте Hashtables для повторяющихся данных вместо большого количества именованных переменных
  • $("{0:F0}" -f $z_lines).PadLeft(5) кажется делает "$z_lines".PadLeft(5)
  • DFSRDiag вызывает, где у вас есть 10 строк копирования-вставки и 5 имен пользовательских переменных, просто чтобы перенести текст "ОК" или "НЕИЗВЕСТНО" в следующую часть скрипта. Откажитесь от этого и объединитесь с очередными кусочками копировально-макаронных изделий. Они уже раздуты, но это можно убрать, потому что...

Это:

if ($?) {$count = [string]$set.Count} else {$count = "ERROR"}
if ($count -ne "ERROR") {
  if ($count -ne "100") { $count = fn_count( $count ) } else {
    $verbose = [string]$verbose ; $count = $verbose.Split(" ")[-1] ; $count = fn_count($count) } }
$AppAxx_Display = $count

Это выглядит так: "Мой скопированный код становится длинным, я собираюсь сократить его, REALLYCRAMMINGEVERYTHINGUPUNREADABLY; fn_count уже бросает $p1 в строку, так что пропустите это здесь, fn_count пропускает нечисловые строки напрямую, так что вы можете пропустить проверку, если это "ОШИБКА", и просто пропустить через что бы то ни было. Забудьте приводить подробные данные к строкам (как это может быть уже не так?), Забудьте много вложенных if/else с трудно читаемым выравниванием, вообще-то, забудьте о сохранении $count - бросьте одну или другую вещь в fn_count и присвойте результат AppAxx за один раз.

  • Я думаю, что $table / format-table shennanigans: idk, но с 5 строками кода для цикла ForEach, я думаю, что он в основном может быть сжат.

  • это $Verbose = $( $set = $( Get-DFSRBackLog ... | Select FullPathname ) ) 4>&1 комментируется вуду. Я даже не хочу трогать это.

Во всяком случае, я упал fn_is_numericустановил хеш-таблицу из пяти серверов и их членов репликации и превратил два больших куска копирования-вставки в один цикл, вытащил двойной вызов Get-DFSRBacklog в функцию и объединил fn_count в это, переехал "0,0" проверить к своему источнику $table путем повторного использования той же хеш-таблицы, которую я настроил ранее, удалил кучу (), странное форматирование чисел, двойные строки, которые могли бы быть одной, и, как правило, сбило с него 100+ строк и исправило ошибку 170->200+:

###################################################################################################
#  File:    DFSR-check-3-show-backlog.ps1
#  Desc:    Simple monitor of DFSR backlog.
#
#  Vers   Date      Who Description
#  ----   ----      --- -----------
#  v0.01  11-Aug-2016   sdo Initial draft, based on commands from BM.
#  v0.02  12-Aug-2016   sdo Use "Out-String" to trim the blank lines of the table.
#  v0.03  12-Aug-2016   sdo Extract count from verbose output if "100" items are returned.
#  v0.04  12-Aug-2016   sdo Write to a log file.
#  v0.05  12-Aug-2016   sdo Only display when different or every 100 entries.
#  v0.06  12-Aug-2016   sdo Same layout and counter as other two scripts.
#  v0.07  12-Aug-2016   sdo If the return backlog value is "", make it "0".
#  v0.08  12-Aug-2016   sdo If display is "0,0", make it "-", which is easier to see activity.
#  v0.09  12-Aug-2016   sdo Round anything > 100 to units of 100.
#  v0.10  12-Aug-2016   sdo Use a function so that display updates less often.
###################################################################################################


# Functions...  ###################################################################################


Function Test-DFSRAtoB {
    Param($ComputerA, $ComputerB, $GroupName)

    # Get the backlog count, either directly or from the verbose log
    $verbose = $( $set = $(Get-DFSRBackLog -Verbose -SourceComputerName $ComputerA -DestinationComputerName $ComputerB -GroupName $GroupName -ErrorAction SilentlyContinue | Select FullPathname ) ) 4>&1
    if (!$?) { return "ERROR" }
    $Count = if ("100" -ne $set.Count ) { $set.Count } else { "$verbose".Split(" ")[-1] }

    # Round the backlog count to (0, <100, nn00+), or return it unchanged if that fails
    try {

        if     (100 -le $Count) { $Count -replace '..$', '00+' }
        elseif (  1 -le $Count) { "<100" } 
        elseif (  0 -eq $Count) { "0" }

    } catch { $Count }

}

Function Show-Header {
    ""
    "           Disp    Cnt  AppAxx          AppBxxxWorking  AppCxxxx        AppKxx          AppTxxxFiles"
    "          =====  =====  ======          ==============  ========        ======          ============"
}


###################################################################################################
# Main code...

$ScriptFileName = [System.IO.FileInfo]$PSCommandPath
$ScriptLog = Join-Path $ScriptFileName.Directory "$($ScriptFileName.BaseName).log"

$Host.UI.RawUI.WindowTitle = $ScriptFileName.Name

$line    = ""
$z_count = 0
$z_lines = 0


Show-Header
Show-Header| Out-File $ScriptLog -Append

$Replications = @(
    @{Name='AppAxx';         Member1='ZZZPAAACSFT001'; Member2='ZZZPAAACSFT002'},
    @{Name='AppBxxxWorking'; Member1='ZZZPAAACSFT001'; Member2='ZZZPAAACSFT002'},
    @{Name='AppCxxxx';       Member1='ZZZPAAACSFT001'; Member2='ZZZPAAACSFT002'},
    @{Name='AppKxx';         Member1='ZZZPAAACSFT001'; Member2='ZZZPAAACSFT002'},
    @{Name='AppTxxxFiles';   Member1='ZZZPAAACSTA003'; Member2='ZZZPAAACSTA004'}
)

while ($true) {

###################################################################################################
# Establish whether DFSR is up/enabled/available, or unknown...
# Get DFSR back-log counts, from both sides... or report the "unknown" from the diagnostics...

  $DisplayData = @{}

  $Replications | ForEach {

    $set = $( DFSRDiag backlog /rgname:$_.Name  /rfname:$_.Name  /sendingmember:$_.Member1   /receivingmember:$_.Member2 )
    if ($LastExitCode -eq 0) 
    {
        $AtoBResult = Test-DFSRAtoB $_.Member1 $_.Member2 $_.Name
        $BtoAResult = Test-DFSRAtoB $_.Member2 $_.Member1 $_.Name

        $Display = "$AtoBResult, $BtoAResult"
        $DisplayData[$_.Name] = if ($Display -eq "0,0") { "-" } else { $Display }
    } 
    else 
    {
        $DisplayData[$_.Name] = "UNKNOWN"
    }

  }

###################################################################################################
# Build the table for display...

  $prev = if (++$z_count % 100) { $line } else { "" }

  $line = ( [PSCustomObject]$DisplayData | Format-Table -HideTableHeaders `
     @{ expression = { $_.AppAxx         } ; width = 15 } `
    ,@{ expression = { $_.AppBxxxWorking } ; width = 15 } `
    ,@{ expression = { $_.AppCxxxx       } ; width = 15 } `
    ,@{ expression = { $_.AppKxx         } ; width = 15 } `
    ,@{ expression = { $_.AppTxxxFiles   } ; width = 15 } `
  | Out-String ).Trim()


  if ($line -ne $prev) {

    if ( (++$z_lines % 10) -eq 0 ) {
      Show-Header
      Show-Header | Out-File $ScriptLog -Append
    }

    ($display = "$(Get-Date -Format T)  $("$z_lines".PadLeft(5))  $("$z_count".PadLeft(5))  $line")
    $display | Out-File $ScriptLog -Append
  }

  Start-Sleep -Seconds 10
}

exit

Чего я не сделал, так это протестировал его, поэтому сомневаюсь, что он будет работать как есть. Надеюсь, это концептуально звучит, хотя.

Другие вопросы по тегам