经过反复试验,我最终得到了这个适用于 Ubuntu Linux 18.04 的脚本。非常感谢Derik Hammer 和他的博客为脚本提供了基础,也感谢 David Söderlund 的回复。
要使脚本正常工作,您需要安装适用于 Linux 的 PowerShell 以及 DBATools 和 SqlCmd2 PowerShell 模块。您还必须将 sql 凭据存储在某个文件中。我选择/var/opt/mssql/secrets/creds.xml
了我的并将访问权限更改为仅 root。脚本可以将登录、DBmail 设置、SQL 代理类别、作业、操作员和计划从主副本同步到所有辅助副本(取消注释您需要的内容,但要小心,顺序很重要,有些东西不能在一个连接中同步,即操作员和作业) ,跳过配置副本(如果有)。
您可以以 root 身份设置计划执行,并使用 CRON 将输出记录到文件中。要进行此设置,请运行:
sudo crontab -e
并将这一行添加到文件中:
*/5 * * * * pwsh /<PATH>/sync-sql-objects.ps1 >> /<PATH>/sync-sql-objects.log
脚本:
<#
.DESCRIPTION
This script will detect your Availability Group replicas and copy all of its instance level objects from primary replica to secondary replicas within the Availability Group. It will skip any configuration replicas.
.EXAMPLE
sudo pwsh sync-sql-objects.ps1
.NOTES
One limitation of this script is that it assumes you only have one availability group. This script should run on your configuration replica server.
.LINK
https://www.sqlhammer.com/synchronizing-server-objects-for-availability-groups/
DEBUG
To see logs on Ubuntu Linux, install Postfix Mail Transfer Agent and then go to see mails in /var/mail/<username>
#>
Write-Output ("Sync started: " + (Get-Date -Format G))
#Error handling
$ErrorActionPreference = "stop";
Trap
{
$err = $_.Exception
while ( $err.InnerException )
{
$err = $err.InnerException
Write-Output $err.Message
};
}
# Prerequisites
try
{
Write-Output "Valiating prerequisites."
# You need to have these modules installed in advance, otherwise the import will fail
if ((Get-Module -Name dbatools) -eq $null)
{
Import-Module dbatools | Out-Null
}
if ((Get-Module -Name Invoke-SqlCmd2) -eq $null)
{
Import-Module Invoke-SqlCmd2 | Out-Null
}
Write-Output "Prerequisites loaded."
}
catch
{
Write-Error $_.Exception.Message -EA Continue
Write-Error "One or more of the prerequisites did not load. Review previous errors for more details." -EA Continue
return
}
# Detect Availability Group replicas
Write-Output "Begin query for Availability Group replicas"
$ConfigurationMode = "CONFIGURATION_ONLY"
$Hostname = hostname
$Credentials = Import-CliXml -Path /var/opt/mssql/secrets/creds.xml
$ReplicasQuery = @"
SELECT replica_server_name,
availability_mode_desc,
primary_replica
FROM sys.availability_replicas AR
INNER JOIN sys.dm_hadr_availability_group_states HAGS
INNER JOIN sys.availability_groups AG ON AG.group_id = HAGS.group_id
ON HAGS.group_id = AR.group_id;
"@
$Replicas = Invoke-Sqlcmd2 -ServerInstance $Hostname -Query $ReplicasQuery -ConnectionTimeout 30 -Credential $Credentials
if(([DBNull]::Value).Equals($Replicas[0].primary_replica))
{
Write-Error "Availability Group query returned no results. Confirm that you connected to a SQL Server instance running an Availability Group. No work was accomplished."
return
}
Write-Output "Completed query of Availability Group replicas"
foreach($replica in $Replicas)
{
# Skip if destination replica is primary replica itself
if($replica.primary_replica.CompareTo($replica.replica_server_name) -eq 0)
{
continue
}
# Skip configuration replicas
if($replica.availability_mode_desc.CompareTo($ConfigurationMode) -eq 0)
{
continue
}
#Connect
$PrimaryReplica = Connect-DbaInstance $replica.primary_replica -ClientName 'ConfigurationReplica' -SqlCredential $Credentials
$SecondaryReplica = Connect-DbaInstance $replica.replica_server_name -ClientName 'ConfigurationReplica' -SqlCredential $Credentials
Write-Output "Copying instance objects from $sourceReplica to $replica"
# Copy objects
# Write-Output "Copying Logins."
# Copy-DbaLogin -Source $PrimaryReplica -Destination $SecondaryReplica
# Write-Output "Copying DBMail."
# Copy-DbaDbMail -Source $PrimaryReplica -Destination $SecondaryReplica -Force
# Write-Output "Copying Agent Categories."
# Copy-DbaAgentJobCategory -Source $PrimaryReplica -Destination $SecondaryReplica -Force
# Write-Output "Copying Agent Schedules."
# Copy-DbaAgentSchedule -Source $PrimaryReplica -Destination $SecondaryReplica -Force
# Write-Output "Copying Operators."
# Copy-DbaAgentOperator -Source $PrimaryReplica -Destination $SecondaryReplica -Force
Write-Output "Copying Jobs."
Copy-DbaAgentJob -Source $PrimaryReplica -Destination $SecondaryReplica -Force
Write-Output "Copy complete from $PrimaryReplica to $SecondaryReplica"
}
Write-Output "SQL Instance object sync complete."
享受!