Automatická záloha / restore / replikace MS SQL Express pomoci powershellu.
Problém je že tato verze neobsahuje agenta který v určitý
čas provede automatickou zálohu nebo restore.Představte si že máte primární server
z důležitou databází(samozřejmě verze sql serveru je express).Dále máte backup
server který má sloužit jako záložní.Pokud padne primární prostě se plynule
přejde na sekundární.
Úkol tedy zní:zálohovat v určitém intervalu primární
server.Zálohu přesunout někam do bezpečí(jiný stroj,jiná lokace).Posléze provést
restore na záložním serveru.
V podstatě se jedná o automatickou replikaci MS SQL Express pomocí powershellu.Přidaná
hodnota je že můžeme replikovat na více strojů plus zálohu odkládat jako backup.Veškeré
úkony provedené/neprovedené jsou zaznamenány v rozsáhlem logu který nás
informuje jak job proběhl.
Skript dáme
samozřejmě spouštět ve windows(plánovač úloh). Interval zálohy je daný nastavením scheduleru.
################################ Vytvoril:Petr Skrivan #########################
#musime naimportovat modul pro praci s sql serverem
import-module -Name sqlps
#import modulu bohuzel rozhazi pocatecni
UNC cesty takze se musime..
#.. prepnout do rootu jinak neprojde nic kde se pouzivaji
UNC cesty
cd c:
#o provedene/neprovedene zaloze
odesilam zpravu a prilozim podrobny log
#..v podobe txt souboru
#..v podobe txt souboru
function sendemail ($subject,$body)
{
$smtpKlient = new-object system.net.mail.smtpClient
$zprava = New-Object system.net.mail.mailmessage
$prihlaseni = New-Object system.net.NetworkCredential
$prihlaseni.username = "vasmejl@organizace.cz"
$smtpKlient.Host = "192.168.150.1"
$smtpKlient.Credentials = $prihlaseni
$zprava.From = "error@organizace.cz"
$zprava.To.Add("error@organizace.cz")
$zprava.Subject = $subject
$zprava.Body = $body
$cesta = "c:/zalohadbwebserver.txt"
$priloha = New-Object system.net.mail.attachment($cesta)
$zprava.Attachments.Add($priloha)
$smtpKlient.Send($zprava)
$priloha.Dispose()
sleep 2
exit
}
#naformatuji dnesni datum do
podoby napr 24.8.2014
$dnes = Get-Date -format d.M.yyyy
$dnes >
c:/zalohadbwebserver.txt #zapis do logu
###########
kontrola zda jsou na serveru databaze ktere chceme zalohovat #######
#nuluji pomocnou promennou
$polenazvudb = " "
#seznam kontrolovanych a nasledne
zalohovanych db
$kontrolovanedb = "databaze1","jinadatabaze","dalsidatabaze"
#nactu si nazvy vsech databazi na
serveru pomoci filtru select rikam ze chci jen jmena
$mamedatabaze = dir sqlserver:\sql\webserver\default\databases | select Name
#nuluji pomocnou promennou
$nenalezena = ""
#ze seznamu databazi setavim
jeden dlouhy string
$mamedatabaze | foreach {$polenazvudb += $_.name}
#seznam kontrolovanych databazi
poslu do kolecka a otestuji zda existuji na serveru
$kontrolovanedb | foreach{
#pokud je jmeno databaze nalezeno
v dlouhem stringu zapiu to do logu
if ($polenazvudb -match $_)
{"Databaze $_ na zdroji
nalezena" >> c:/zalohadbwebserver.txt }
#else se provede jen kdyz neni
jmeno databaze nalezeno v dlouhem stringu
else
#do pomocne promenne se prida
jmeno databaze jenz nebyla nalezena
{$nenalezena += "$_,
"
"Databaze $_ na zdroji
nenalezena" >> c:/zalohadbwebserver.txt}
}#konec kolecka foreach
#pokud promenna $nenalezena neco
obsahuje pak nejaka databaze nebyla nalezena odeslu email s
#..infem o tom ktera databaze nebyla nalezena
#..infem o tom ktera databaze nebyla nalezena
if ($nenalezena){sendemail "zaloha
webserver" "tyto database nebyly zálohovany $nenalezena "}
" " >>
c:/zalohadbwebserver.txt
#!!!!!!!!!! Zacatek velkeho kolecka foreach
!!!!!!!!!!!!!!!!!!!!!!!!
#nyni mame v promenne
$kontrolovanedb jen existujici nazvy validnich datbazi
foreach($dbvroure in $kontrolovanedb)
{
################### kontrola statusu databaze na zdrojovem
serveru
##########
#import modulu nam zajistil ze z sql serverem muzu pacovat s pomoci dir
$kontrolazdroj = dir sqlserver:\sql\dbserver\default\databases | Where-Object {$_.name -match $dbvroure}
if ($kontrolazdroj -notmatch "normal") # pokud je status normalni
{(Get-Date -format "H:mm:ss")+": Status
databaze $dbvroure na zdrojovem serveru : OK" >>
c:/zalohadbwebserver.txt }
else
{"kontrola statusu db:
$dbvroure na zdrojovem serveru selhala" >> c:/zalohadbwebserver.txt
sendemail "zaloha
webserver" "kontrola statusu db: $dbvroure na zdrojovem serveru
selhala"}
#################### mazani moznych duplicit
#################################
#podivame se do adresare ktery je
momentalne v kolecku na soubor ktery ma nazev
#..jako dnesni datum
#..jako dnesni datum
$duplicitnidb = dir \\192.168.150.25\c$\Backup\MSSQL\$dbvroure\$dnes.bak
#pokud najdeme soubor ktery je ve
spravnem adresari a ma nazev jako $dnes
#..podminka projde a soubor bude smazan
#..podminka projde a soubor bude smazan
if($duplicitnidb)
{
Remove-Item $duplicitnidb
}
##############################
zaloha databazi
##################################
#zalohuj vybranou databazi na
vybranem serveru nazev zalohy bude dnesni datum
backup-sqldatabase
-ServerInstance dbserver -Database $dbvroure -BackupFile "C:\Backup\MSSQL\$dbvroure\$dnes.bak"
(Get-Date -format "H:mm:ss")+": Na
zdrojovem serveru zalohuji databazi: $dbvroure" >>
c:/zalohadbwebserver.txt
sleep 5
################
konekt do adresare se zalohami na zdroji ######################
#do promenne si nactu kompletni
obsah adresare
$zdrojzalohadb = dir \\192.168.100.25\c$\Backup\MSSQL\$dbvroure
(Get-Date -format "H:mm:ss")+":
Pripojuji adresar se zalohami na zdrojovem serveru databaze: $dbvroure" >>
c:/zalohadbwebserver.txt
#otestuji zda mam spojeni na
server a zda dana slozka obsahuje nejake zalohy
IF(!$zdrojzalohadb)
{
#volam funkci sendemail a
predavam ji parametry
"nemohu se pripojit do
adresare $dbvroure se zalohami na zdrojovem serveru pro databazi:
$dbvroure" >> c:/zalohadbserver.txt
sendemail "zaloha dbserver" "nebylo se mozne spojit se serverem,nebo slozka neobsahuje
zadne zalohy pro db $dbvroure"
}
###################### hledani dnesni databaze na zdroji
#######################
#obsah adresare poslu do roury
a najdu slozku jejiz datum vytvoreni odpovida
#.. dnesnimu datumu
#.. dnesnimu datumu
$dneszdrojzalohadb = $zdrojzalohadb | where-object {$_.CreationTime.GetDateTimeFormats()[0]
-match $dnes}
#pokud zadane misto obsahuje dva
a vice souboru s dnesnim datumem neco je spatne
#..takze posilam emajl a ukoncuji program
#..takze posilam emajl a ukoncuji program
if ($dneszdrojzalohadb.Count -gt 1)
{
#volam funkci sendemail a
predavam ji parametry
"Adresar se zalohami na
zdrojovem serveru obsahuje vicero souboru s dnesnim datem nelze urcit vhodny
soubor zalohy pro db: $dbvroure" >> c:/zalohadbwebserver.txt
sendemail "zaloha
dbserver" "adresar se zalohami na zdrojovem serveru obsahuje vicero
souboru s dnesnim datumem nelze urcit spravny soubor jedna se o:
$dbvroure"
}
#otestuji zda byla nalezena
dnesni zaloha testuji zda je promenna prazdna
#..pokud ano odeslu email
#..pokud ano odeslu email
IF(!$dneszdrojzalohadb)
{
#volam funkci sendemail a
predavam ji parametry
"Na zdrojovem serveru v
adresari zaloh nebyl nalezen soubor z dnesnim datem vytvoreni pro db:
$dbvroure" >> c:/zalohadbwebserver.txt
sendemail "zaloha
dbserver" "Na zdrojovem serveru v adresari zaloh nebyl nalezen soubor
z dnesnim datem vytvoreni pro db: $dbvroure"
}
#zbyva jen soubor s dnesnim
datumem takze si jeho jmeno ulozim do promenne
$jmenodneszdrojzalohadb = $dneszdrojzalohadb.name
(Get-Date -format "H:mm:ss")+": Na
zdrojovem serveru nalezen soubor $jmenodneszdrojzalohadb kopiruji na zalozni
server do adresare $dbvroure" >> c:/zalohadbwebserver.txt
####################
kopirovani backupu na zalozni server #######################
#zkopiruj ze zadaneho adresare
zadany file do zadane destinace
copy-item \\192.168.150.25\c$\Backup\MSSQL\$dbvroure\$jmenodneszdrojzalohadb -Destination \\192.168.150.16\c$\backup\$dbvroure\
#sleep 5
(Get-Date -format "H:mm:ss")+": Testuji
zda zaloznim serveru existuje databaze: $dbvroure" >>
c:/zalohadbwebserver.txt
$existujedatabaze = dir sqlserver:\sql\vm-webbackup\Default\databases | Where-Object {$_.name -match "$dbvroure"}
#otestujeme zda na serveru
existuje databaze delame restore takze databaze uz
#..musi na serveru byt jinak dojde k selhani
#..musi na serveru byt jinak dojde k selhani
IF(!$existujedatabaze)
{
#volam funkci sendemail a
predavam ji parametry
"na zaloznim serveru nebyla
nalezena db: $dbvroure" >> c:/zalohadbwebserver.txt
sendemail "zaloha
dbserver" "na zaloznim serveru nebyla nalezena db: $dbvroure"
}
#####################
restore databaze na zaloznim serveru
####################
sleep 5
#restor databazi na
vm-webbackup pomoci serverinstance skript je spoustem primo
#...na stroji vm-webbackup takze nepouzivam unc cesty ale vse provadim lokalne
#...na stroji vm-webbackup takze nepouzivam unc cesty ale vse provadim lokalne
(Get-Date -format "H:mm:ss")+":
Provadim restore databaze $dbvroure na zaloznim serveru " >>
c:/zalohadbwebserver.txt
try{
Restore-SqlDatabase
-ServerInstance vm-webbackup -Database $dbvroure -BackupFile
C:\backup\$dbvroure\$jmenodneszdrojzalohadb -RestoreAction Database
-ReplaceDatabase
} #konec bloku try
Catch
{
(Get-Date -format "H:mm:ss")+": Restore
databaze $dbvroure na zaloznim serveru se nepodarila" >>
c:/zalohadbwebserver.txt
sendemail "zaloha
dbserver" "Restore databaze $dbvroure na zaloznim serveru se
nepodarila"
} #konec bloku catch
############### kontrola statusu databaze na zaloznim
serveru
###############
$kontrolazdroj = dir sqlserver:\sql\vm-webbackup\default\databases | Where-Object {$_.name -match $dbvroure}
if ($kontrolazdroj.Status -notmatch "normal")
{"kontrola statusu db:
$dbvroure na zaloznim serveru selhala" >> c:/zalohadbwebserver.txt
sendemail "zaloha
dbserver" "kontrola statusu db: $dbvroure na zaloznim serveru
selhala"}
else
{(Get-Date -format "H:mm:ss")+": Status
databaze $dbvroure na zaloznim serveru: OK" >>
c:/zalohadbwebserver.txt }
################# odstranim stare soubory na zaloznim serveru
##################
cd \\192.168.150.16\c$\backup\$dbvroure
sleep 2
$smaz = dir | Where-Object {$_.name -notmatch $dnes}
(Get-Date -format "H:mm:ss")+": Mazu
stare zalohy na zaloznim serveru delete: $dbvroure" >>
c:/zalohadbwebserver.txt
Remove-Item $smaz
" " >>
c:/zalohadbwebserver.txt
} #
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> KONEC HLAVNIHO KOLECKA FOREACH
#toto je nutne jinak se rozhazi
UNC cesty u ostatnich skriptu
Remove-Module -Name sqlpsukázka logu: