none
PowerShell Анализ объем дискового пространства для резервных копий БД. RRS feed

  • Вопрос

  • Здравствуйте. 

    Поставили задачу написать скрипт, который будет определять необходимое дисковое пространство для резервных копий баз данных. В идеале он должен немного прогнозировать рост базы за определенное время, скажем, за 24 часа, на сколько база выростет и какой при этом потребуется объем дискового пространства. Расчет должен идти в совокупности со всех серверов СУБД.

    Базы данных крутятся на MS SQL Server 2008 R2 и MS SQL Server 2012.

    Бэкапы выполняются средствами Symantec Backup Exec 2012

    Каким образом лучше оформить скрипт? Дело в том, что никогда не использовал ПОШ для работы с MS SQL сервером и Symantec'ом. По какому алгоритму он должен действовать?. 

    Хотелось бы наглядно увидеть принцип построения самого скрипта для данной задачи.

    Заранее всем спасибо!

    16 января 2018 г. 12:39

Ответы

  • Разобрался в чем была проблема.

    В переменную $sum попадает пробел и я ума не приложу почему -replace " ", "" не срабатывает

    Собственно вот рабочий код с "костылем":

    $servers = "server1.com", "server2.com", "server3.com"
    $exportPath = "C:\export\export.txt"
    
    if ((Test-Path $exportPath) -eq $false) {
        Add-Content -Path $exportPath -Value "Date;Server;Size"
    }
    
    Foreach ($server in $servers) {
        Invoke-Command -ComputerName $server -ScriptBlock {
        $folderSize = Get-ChildItem "D:\DB" -Recurse | measure -Property length -Sum;
        $_size = ("{0:N2}" -f $($FolderSize.Sum/1MB)) -replace ",","."
        $size = $_size.Split("")[0] + $_size.Split("")[1] + $_size.Split("")[2] + $_size.Split("")[3]
        $date = Get-Date -Format d
        $output = [string]$date + ";" + $server + ";" + $size
        Write-Output -InputObject $output
        } | Add-Content -Path $exportPath
    }
    
    $csv = Import-Csv $exportPath -Delimiter ";"
    $csv | ? {$_.Date -eq (Get-Date -Format d) -and $_.Server -ne "SUM"} | Foreach {
        $sum += [double]$_.Size
    }
    
    $outputSum = $(Get-Date -Format d) + ";SUM;" + $sum
    Add-Content -Path $exportPath -Value $outputSum
    Не забудьте указать ваши сервера и путь до БД

    • Помечено в качестве ответа KazunEditor 22 января 2018 г. 5:45
    17 января 2018 г. 14:39

