Периодическое полное резервное копирование фермы SharePoint 2013 с помощью PowerShell

imageПри использовании System Center 2012 R2 Data Protection Manager (DPM) в качестве инструмента для резервного копирования фермы SharePoint Server 2013 реализуются такие преимущества, как например Item-Level Recovery, когда при необходимости можно достаточно оперативно выполнить восстановление отдельного элемента списка SharePoint или какого-либо документа из библиотеки документов SharePoint. Однако, как я понимаю, для сценариев Disaster Recovery может оказаться более полезным наличие полной резервной копии фермы SharePoint, сделанной средствами самого SharePoint. В качестве исходного материала для размышлений о преимуществах и недостатках разных методов резервного копирования данных SharePoint можно взять например слайды samhassani.com - Slide deck for "SharePoint 2013 Backup and Recovery with DPM 2012" from SharePoint Evolution Conference Published.

Для того, чтобы настроить резервное копирование фермы SharePoint с помощью DPM достаточно установить Агент DPM на WFE-сервер SharePoint и согласно документа Использование программы ConfigureSharePoint произвести настройку этого Агента командой:

cd /d "C:\Program Files\Microsoft Data Protection Manager\DPM\bin"
ConfigureSharepoint.exe -EnableSharePointProtection

image

При запросе учетной записи WSSCmdletsWrapper можно указать учетную запись Database Access account, или как её ещё по другому называют SharePoint Farm service account, (в нашем примере s-KOM-AD01-SP-Farm).

После выполнения этой команды в консоли сервера DPM у нас появится возможность выполнения резервного копирования данных фермы SharePoint 2013.

***

Для автоматизации же выполнения полного резервного копирования всех данных фермы SharePoint средствами самого SharePoint (без применения DPM) в сети можно найти ряд примеров, как то TechNet Blogs -  Team blog of MCS @ Middle East and Africa -  SharePoint 2013 Backup with PowerShell and Task Scheduler for beginners или Get in the Sky  - SharePoint Backup Best Practice. Развивая эту тему в конечном итоге у меня получился PowerShell скрипт, работающий на PS-командлетах SharePoint 2013 SP1 и контролирующий удаление старых полных резервных копий фермы:

# Блок переменных
#
# BackupFolder - Путь к каталогу резервных копий SharePoint
# BackupReport - Полный путь к XML файлу описания резервных копий spbrtoc.xml
# BackupLog - Полный путь к файлу лога выполнения операций
# Days - Количество дней хранения резервных копий
# EmailTo - Адрес электронной почты для отправки письма при возникновении проблем.
# EmailServer - Имя почтового сервера. Если на сервере SharePoint установлена служба SMTP, то можно указать localhost
# EmailFrom - Адрес электронной почты отправителя
#
$BackupFolder = "\\kom-ad01-fscl\BACKUP_SharePointFarm$\"
$BackupReport  = $BackupFolder + "spbrtoc.xml"
$BackupLog = $BackupFolder +"Logs\SPFarm-Backup-" + $(Get-Date -Format yyyy-MM-dd) + ".log"
$Days = 7
$EmailTo = "DST-SharePoint-Farm-Admins@holding.com"
$EmailServer = "KOM-AD01-MAIL"
$EmailFrom = "KOM-AD01-WEB03@holding.com"
$PSScriptLogPath = $PSScriptRoot + "\SP2013-Farm-Full-Backup.log"
#
# Блок вспомогательных функций
#
#
$ErrorActionPreference="SilentlyContinue"
Stop-Transcript | Out-Null
$ErrorActionPreference = "Continue"
Start-Transcript -Path $PSScriptLogPath -Append
#
Function WriteLog ($Text) 
{
    Write-Host $Text -ForegroundColor Green    
    Add-Content $BackupLog "$(Get-Date -Format o)`t $Text"
}
#
Function SendMail ([String]$vSubject, [String]$vBody) 
{
    Send-MailMessage -From $EmailFrom -Subject $vSubject -To $EmailTo -Body $vBody -SmtpServer $EmailServer
}
#
#
# Блок создания новой резервной копии фермы SharePoint
#
#
Add-PSSnapin "Microsoft.SharePoint.PowerShell"
Try
{
    WriteLog "Backing up SharePoint Farm... "
    Backup-SPFarm -Directory $BackupFolder -BackupMethod Full -Verbose -Percentage 5
    WriteLog "Done."
}
Catch [System.Exception] 
{
    WriteLog "An error occured while backing up the SharePoint Farm: $_."
    SendMail "SharePoint Farm Backup Failed" "ERROR: $_."
}
#
#
# Блок удаления устаревших резервных копий
#
#
Try 
{
    $LatestDate = (Get-Date).adddays(-$Days)
    [xml]$FileData = Get-Content $BackupReport
    $BackupEvents = $FileData.SPBackupRestoreHistory.SPHistoryObject
    ForEach ($BackupEvent in $BackupEvents) {
        $BackupDate = [DateTime]$BackupEvent.SPStartTime
        If ($BackupDate -lt $LatestDate) {

        WriteLog "Delete the old backup report item from the XML file for date $BackupDate ..."
        $FileData.SPBackupRestoreHistory.RemoveChild($BackupEvent)

        [System.String]$DelDir = $BackupEvent.SPBackupDirectory
        WriteLog "Delete the old backup folder $DelDir ..."
        Remove-Item $DelDir -Recurse

        WriteLog "Save Sharepoint backup report XML file ..."
        $FileData.Save($BackupReport)
    
        }
    }

}
Catch [system.exception] 
{
    WriteLog "An error occured while deleting backups older than $Days days: $_."
    SendMail "SharePoint Backup Warning: An error occured while deleting backups older than $Days days" "ERROR: $_."
}
WriteLog "------------- Operations are completed -------------"
Stop-Transcript

