Первый скрипт
Задача сделать синхронизацию логинов с праймери реплики в mssql на секондори реплики с проверкой паролей совпадают или нет . если не совпадают то скопировать логин с правильным паролем. Сделал проверку по хэшу паролей. Лог будет удаляться из папки старше 7 дней
Set-DbatoolsInsecureConnection -SessionOnly
# Параметры
$AGListenerName = "db01" # Имя листенера группы доступности
$LogFolder = "D:\DBA_scripts_AG\log"
$MaxLogAge = 7 # Максимальный возраст логов в днях
# Создаем папку для логов если не существует
if (-not (Test-Path $LogFolder)) {
New-Item -ItemType Directory -Path $LogFolder -Force | Out-Null
}
# Удаляем старые логи (старше 7 дней)
Get-ChildItem -Path $LogFolder | #-Filter "LoginSync_*.log"
Where-Object { $_.LastWriteTime -lt (Get-Date).AddDays(-$MaxLogAge) } |
Remove-Item -Force
# Создаем лог-файл с датой в имени
$LogPath = Join-Path $LogFolder ("LoginSync_" + (Get-Date -Format "yyyyMMdd_HHmmss") + ".log")
# Функция для получения хэша пароля
function Get-SqlLoginHash {
param (
[string]$SqlInstance,
[string]$LoginName
)
try {
$query = @"
SELECT CAST(LOGINPROPERTY(name, 'PasswordHash') AS varbinary(256)) AS PasswordHash
FROM sys.sql_logins
WHERE name = '$LoginName'
"@
$result = Invoke-DbaQuery -SqlInstance $SqlInstance -Query $query -ErrorAction Stop
return $result.PasswordHash
}
catch {
Write-Output "Ошибка при получении хэша для $LoginName на $SqlInstance : $_" | Out-File $LogPath -Append
return $null
}
}
# Начало выполнения
Write-Output "Начало синхронизации: $(Get-Date)" | Out-File $LogPath -Append
# Получаем информацию о группе доступности
try {
$AG = Get-DbaAvailabilityGroup -SqlInstance $AGListenerName -ErrorAction Stop
$primaryReplica = $AG.AvailabilityReplicas | Where-Object { $_.Role -eq "Primary" }
$secondaryReplicas = $AG.AvailabilityReplicas | Where-Object { $_.Role -eq "Secondary" }
Write-Output "Первичная реплика: $($primaryReplica.Name)" | Out-File $LogPath -Append
Write-Output "Вторичные реплики: $($secondaryReplicas.Name -join ', ')" | Out-File $LogPath -Append
}
catch {
Write-Output "Ошибка при получении информации о группе доступности: $_" | Out-File $LogPath -Append
exit
}
# Получаем SQL-логины с первичной реплики
try {
$primaryLogins = Get-DbaLogin -SqlInstance $primaryReplica.Name -Type SQL -ExcludeSystemLogin -ExcludeFilter '##*','NT *','sa'
Write-Output "Найдено SQL-логинов на первичной реплике: $($primaryLogins.Count)" | Out-File $LogPath -Append
$primaryLogins | Select-Object Name | Out-File $LogPath -Append
}
catch {
Write-Output "Ошибка при получении логинов с первичной реплики: $_" | Out-File $LogPath -Append
exit
}
# Создаем коллекцию для несовпадающих логинов
$mismatchedLogins = @()
# Обрабатываем каждую вторичную реплику
foreach ($secondaryReplica in $secondaryReplicas) {
$secondaryServer = $secondaryReplica.Name
Write-Output "`nОбработка вторичной реплики: $secondaryServer" | Out-File $LogPath -Append
try {
# Получаем логины с вторичной реплики
$secondaryLogins = Get-DbaLogin -SqlInstance $secondaryServer -Type SQL -ExcludeSystemLogin -ExcludeFilter '##*','NT *','sa'
Write-Output "Найдено SQL-логинов на вторичной реплике: $($secondaryLogins.Count)" | Out-File $LogPath -Append
$secondaryLogins | Select-Object Name | Out-File $LogPath -Append
# Сравниваем каждый логин
foreach ($login in $primaryLogins) {
$secondaryLogin = $secondaryLogins | Where-Object Name -eq $login.Name
if ($secondaryLogin) {
# Получаем хэши паролей
$primaryHash = Get-SqlLoginHash -SqlInstance $primaryReplica.Name -LoginName $login.Name
$secondaryHash = Get-SqlLoginHash -SqlInstance $secondaryServer -LoginName $login.Name
if ($primaryHash -and $secondaryHash) {
# Сравниваем хэши
if (Compare-Object $primaryHash $secondaryHash) {
$mismatchInfo = [PSCustomObject]@{
LoginName = $login.Name
PrimaryServer = $primaryReplica.Name
SecondaryServer = $secondaryServer
Status = "PasswordMismatch"
}
$mismatchedLogins += $mismatchInfo
Write-Output "Разные пароли для логина: $($login.Name)" | Out-File $LogPath -Append
# Обновляем логин
#Copy-DbaLogin -Source $primaryReplica.Name -Destination $secondaryServer -Login $login.Name -Force
Write-Output "Обновлен логин: $($login.Name)" | Out-File $LogPath -Append
}
else {
Write-Output "Пароли совпадают для: $($login.Name)" | Out-File $LogPath -Append
}
}
}
else {
$mismatchInfo = [PSCustomObject]@{
LoginName = $login.Name
PrimaryServer = $primaryReplica.Name
SecondaryServer = $secondaryServer
Status = "MissingOnSecondary"
}
$mismatchedLogins += $mismatchInfo
# Копируем отсутствующий логин
#Copy-DbaLogin -Source $primaryReplica.Name -Destination $secondaryServer -Login $login.Name -Force
Write-Output "Добавлен новый логин: $($login.Name)" | Out-File $LogPath -Append
}
}
# Удаляем лишние логины
foreach ($login in $secondaryLogins) {
if ($login.Name -notin $primaryLogins.Name) {
$mismatchInfo = [PSCustomObject]@{
LoginName = $login.Name
PrimaryServer = $primaryReplica.Name
SecondaryServer = $secondaryServer
Status = "ExtraOnSecondary"
}
$mismatchedLogins += $mismatchInfo
#Remove-DbaLogin -SqlInstance $secondaryServer -Login $login.Name -Force
Write-Output "Удален лишний логин: $($login.Name)" | Out-File $LogPath -Append
}
}
}
catch {
Write-Output "Ошибка при обработке вторичной реплики $secondaryServer : $_" | Out-File $LogPath -Append
}
}
# Выводим сводку по несовпадающим логинам
if ($mismatchedLogins.Count -gt 0) {
Write-Output "`nСводка по несовпадающим логинам:" | Out-File $LogPath -Append
Write-Output "=================================" | Out-File $LogPath -Append
$mismatchedLogins | Format-Table -AutoSize | Out-File $LogPath -Append
# Экспортируем несовпадающие логины в CSV
$csvPath = Join-Path $LogFolder ("LoginSyncMismatches_" + (Get-Date -Format "yyyyMMdd_HHmmss") + ".csv")
$mismatchedLogins | Export-Csv -Path $csvPath -NoTypeInformation -Encoding UTF8
Write-Output "Список несовпадающих логинов сохранен в: $csvPath" | Out-File $LogPath -Append
}
else {
Write-Output "`nВсе логины синхронизированы, несовпадений не обнаружено." | Out-File $LogPath -Append
}
Write-Output "`nСинхронизация завершена: $(Get-Date)" | Out-File $LogPath -Append
Similar Posts:
- Как бэкапить логины (login) и задания (JOB) mssql через dbatools
- Как в always on mssql синхронизировать логины и пароль на вторичной реплики и удалять логины когда удалили на первичной.
- Как синхронизировать обьекты в always on c первичной реплики на вторичную
- Как в always on mssql синхронизировать JOB на вторичной реплики и удалять JOB со вторичной когда удалили на первичной.
- Как импортировать сертификат для компьютера в личное (personal\my) хранилище сертификатов.