Все ответы

  • Написать скрипт - не проблема.

    $servers = "server1.com", "server2.com", "server3.com"
    $exportPath = "C:\export\export.txt"
    
    Foreach ($server in $servers) {
        Invoke-Command -ComputerName $server -ScriptBlock {
        (Get-ChildItem -Path D:\DB | measure -Property Length -Sum).Sum / 1024Mb
        } | Add-Content -Path $exportPath
    }
    
    $exportContent = Get-Content $exportPath
    
    for ($i = 0; $i -le ($exportContent.length - 1); $i++) {
        $sum += [int]$exportContent[$i]
    }
    
    Write-Host $sum

    Но кто как не вы должен проанализировать процент роста баз? Это же индивидуально :D

    PS Скрипт выше получает общий объем баз со всех серверов.

    • Изменено Sergey Ya 16 января 2018 г. 13:09
    16 января 2018 г. 13:06
  • Визуально и статично это можно сделать. Только это нужно делать в процессе работы скрипта: что бы он сам анализировал рост одной базы или общий рост всех баз. Каким то образом возможно это оформить? Не хочется каждый раз менять в скрипте константы.
    16 января 2018 г. 13:21
  • Если я правильно понял, то вам нужна статистика за сутки с интервалом , предположим, 1 час?

    11:00 - 1gb

    12:00 - 1.3gb

    13:00 - 2gb

    и тд

    Так?

    16 января 2018 г. 13:25
  • (Get-ChildItem -Path D:\DB | measure -Property Length -Sum).Sum / 1024Mb

    Свойство Length у меня почему то пустое выдается.

    17 января 2018 г. 7:20
  • Можно даже интервал 24 часа, ровно сутки, не обязательно почасовая аналитика.

    грубо говоря:

    17.01.2018 - 1GB

    18.01.2018 - 2GB  

    и т.д.

    17 января 2018 г. 7:22
  • Немного поправил начальный скрипт. Старый вариант считал только файлы в папке, но не брал в расчет вложенные папки с файлами.

    Вот рабочий вариант:
    $servers = "server1.com", "server2.com", "server3.com"
    $exportPath = "C:\export\export.txt"
    
    if ((Test-Path $exportPath) -eq $false) {
        Add-Content -Path $exportPath -Value "Date;Server;Size"
    }
    
    Foreach ($server in $servers) {
        Invoke-Command -ComputerName $server -ScriptBlock {
        $folderSize = Get-ChildItem "D:\DB" -Recurse | measure -Property length -Sum;
        $size = ("{0:N2}" -f $($FolderSize.Sum/1MB)) -replace ",","."
        $date = Get-Date -Format d
        $output = [string]$date + ";" + $server + ";" + $size
        Write-Output -InputObject $output
        } | Add-Content -Path $exportPath
    }
    
    $csv = Import-Csv $exportPath -Delimiter ";"
    $csv | ? {$_.Date -eq (Get-Date -Format d) -and $_.Server -ne "SUM"} | Foreach {
        $sum += [double]$_.Size
    }
    
    $outputSum = $(Get-Date -Format d) + ";SUM;" + $sum
    Add-Content -Path $exportPath -Value $outputSum

    Вывод с датой, как вы и хотели. Плюс после каждого запуска идет сложение с выводом текущей даты, на выходе мы получаем строчку в логе примерно в таком формате 17.01.2018;SUM;1024. То есть это сумма значений за 17,01,2018.

    Это первая часть - сбор данных.

    Осталось проанализировать лог, тут нужно немного подумать :D

    17 января 2018 г. 9:12
  • Ругается на некоректный формат:

    Cannot convert value "377�451.82" to type "System.Double". Error: "Input string was not in a correct format."
    At line:20 char:5
    +     $sum += [double]$_.Size
    +     ~~~~~~~~~~~~~~~~~~~~~~~
        + CategoryInfo          : InvalidArgument: (:) [], RuntimeException
        + FullyQualifiedErrorId : InvalidCastFromStringToDoubleOrSingle

    17 января 2018 г. 9:48
  • Ругается на некоректный формат:

    Cannot convert value "377�451.82" to type "System.Double". Error: "Input string was not in a correct format."
    At line:20 char:5
    +     $sum += [double]$_.Size
    +     ~~~~~~~~~~~~~~~~~~~~~~~
        + CategoryInfo          : InvalidArgument: (:) [], RuntimeException
        + FullyQualifiedErrorId : InvalidCastFromStringToDoubleOrSingle

    Странно, у меня работает.. 

    Попробуйте заменить

    $size = ("{0:N2}" -f $($FolderSize.Sum/1MB)) -replace ",","."

    На 

    $size = "{0:N2}" -f $($FolderSize.Sum/1MB)

    Если это не поможет, то [double] поменяйте на [int] в этой строке $sum += [double]$_.Size

    Проблема в типе данных, что мы получаем из импорта. По умолчанию он [string], следовательно арифметические операции мы не сможем совершать, поэтому нужно конвертировать

    Можете дать вывод лога? У вас что-то с форматом, нужно понять что это такое 

    Cannot convert value "377�451.82" to type "System.Double"
    • Изменено Sergey Ya 17 января 2018 г. 10:21
    17 января 2018 г. 10:14
  • Часть вторая - обработка лога :D

    $csv = Import-Csv $exportPath -Delimiter ";" | ? {$_.Server -eq "SUM"}
    
    for ($i = 0; $i -le ($csv.Count - 1); $i++) {
        if ($i -ne 0) {
            $sum += [double]$csv.Size[$i] - [double]$csv.Size[$i - 1]
        }
    }
    
    $result = $sum / $csv.Length

    Поясняю:

    Каждый раз мы получаем разницу (сегодня минус вчера = разница), далее разницу делим на количество элементов и получаем среднее значение на которое растет наша БД.

    17 января 2018 г. 10:18
  • Изменил строку как Вы сказали на:

    $size = {0:N2} -f $($FolderSize.Sum/1MB)

    Результат тот же. 

    Так же меня [double] на [int] и [string] результата не дало, ошибка таже выходит.

    Где можно вывод лога посмотреть? (Я еще не совсем силен в PowerShell))))

    17 января 2018 г. 14:02
  • Изменил строку как Вы сказали на:

    $size = {0:N2} -f $($FolderSize.Sum/1MB)

    Результат тот же. 

    Так же меня [double] на [int] и [string] результата не дало, ошибка таже выходит.

    Где можно вывод лога посмотреть? (Я еще не совсем силен в PowerShell))))

    В папке куда вы сливаете лог. В моем примере это 

    $exportPath = "C:\export\export.txt"


    Сдается мне, что там пробел стоит. Если так, то замените строку

    $size = ("{0:N2}" -f $($FolderSize.Sum/1MB)) -replace ",","."



    на

    $size = (("{0:N2}" -f $($FolderSize.Sum/1MB)) -replace ",",".") -replace " ", ""


    Для понимания:

    Чтобы избавится от ошибки нужно исключить из лога все посторонние символы (включая пробелы), в противном случае не получится преобразовать строку в число.

    • Изменено Sergey Ya 17 января 2018 г. 14:16
    17 января 2018 г. 14:13
  • Разобрался в чем была проблема.

    В переменную $sum попадает пробел и я ума не приложу почему -replace " ", "" не срабатывает

    Собственно вот рабочий код с "костылем":

    $servers = "server1.com", "server2.com", "server3.com"
    $exportPath = "C:\export\export.txt"
    
    if ((Test-Path $exportPath) -eq $false) {
        Add-Content -Path $exportPath -Value "Date;Server;Size"
    }
    
    Foreach ($server in $servers) {
        Invoke-Command -ComputerName $server -ScriptBlock {
        $folderSize = Get-ChildItem "D:\DB" -Recurse | measure -Property length -Sum;
        $_size = ("{0:N2}" -f $($FolderSize.Sum/1MB)) -replace ",","."
        $size = $_size.Split("")[0] + $_size.Split("")[1] + $_size.Split("")[2] + $_size.Split("")[3]
        $date = Get-Date -Format d
        $output = [string]$date + ";" + $server + ";" + $size
        Write-Output -InputObject $output
        } | Add-Content -Path $exportPath
    }
    
    $csv = Import-Csv $exportPath -Delimiter ";"
    $csv | ? {$_.Date -eq (Get-Date -Format d) -and $_.Server -ne "SUM"} | Foreach {
        $sum += [double]$_.Size
    }
    
    $outputSum = $(Get-Date -Format d) + ";SUM;" + $sum
    Add-Content -Path $exportPath -Value $outputSum
    Не забудьте указать ваши сервера и путь до БД

    • Помечено в качестве ответа KazunEditor 22 января 2018 г. 5:45
    17 января 2018 г. 14:39
  • to Sergey: пробел может быть не пробелом, а например табом или еще чем, в таких случаях хорошо работают '\s*'

    плюс если вы хотите убрать символ(ы) можно использовать -replace '\s*' без второй компоненты


    The opinion expressed by me is not an official position of Microsoft

    17 января 2018 г. 16:19
    Модератор
  • to Sergey: пробел может быть не пробелом, а например табом или еще чем, в таких случаях хорошо работают '\s*'

    плюс если вы хотите убрать символ(ы) можно использовать -replace '\s*' без второй компоненты


    The opinion expressed by me is not an official position of Microsoft

    Спасибо огромное, не знал.

    17 января 2018 г. 17:02