Как видно, помимо удаления самих файлов старых резервных копий скриптом производится корректировка файла spbrtoc.xml, который используется SharePoint для описания результата всех прошедших операций резервного копирования.

По условиям нашей задачи полученный скрипт нужно настроить на выполнение на периодической основе. Сделать это можно например создав задание в Планировщике задач Windows на WFE-сервере SharePoint.

Сохраним скрипт, например с именем:
C:\Tools\ScheduledScripts\SP2013-Farm-Full-Backup.ps1
В подкаталоге со скриптом создадим пустой лог файл, например:
C:\Tools\ScheduledScripts\SP2013-Farm-Full-Backup.log

Теперь нам нужно определиться с тем, от имени какой учетной записи будет выполняться скрипт резервного копирования фермы SharePoint. И здесь можно пойти несколькими путями. Наверное самым правильным из них с точки зрения безопасности будет создание отдельной доменной учетной записи именно для операций резервного копирования фермы, однако такой метод повлечёт за собой необходимость ряда дополнительных манипуляций для наделения этой учетной записи всеми нужными полномочиями на уровне объектов SQL Server и SharePoint. Если пойти по более упрощённому сценарию, то для запуска скрипта можно использовать учетную запись фермы — Database Access account, или как её ещё по другому называют SharePoint Farm service account, (в нашем примере s-KOM-AD01-SP-Farm). В большинстве случаев у этой учетной записи уже есть все необходимые разрешения на уровне объектов SQL Server и SharePoint. Исключением может стать например то, что эта учетная запись может быть не включена в группу локальных Администраторов на нашем WFE-сервере SharePoint. В таком случае при попытке выполнения PS-командлета резервного копирования фермы SharePoint мы можем получить ошибку:

VERBOSE: Leaving BeginProcessing Method of Backup-SPFarm.
An error occured while backing up the SharePoint Farm: You need to have Machine administrator priviliges to run this cmdlet..

Чтобы избежать этой ошибки, потребуется включить учетную запись фермы в группу локальных Администраторов на нашем WFE-сервере SharePoint, что само по себе, как мы понимаем, уже не есть “best practice”, но если мы пошли по пути использования именно учетной записи фермы, то нам придётся смириться с данным обстоятельством. Таким образом давать отдельно разрешение возможности изменения лог-файла SP2013-Farm-Full-Backup.log нам не потребуется.

Итак, в нашем примере для запуска скрипта будет использоваться учетная запись фермы s-KOM-AD01-SP-Farm и поэтому после её включения в группу Администраторов, нам потребуется выполнить перезапуск сервера SharePoint, чтобы расширенные права вступили в силу.

После перезагрузки нам нужно проверить отработку скрипта с запуском от имени учетной записи фермы. Для этого с помощью утилиты PsExec сначала запустим командную строку (в режиме повышенных привилегий) от имени этой учетной записи:

psexec -u "KOM\s-KOM-AD01-SP-Farm" -e -i -h "cmd"

В запущенной командной строке выполним запуск нашего скрипта таким же образом, как он будет выполнятся в дальнейшем в Планировщике задач.

powershell.exe -NoProfile -command "C:\Tools\ScheduledScripts\SP2013-Farm-Full-Backup.ps1"

