Olá pessoal!
Tudo certo?
Neste post vou demonstrar como fazer backup de todos os jobs do SQL Server Agent via linha de comando (CLR C# ou Powershell) e exportar os resultados para scripts SQL. Você pode optar por gerar 1 script para cada job ou 1 script único com todos os jobs da sua instância.
Durante a migração do SQL Server 2008 R2 para o 2014 esse script foi especialmente útil, uma vez que na instância do servidor de relatórios existiam pouco mais de 700 jobs e a tarefa de salvar o script de cada um manualmente não era viável. Fazer o backup/restore do database msdb poderia ser uma solução (embora não ache muito recomendável), mas como se tratavam de versões diferentes do SQL Server, descartamos essa hipótese.
Lembre-se que antes de fazer o restore dos jobs no novo ambiente, você precisará ter criado os logins na instância nova. Caso você não saiba como fazer o backup dos logins e suas permissões, acesse o post SQL Server – Como transferir logins entre instâncias gerando backup de usuários, logins e permissões.
Pré-requisitos
Como pré-requisitos para a utilização da Stored Procedure stpJob_Backup, você precisará criar também, os objetos abaixo:
Utils.ExecutaScriptPowerShell (Clique aqui para acessar o post)
Visualizar código-fonte
Código fonte do arquivo Servidor.cs
Visualizar código-fonte
Código-fonte da classe Retorno (Clique aqui para acessar o post)
Visualizar código-fonte
Código-fonte da Procedure do CLR (C#) stpJob_Backup
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 |
using System; using System.Data.SqlTypes; using Bibliotecas.Model; public partial class StoredProcedures { [Microsoft.SqlServer.Server.SqlProcedure] public static void stpJob_Backup(SqlString Ds_Servidor, SqlString Ds_Diretorio_Destino, SqlBoolean Fl_Arquivo_Unico) { try { var comando = @" $ServerNameList = """ + Ds_Servidor.Value + @""" [System.Reflection.Assembly]::LoadWithPartialName(""Microsoft.SqlServer.Smo"") | Out-Null $objSQLConnection = New-Object System.Data.SqlClient.SqlConnection foreach ($ServerName in $ServerNameList) { Try { $objSQLConnection.ConnectionString = ""Server=$ServerName;Integrated Security=SSPI;"" Write-Host ""Tentando se conectar na instância do servidor $ServerName..."" -NoNewline $objSQLConnection.Open() | Out-Null Write-Host ""Conectado."" $objSQLConnection.Close() } Catch { Write-Host -BackgroundColor Red -ForegroundColor White ""Falha"" $errText = $Error[0].ToString() if ($errText.Contains(""network-related"")) {Write-Host ""Erro de conexão à instância. Por favor, verifique o nome do servidor digitado, porta ou firewall.""} Write-Host $errText continue } $OutputFolder = """ + Ds_Diretorio_Destino.Value + @""" $DoesFolderExist = Test-Path $OutputFolder $null = if (!$DoesFolderExist){MKDIR ""$OutputFolder""} $srv = New-Object ""Microsoft.SqlServer.Management.Smo.Server"" $ServerName"; if (Fl_Arquivo_Unico.Value) { comando += @" $srv.JobServer.Jobs | foreach {$_.Script() + ""GO`r`n""} | out-file ""$OutputFolder\jobs.sql"""; } else { comando += @" $srv.JobServer.Jobs | foreach-object -process {out-file -filepath $(""$OutputFolder\"" + $($_.Name -replace '\\', '') + "".sql"") -inputobject $_.Script() }"; } comando += @" }"; var saida = Utils.ExecutaScriptPowerShell(comando); Retorno.Mensagem(saida); } catch (Exception e) { Retorno.Erro("Erro : " + e.Message); } } }; |
Exemplos de uso
Agora vou demonstrar como utilizar a Stored Procedure criada para exportar o script SQL de todos os jobs do SQL Server Agent. Esses são os jobs atuais da instância.
Exemplo 1:
Neste exemplo, vou demonstrar como exportar o script de criação de todos os jobs da instância, sendo 1 arquivo sql para cada job.
1 2 3 4 |
EXEC CLR.dbo.stpJob_Backup @Ds_Servidor = N'VM-DBA', -- nvarchar(max) @Ds_Diretorio_Destino = N'C:\Temp\Jobs', -- nvarchar(max) @Fl_Arquivo_Unico = 0 -- bit |
Exemplo 2:
Neste exemplo, vou demonstrar como exportar o script de criação de todos os jobs da instância, sendo 1 arquivo sql contendo o script de todos os jobs.
1 2 3 4 |
EXEC CLR.dbo.stpJob_Backup @Ds_Servidor = N'VM-DBA', -- nvarchar(max) @Ds_Diretorio_Destino = N'C:\Temp\Jobs', -- nvarchar(max) @Fl_Arquivo_Unico = 1 -- bit |
Utilizando apenas o PowerShell e OLE Automation
Caso você não queira utilizar o CLR para esta solução e deseja utilizar apenas o PowerShell pelo banco de dados, você também pode fazê-lo.
Pré-requisitos
Como pré-requisitos para utilizar a procedure abaixo, precisaremos de algumas funções para manipulação de arquivos. Para isso, utilizaremos o OLE Automation para manipular esses arquivos. Para saber mais sobre isso, veja o post Operações com arquivos utilizando OLE Automation no SQL Server.
stpEscreve_Arquivo_FSO
Visualizar código-fonte
fncArquivo_Existe_FSO
Visualizar código-fonte
stpApaga_Arquivo_FSO
Visualizar código-fonte
Stored Procedure stpExecuta_Script_Powershell
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 |
CREATE PROCEDURE [dbo].[stpExecuta_Script_Powershell] @Ds_Script [varchar](MAX), @Fl_Apaga_Script [bit] = 1 AS BEGIN SET NOCOUNT ON DECLARE @QuebraLinha VARCHAR(10) = CHAR(13) + CHAR(10), @arquivo VARCHAR(MAX), @diretorio VARCHAR(MAX) = 'C:\Temp\', @scriptPS VARCHAR(MAX) = CAST(NEWID() AS VARCHAR(50)) + '.ps1', @caminho VARCHAR(MAX) SET @caminho = @diretorio + @scriptPS EXEC dbo.stpEscreve_Arquivo_FSO @String = @Ds_Script, -- varchar(max) @Ds_Arquivo = @caminho -- varchar(1501) SET @scriptPS = @diretorio + @scriptPS DECLARE @cmd VARCHAR(4000) SET @cmd = 'powershell -ExecutionPolicy Unrestricted -File "' + @scriptPS + '"' DECLARE @Retorno TABLE (Ds_Texto VARCHAR(MAX)) INSERT INTO @Retorno EXEC master.dbo.xp_cmdshell @cmd -- Apaga o script gerado IF (@Fl_Apaga_Script = 1) BEGIN EXEC dbo.stpApaga_Arquivo_FSO @strArquivo = @scriptPS -- varchar(1000) END SELECT * FROM @Retorno END |
Exemplo de uso:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 |
DECLARE @Script VARCHAR(MAX) = ' $ServerNameList = "VM-DBA" $OutputFolder = "C:\Teste\Jobs\" $DoesFolderExist = Test-Path $OutputFolder $null = if (!$DoesFolderExist){MKDIR "$OutputFolder"} [System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SqlServer.Smo") | Out-Null $objSQLConnection = New-Object System.Data.SqlClient.SqlConnection foreach ($ServerName in $ServerNameList) { Try { $objSQLConnection.ConnectionString = "Server=$ServerName;Integrated Security=SSPI;" Write-Host "Tentando se conectar na instância do servidor $ServerName..." -NoNewline $objSQLConnection.Open() | Out-Null Write-Host "Conectado." $objSQLConnection.Close() } Catch { Write-Host -BackgroundColor Red -ForegroundColor White "Falha" $errText = $Error[0].ToString() if ($errText.Contains("network-related")) {Write-Host "Erro de conexão à instância. Por favor, verifique o nome do servidor digitado, porta ou firewall."} Write-Host $errText continue } $srv = New-Object "Microsoft.SqlServer.Management.Smo.Server" $ServerName # Arquivo único com todos os jobs # $srv.JobServer.Jobs | foreach {$_.Script() + "GO`r`n"} | out-file "$OutputFolder\jobs.sql" # Um arquivo por job $srv.JobServer.Jobs | foreach-object -process {out-file -filepath $("$OutputFolder\" + $($_.Name -replace "\\", "") + ".sql") -inputobject $_.Script() } }' EXEC dbo.stpExecuta_Script_Powershell @Ds_Script = @Script, -- varchar(max) @Fl_Apaga_Script = 0 -- bit |
Utilizando apenas PowerShell
Se você quiser utilizar apenas script PowerShell manualmente, segue abaixo o script completo.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 |
# Nome da sua máquina $ServerNameList = "VM-DBA" # Diretório para salvar os scripts $OutputFolder = "C:\Jobs\" $DoesFolderExist = Test-Path $OutputFolder $null = if (!$DoesFolderExist){MKDIR "$OutputFolder"} [System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SqlServer.Smo") | Out-Null $objSQLConnection = New-Object System.Data.SqlClient.SqlConnection foreach ($ServerName in $ServerNameList) { Try { $objSQLConnection.ConnectionString = "Server=$ServerName;Integrated Security=SSPI;" Write-Host "Tentando se conectar na instância do servidor $ServerName..." -NoNewline $objSQLConnection.Open() | Out-Null Write-Host "Conectado." $objSQLConnection.Close() } Catch { Write-Host -BackgroundColor Red -ForegroundColor White "Falha" $errText = $Error[0].ToString() if ($errText.Contains("network-related")) {Write-Host "Erro de conexão à instância. Por favor, verifique o nome do servidor digitado, porta ou firewall."} Write-Host $errText continue } $srv = New-Object "Microsoft.SqlServer.Management.Smo.Server" $ServerName # Arquivo único com todos os jobs # $srv.JobServer.Jobs | foreach {$_.Script() + "GO`r`n"} | out-file "$OutputFolder\jobs.sql" # Um arquivo por job $srv.JobServer.Jobs | foreach-object -process {out-file -filepath $("$OutputFolder\" + $($_.Name -replace "\\", "") + ".sql") -inputobject $_.Script() } } |
É isso aí, pessoal.
Um grande abraço e até a próxima.
SQL Server – Como fazer backup de todos os jobs do SQL Agent via linha de comando (CLR C# ou Powershell) backup restore sql server agent jobs command line
SQL Server – Como fazer backup de todos os jobs do SQL Agent via linha de comando (CLR C# ou Powershell) backup restore sql server agent jobs command line
Maravilha de post!!! Excelente para ser utilizado para guardar reversa de create de usuários e respectivos grants também! 🙂
Obrigado pelo feedback, Herica. Em breve teremos um post de reversa de usuários e permissões salvando em scripts sql para auxiliar em migrações 🙂
Que post incrível!!!
Você tem que ensinar power Shell pro dono desse blog: http://rafaelsodre.com.br/blog