Вопрос или проблема
Мы готовимся избавиться от Exchange на месте и переходим от аутсорсинг-провайдера к Office 365. У нас работает полностью обновленная версия Exchange 2013 на полностью обновленном сервере 2012.
Во время миграции тестовых почтовых ящиков мы обнаружили, что многие ящики в разных базах данных повреждены. Более подробную информацию о причине можно найти ЗДЕСЬ. По сути: SAN, на котором хранится наш Exchange VM, перегружен, и регулярно время ожидания ввода-вывода превышает 5 секунд, а скорость чтения редко превышает 500 КБ/с.
Медленные скорости были бы достаточны, чтобы вызвать значительные потери времени во время миграции, но когда сталкиваешься с поврежденными ящиками, миграция 1 ГБ данных превращается из 2-3 часов в 10-20 часов. Каждый из ящиков, у которых есть проблемы (которые я нашел до сих пор), выдает сообщения, подобные приведенному ниже, когда проверяются с помощью get-mailboxstatistics:
ПРЕДУПРЕЖДЕНИЕ: Объект <GUID> поврежден и находится в неконсистентном состоянии. Произошли следующие ошибки проверки:
ПРЕДУПРЕЖДЕНИЕ: Не удается извлечь значение свойства 'DeletedItemCount'. Источник: PropTag(DeletedMsgCount), PropType(Int), RawValue(-2), RawValueType(System.Int32). Цель:
Type(System.Nullable`1[System.UInt32]), IsMultiValued(False). Подробности об ошибке: <n/a>
Запуск New-MailboxRepairRequest для всех баз данных выявил некоторые повреждения и восстановил их, но не все. Я не могу найти способ, чтобы Get-MailboxStatistics зафиксировал тот факт, что в каждом из этих ящиков что-то сломано, хотя я уверен, что такой способ есть. Перемещение ящиков из одной базы данных в другую, похоже, решает проблему. У нас примерно 50 баз данных и около 50 пользователей в каждой базе, поэтому проходить через это вручную невозможно.
Что я хочу сделать, используя PowerShell (простите за ленивый псевдокод, пожалуйста):
foreach ($mailbox in $database){
if get-mailboxstatisics -eq $corrupted {
move $mailbox to $otherdb
wait
move $mailbox back to $database}
}
Тем не менее, я не могу понять, как поймать текст “Предупреждение: это сломано” из Get-MailboxStatistics, и возвращаемый объект не имеет ничего, что показывало бы, что он поврежден.
Мне просто нужно поймать предупреждение и предположить, что все, что жалуется на несовместимость, можно исправить таким образом, а затем вернуться и проверить список ящиков, которые действительно имеют проблему, после того как они были перемещены обратно, чтобы узнать, все ли еще сломано? Или есть лучший способ сделать то, что мне нужно?
Замена SAN не входит в рамки возможного, так же как и исправление любых других основных причин.
Чтобы изолировать сообщения от существующих командлетов PowerShell, вы можете использовать
Переменная предупреждения
Большинство командлетов по умолчанию имеют параметр -WarningVariable
, вы можете объединить это с -WarningAction SilentlyContinue
, чтобы подавить предупреждение и сохранить его вывод в переменной, которую затем можно будет обрабатывать или отображать любым удобным вам образом. Так вы можете выполнить следующий код
$mailbox | Get-MailboxStatistics -WarningAction SilentlyContinue -WarningVariable MyWarning;
if($MyWarning -like '*corrupted*'){
Write-Host "возможное повреждение";
}
Я попробовал воспроизвести событие предупреждения, чтобы дважды проверить вышеизложенное, но не смог сделать это через командлет MailboxStats. Выше должно работать – но не тестировалось в этом контексте.
Ответ или решение
Чтобы идентифицировать почтовые ящики с повреждениями в Exchange 2013 и упростить миграцию на Office 365, можно воспользоваться PowerShell и алгоритмом, который поможет автоматизировать проверку каждого почтового ящика. Давайте рассмотрим, как можно реализовать эту задачу.
Общий подход
- Использование cmdlet Get-MailboxStatistics для проверки состояния почтовых ящиков.
- Пользоваться параметрами
-WarningVariable
и-WarningAction
для фильтрации сообщений о предупреждениях и выявления поврежденных объектов. - Перемещение поврежденных почтовых ящиков в другую базу данных и обратно для устранения повреждений.
Набор команд PowerShell
Вот полный скрипт PowerShell, который поможет вам в выполнении описанной задачи:
# Получаем список всех баз данных Exchange
$databases = Get-MailboxDatabase
foreach ($database in $databases) {
# Получаем все почтовые ящики в текущей базе данных
$mailboxes = Get-Mailbox -Database $database.Identity
foreach ($mailbox in $mailboxes) {
# Проверяем статус почтового ящика и сохраняем предупреждения
$MyWarning = $null
$stats = Get-MailboxStatistics -Identity $mailbox.Identity -WarningAction SilentlyContinue -WarningVariable MyWarning
# Если в предупреждении содержится слово "corrupted", значит, почтовый ящик поврежден
if ($MyWarning -like '*corrupted*') {
Write-Host "Обнаружено возможное повреждение для почтового ящика: $($mailbox.Identity)"
# Перемещение поврежденного почтового ящика в другую базу данных
$otherDb = Get-MailboxDatabase | Where-Object { $_.Identity -ne $database.Identity } | Get-Random
Write-Host "Перемещение $($mailbox.Identity) из $database в $otherDb"
# Перемещаем почтовый ящик
New-MoveRequest -Identity $mailbox.Identity -TargetDatabase $otherDb.Identity
# Ожидаем завершения перемещения
do {
Start-Sleep -Seconds 10
$moveRequest = Get-MoveRequest -Identity $mailbox.Identity
} while ($moveRequest.Status -eq 'InProgress')
# Перемещение обратно в исходную базу данных
Write-Host "Перемещение $($mailbox.Identity) обратно в $database"
New-MoveRequest -Identity $mailbox.Identity -TargetDatabase $database.Identity
# Ожидаем завершения повторного перемещения
do {
Start-Sleep -Seconds 10
$moveRequest = Get-MoveRequest -Identity $mailbox.Identity
} while ($moveRequest.Status -eq 'InProgress')
Write-Host "Почтовый ящик $($mailbox.Identity) был успешно перемещен и возвращен."
}
}
}
Объяснение скрипта
- Получение списка баз данных: Сначала мы получаем все базы данных Exchange, в которых находятся почтовые ящики.
- Цикл по почтовым ящикам: Далее мы проходим по каждому почтовому ящику и проверяем его состояние с помощью
Get-MailboxStatistics
. - Фильтрация предупреждений: Мы сохраняем предупреждения в переменной
$MyWarning
и проверяем наличие слова "corrupted", чтобы выявить поврежденные почтовые ящики. - Перемещение почтовых ящиков: Если повреждение обнаружено, почтовый ящик временно перемещается в другую базу данных, а затем возвращается обратно, что может помочь исправить ошибки.
Заключение
Использование данного скрипта позволит вам автоматизировать процесс выявления и устранения поврежденных почтовых ящиков в Exchange 2013. Это не только сэкономит время, но и повысит эффективность миграции в Office 365. Не забывайте выполнять регулярные резервные копии и проверять состояние ваших баз данных, чтобы избежать подобных проблем в будущем.