image

 

В результате выполнения команды мы должны убедиться в том, что скрипт отработал без ошибок и в файл лога SP2013-Farm-Full-Backup.log добавлена информация о выполнении скрипта. Этот лог может оказаться нам полезен в случае, если по какой-то причине скрипт будет выполняться с ошибками, отловить которые при запуске скрипта в скрытом режиме из Планировщика будет весьма затруднительно.

image

 

Создаваемый скриптом сокращённый вариант лога, в котором фиксируются только ошибки выполнения можно найти в корневой общей папке резервных копий в подкаталоге \Logs

image

 

Расширенный вариант лога создаваемого SharePoint в процессе резервного копирования можно найти в папке отдельной резервной копии, например \spbr0003\spbackup.log

image

 

Увидеть статус выполнения резервного копирования можно также на веб-узле Центра администрирования (ЦА) фермы SharePoint пройдя по ссылкам Central Administration > Backup and Restore > Farm Backup and Restore > View backup and restore history

image

 

В таблице истории запусков резервного копирования разворачиваем запись о соответствующем бэкапе и убеждаемся в том, что счетчик ошибок и предупреждений равен 0

 

image

 

Как видим, в нашем случае скрипт отрабатывает без ошибок, и поэтому теперь мы можем создать соответствующее задание в Планировщике задач.

Задача будет выполняется вне зависимости от входа в систему от имени учетной записи фермы (потребуется ввод и сохранение её учетных данных)

image

Время выполнения задачи устанавливаем с учетом других процессов автоматизации, желательно на нерабочее время.

image

В качестве выполняемого действия вводим проверенную ранее команду запуска PowerShell с соответствующими параметрами.

image

 

Дожидаемся выполнения задания планировщика по заданному расписанию и проверяем результат в ЦА и/или ранее обозначенных лог-файлах.

По истечении количества дней указанного в скрипте в переменной $Days убеждаемся в том, что старые архивные копии действительно корректно удаляются…

image

Всего комментариев: 15 Комментировать

  1. Eugene Leitan /

    Алексей. очередной раз очень полезная статья! :) Спасибо!

    Хотел добавить, что разрешения на запись для BackupFolder (Путь к каталогу резервных копий SharePoint) нужны не только учетной записи фермы — Database Access account, или как её ещё по другому называют SharePoint Farm service account, (в примере s-KOM-AD01-SP-Farm), НО и учетной записи SQL, от имени которой работает служба SQL SharePoint.

    Иначе: SharePoint 2010: Cannot open backup device 'F:\[foldername]'. Operating system error 5(Access is denied.) (http://social.technet.microsoft.com/wiki/contents/articles/20732.sharepoint-2010-cannot-open-backup-device-f-foldername-operating-system-error-5-access-is-denied.aspx)

    Также дополнительно создал папку Logs в $BackupFolder, т.к. скриптом она не создается.

    1. Алексей Максимов / Автор записи

      Ну здесь то я писал про SharePoint 2013, и на 2010 это проверено разумеется не было.

      1. Eugene Leitan /

        Я тоже проверял на Sharepoint 2013, а решение нашел в статье про Sharepoint 2010. :)
        Кстати замечено что, если нет доступа или прервана операция архивирования, то на веб-узле Центра администрирования (ЦА) фермы SharePoint нет счетчико ошибок, поэтому лучше проверять лог :)

      2. Eugene Leitan /

        Ссылка на решение в SharePoint 2013:
        Reminder: Use a UNC path as the destination for the Backup-SPFarm cmdlet (http://blogs.technet.com/b/alexsearch/archive/2014/02/06/reminder-to-use-a-unc-path-for-the-destination-directory-for-the-backup-spfarm-cmdlet.aspx)

  2. Алексей Максимов / Автор записи

    Действительно про разрешения на шару я ничего не написал. Как-то упустил это из виду. Я просто помню, что ещё в лохматые времена использования SP2010 предоставление доступа к шаре для учетной записи SQL Server было как-то очевидно, и даже по-моему где-то на течнете было про это написано. Видимо поэтому я и не стал заострять на этом внимание. Ну ты своим комментарием восполнил этот пробел.

  3. Андрей /

    Алексей, доброго времени суток!
    Огромное спасибо за статью - практически готовое решение одной из основных задач обслуживания шарика. Сделал все, как описано - работает на отлично!
    За одним мелким недочетом - не критичным, но несколько неприятным - при удалении и добавлении записей в файл spbrtoc.xml в русифицированной версии шарпойнта при запуске скрипта планировщиком вместо названия топового компонента: "Ферма" появляется невнятная строка - " Ферма ".
    При запуске из того же планировщика задания вручную - все нормально, прописывается "Ферма". Не посоветуете, где можно посмотреть/подкрутить сей глюк? Подозреваю, что на уровне системы, но как то никак не соображу где... ((

    1. Алексей Максимов / Автор записи

      Могу только предположить, что есть какая-то разница в региональных настройках между учётной записью, от имени которой запускается задание в шедулере, и вашей учётной записью, от имени которой вы пробуете ручной запуск скрипта.

      1. Андрей /

        ...да нет, и логинюсь, и запускаю задание, и скрипт по расписанию запускается от одной и той же записи. И настройки региональные вроде проверял...
        Причем, если в расписании стоит установка "запускать из-под зарегистрировавшегося пользователя" пишется "Ферма" (но в случае перезапуска серверов без логина, естественно, задание запуститься не может), если так же, как указано в статье, то задание запустится в любом случае, но напишется кракозябра в spbrtoc.xml. И, кстати, я так подозреваю, в этот файл пишет инфу при обновлении/удалении старых баз не сам скрипт? А процедура шарпойнта, осуществляющая бэкап?

        1. Алексей Максимов / Автор записи

          Да, файл пишется процедурой бэкапа. Скрипт лишь удаляет из файла записи о старых бэкапах.

          1. Андрей /

            Позволю себе еще раз поднять тему...
            В общем, выяснилось в процессе эксплуатации скрипта вот что - на самом деле, оказалось, что пункт в задании не при чем (см. предыдущий мой пост). Кракозябры появляются только тогда, когда начинает работать блок скрипта по удалению старых бэкапов и дописыванию spbrtoc.xml Т.е. когда скрипт только начинает работать на чистой директории, название топового уровня пишется нормально - "Ферма". НО! как только начинается удаление старых и дописывание файла, туда пишется слово "Ферма" (в кодировке UTF-8) перекодированная в ANSI ! А на следующий день эта кракозябра (которая уже вписана в spbrtoc.xml с кодировкой UTF-8) снова перекодируется в ANSI и так далее - получая строку символов все длиннее и длиннее (такая, видимо, особенность перекодировки этих символов). Попытки изменять кодировку скрипта и spbrtoc.xml ни к чему не привели. Пользователь, от которого выполняется скрипт, прописан русскоязычным везде, где можно, но воз и ныне там... (((

          2. Андрей /

            ... нашел решение. В блоке удаления старых бекапов в строке с командой Get-content достаточно добавить ключик -Encoding UTF8
            Насколько я понял, повершелл работает на уровне системы с кодировкой ANSI, а шарик пишет spbrtoc.xml в UTF8, поэтому для устранения разночтений, так сказать, надо явно указать в команде кодировку, с которой надо работать.

  4. Арсений /

    Спасибо за полезную статью. Всё время рекомендую ваш блог коллегам. Небольшое дополнение, чтобы решение было полным можно сделать if и развести бэкапы на полные и дифференциальные. Например вот так:
    $today = Get-Date
    $full = 'Saturday'
    Try
    {
    $ExistsBackups = (Get-SPBackupHistory -Directory $BackupFolder -ShowBackup)
    If ($ExistsBackups -eq $null)
    {
    WriteLog "Backing up SharePoint Farm Full... "
    Backup-SPFarm -Directory $BackupFolder -BackupMethod Full -Verbose -Percentage 5
    WriteLog "Done."
    }
    else
    {
    if ($full -eq $today)
    {
    WriteLog "Backing up SharePoint Farm Full... "
    Backup-SPFarm -Directory $BackupFolder -BackupMethod Full -Verbose -Percentage 5
    WriteLog "Done."
    }
    else
    {
    WriteLog "Backing up SharePoint Farm Differential... "
    Backup-SPFarm -Directory $BackupFolder -BackupMethod Differential -Verbose -Percentage 5
    WriteLog "Done."
    }
    }
    }

  5. Обратная ссылка: Попытка резервного копирования фермы SharePoint 2013 приводит к исключению Backup-SPFarm : An update conflict has occurred, and you must re-try this action …SPUpdatedConcurrencyException – Бло /

  6. Обратная ссылка: SharePoint Server 2016 Search Service in Paused for Backup/Restore /

  7. Алексей Максимов / Автор записи

    Решение применимо к SharePoint Server 2016/2019

Добавить комментарий