Wraz ze sztuczną inteligencją stworzyłem jakiś czas skrypt PowerShell mający na celu wykonywanie kopii baz danych MS SQL, kompresji za pomocą 7z a następnie przenoszenia tych kopii na FTP i do katalogu który jest synchronizowany z chmurą.
Na FTP przenoszone są pliki z datą wykonania kopii i usuwane starsze pliki, zaś do katalogu chmury kopie są numerowane dniem tygodnia w celu ograniczenia ilości kopii gdyż usunięcie pliku z katalogu nie usuwa z chmury więc muszą być nadpisywane, przynajmniej w moim przypadku właśnie tak się działo.
Nie będę opisywał kolejnych linii kodu i tłumaczył jak to rozwiązanie działa, tak więc ten skrypt jest dla ambitnych którym się chce i są ambitni w jego rozszyfrowaniu. Być może znajdziecie elementy które zrobili byście inaczej lub łatwiej więc z racji iż ten twór jest zrobiony na spółkę ze sztuczną inteligencją możecie śmiało modyfikować i wykorzystywać do własnych celów.
# Ścieżka, gdzie zostaną zapisane kopie baz danych
$backupPath = "E:\BACKUP\TMP"
# Parametry połączenia do serwera SQL
$serverName = ".\MSSQLEXPRESS" # Zastąp odpowiednimi danymi
$username = "sa" # Zastąp odpowiednimi danymi
$password = "MSSQLP@$w00rd" # Zastąp odpowiednimi danymi
# Ustawienie timeout na 600 sekund (10 minut)
$timeout = 600
# Wyślij pliki ZIP na serwer FTP
$ftpServer = "192.168.1.8"
$ftpUsername = "itbackup"
$ftpPassword = "FTPP@$w00rd"
$ftpDestinationDirectory = "/BACKUP/"
#MOBILBOX/"
# Ścieżka docelowa dla skopiowanych plików ZIP
$destinationPath = "E:\BACKUP\CLOUD\CATBAZY"
# Liczba dni, po których starsze pliki zostaną usunięte
$daysToKeep = 7
$daysToKeepTMP = 3
# Tablica z nazwami baz danych do wykonania kopii
$databasesToBackup = @("baza1")
$LogFile = "E:/BACKUP/LOG/" + (Get-Date -Format "yyyyMMdd") + ".MOBILEBOX.log"
# Funkcja do wykonywania kopii baz danych z kompresją do ZIP za pomocą 7-Zip
function Backup-SelectedDatabasesWithCompression {
param (
[string]$serverName,
[string]$username,
[string]$password,
[string]$backupPath,
[int]$timeout,
[string[]]$databasesToBackup
)
# Utwórz połączenie do serwera SQL
$connectionString = "Server=$serverName;Database=master;User Id=$username;Password=$password;"
$connection = New-Object System.Data.SqlClient.SqlConnection
$connection.ConnectionString = $connectionString
$connection.Open()
$sevenZipExe = "C:\Program Files\7-Zip\7z.exe" # Ścieżka do pliku wykonywalnego 7-Zip
$zipFileNames = @() # Tablica do przechowywania nazw plików ZIP
foreach ($databaseName in $databasesToBackup) {
"[START] "+ (Get-Date -Format "yyyy-MM-dd HH:mm:ss") + " " + $databaseName >> $LogFile
# Utwórz ścieżkę do kopii danej bazy danych z datą i nazwą bazy
$timestamp = Get-Date -Format "yyyyMMddHHmmss"
$databaseBackupPath = Join-Path $backupPath "$timestamp-$databaseName.bak"
# Utwórz kopię danej bazy danych
$backupCommand = $connection.CreateCommand()
$backupCommand.CommandText = "BACKUP DATABASE $databaseName TO DISK = '$databaseBackupPath'"
$backupCommand.CommandTimeout = $timeout # Ustaw timeout
try {
$backupCommand.ExecuteNonQuery()
Write-Host "[BAK] OK "+ (Get-Date -Format "yyyy-MM-dd HH:mm:ss") + " Kopia bazy danych wykonana poprawnie."
"[BAK] OK "+ (Get-Date -Format "yyyy-MM-dd HH:mm:ss") + " Kopia bazy danych wykonana poprawnie." >> $LogFile
} catch {
Write-Host "ERROR Kopia bazy danych $databaseName została wykonana i zapisana w $databaseBackupPath"
"[BAK] ERROR "+ (Get-Date -Format "yyyy-MM-dd HH:mm:ss") + " Kopia bazy danych nie została wykonana." >> $LogFile
}
# Kompresuj kopię do formatu ZIP za pomocą 7-Zip (po udanej kopii)
$zipFileName = "$timestamp-$databaseName.zip"
$zipFileNames += $zipFileName
Compress-DatabaseBackupToZIPWith7Zip $databaseBackupPath $zipFileName
#Write-Host "Kopia bazy danych $databaseBackupPath została skopresowana do $zipFileName"
# Usuń plik BAK po udanej kompresji
$backupCommand.CommandTimeout = $timeout # Ustaw timeout
try {
Remove-Item $databaseBackupPath -Force
Write-Host "[BAK] OK "+ (Get-Date -Format "yyyy-MM-dd HH:mm:ss") + " Usunięto okuj BAK po kompresji."
"[BAK] OK "+ (Get-Date -Format "yyyy-MM-dd HH:mm:ss") + " Usunięto okuj BAK po kompresji." >> $LogFile
} catch {
Write-Host "[BAK] INFO "+ (Get-Date -Format "yyyy-MM-dd HH:mm:ss") + " Nie usunięto okuj BAK po kompresji."
"[BAK] INFO "+ (Get-Date -Format "yyyy-MM-dd HH:mm:ss") + " Nie usunięto okuj BAK po kompresji." >> $LogFile
}
Send-ZipFilesToFTP -zipFileName $zipFileName -ftpServer $ftpServer -ftpUsername $ftpUsername -ftpPassword $ftpPassword -ftpDestinationDirectory $ftpDestinationDirectory -backupPath $backupPath -desiredString $databaseName -databaseName $databaseName -daysToKeep $daysToKeep
Remove-OldFilesWithPattern -path $backupPath -daysToKeep $daysToKeepTMP -databaseName $databaseName
}
$connection.Close()
"[END] "+ (Get-Date -Format "yyyy-MM-dd HH:mm:ss") + " " + $databaseName >> $LogFile
}
# Funkcja do kompresji pliku do formatu ZIP za pomocą 7-Zip
function Compress-DatabaseBackupToZIPWith7Zip {
param (
[string]$sourcePath,
[string]$zipFileName
)
$sevenZipExe = "C:\Program Files\7-Zip\7z.exe" # Ścieżka do pliku wykonywalnego 7-Zip
Write-Host "$zipFileName $sourcePath"
# Kompresuj plik do formatu ZIP za pomocą 7-Zip
try {
& $sevenZipExe a -tzip $backupPath\$zipFileName $sourcePath
Write-Host "[ZIP] OK "+ (Get-Date -Format "yyyy-MM-dd HH:mm:ss") + " Kompresja wykonana poprawnie."
"[ZIP] OK "+ (Get-Date -Format "yyyy-MM-dd HH:mm:ss") + " Kompresja wykonana poprawnie." >> $LogFile
} catch {
Write-Host "[ZIP] ERROR "+ (Get-Date -Format "yyyy-MM-dd HH:mm:ss") + " Kopresja nie została wykonana."
"[ZIP] ERROR "+ (Get-Date -Format "yyyy-MM-dd HH:mm:ss") + " Kopresja nie została wykonana." >> $LogFile
}
}
function Delete-FTPFileList($ftpServer, $ftpUsername, $ftpPassword, $ftpDirectory,$databaseName) {
$request = [System.Net.FtpWebRequest]::Create("ftp://$ftpServer$ftpDirectory")
$request.Credentials = New-Object System.Net.NetworkCredential($ftpUsername, $ftpPassword)
$request.Method = [System.Net.WebRequestMethods+Ftp]::ListDirectory
$response = $request.GetResponse()
$reader = New-Object System.IO.StreamReader($response.GetResponseStream())
$directoryListing = $reader.ReadToEnd()
$reader.Close()
$response.Close()
#$directoryListing = $directoryListing -split "`r`n"
#$filteredFiles = $directoryListing -split "`r`n" | Where-Object { $_ -like "*$databaseName*" }
#-------------------
# Inicjalizuj pustą tablicę na dane plików
$fileDataArray = @()
# Iteruj przez listę plików
foreach ($fileInfo in $directoryListing -split "`n") {
Write-Host $fileInfo
# Podziel informacje o pliku
#$fileInfoArray = $fileInfo -split("\s+")
# Uzyskaj nazwę pliku
$fileName = $fileInfo
if ($fileName -and $fileName -like "*$databaseName*") {
# Spróbuj wyciągnąć 12 cyfr z nazwy pliku i potraktować jako datę i czas w formacie yyyyMMddHHmm
$fileNumber = $fileName -replace '[^\d]', '' # Usuń wszystko, co nie jest cyfrą
$fileNumber = $fileNumber.Substring(0, [Math]::Min(12, $fileNumber.Length)) # Weź 12 pierwszych cyfr
try {
$parsedDateTime = [datetime]::ParseExact($fileNumber, "yyyyMMddHHmm", $null)
# Dodaj nazwę pliku i datę do tablicy
$fileDataArray += [PSCustomObject]@{
FileName = $fileName
FileDateTime = $parsedDateTime
}
}
catch {
Write-Host ("Nie udało się sparsować 12 cyfr jako daty i czasu: {0}" -f $_.Exception.Message)
}
}
}
# Sortuj tablicę według daty
$fileDataArray = $fileDataArray | Sort-Object FileDateTime
# Pobierz 14 najmłodszych plików
$youngestFiles = $fileDataArray | Select-Object -First 14
# Pobierz pliki starsze niż 14 najmłodszych
$olderFiles = $fileDataArray | Where-Object { $_.FileDateTime -lt $youngestFiles[-1].FileDateTime }
# Wyświetl pierwsze pliki pomijając 14 ostatnich, gdy jest ich więcej niż 14
$filesToDisplay = $fileDataArray | Select-Object -First ([Math]::Max(0, ($fileDataArray.Count - 14)))
# Zwróć tablicę zawierającą wyłącznie nazwy plików
$fileNamesArray = $filesToDisplay | ForEach-Object { $_.FileName }
# Usuń pliki na serwerze FTP na podstawie listy nazw plików
foreach ($fileNameToDelete in $fileNamesArray) {
Write-Host "ftp://$ftpServer$ftpDirectory$fileNameToDelete"
$ftpDeletePath = "ftp://$ftpServer$ftpDirectory$fileNameToDelete"
$ftpDeleteRequest = [System.Net.FtpWebRequest]::Create($ftpDeletePath)
$ftpDeleteRequest.Credentials = New-Object System.Net.NetworkCredential($ftpUsername, $ftpPassword)
$ftpDeleteRequest.Method = [System.Net.WebRequestMethods+Ftp]::DeleteFile
try {
$ftpDeleteResponse = $ftpDeleteRequest.GetResponse()
Write-Host "[FTP] OK "+ (Get-Date -Format "yyyy-MM-dd HH:mm:ss") +" Plik $fileNameToDelete usunięty z FTP."
"[FTP] OK "+ (Get-Date -Format "yyyy-MM-dd HH:mm:ss") + " Plik $fileNameToDelete usunięty z FTP." >> $LogFile
}
catch {
Write-Host "[FTP] ERROR "+ (Get-Date -Format "yyyy-MM-dd HH:mm:ss") +" Plik $fileNameToDelete usunięty z FTP."
"[FTP] ERROR "+ (Get-Date -Format "yyyy-MM-dd HH:mm:ss") + " Plik $fileNameToDelete usunięty z FTP." >> $LogFile
}
}
#---------------------
return $directoryListing
}
# Funkcja do wysyłania plików na serwer FTP
function Send-ZipFilesToFTP {
param (
[string[]]$zipFileNames,
[string]$ftpServer,
[string]$ftpUsername,
[string]$ftpPassword,
[string]$ftpDestinationDirectory,
[string]$backupPath,
[string]$desiredString,
[string]$databaseName,
[string]$daysToKeep
)
$ftpSession = New-Object System.Net.WebClient
# Ustaw parametry autoryzacji
$ftpSession.Credentials = New-Object System.Net.NetworkCredential($ftpUsername, $ftpPassword)
# Pobierz listę plików na serwerze FTP
$ftpFiles = Delete-FTPFileList $ftpServer $ftpUsername $ftpPassword $ftpDestinationDirectory $databaseName
foreach ($zipFileName in $zipFileNames) {
$sourcePath = Join-Path $backupPath $zipFileName
if (Test-Path $sourcePath) {
# Zapisz zawartość pliku do strumienia FTP
$remoteFilePath = "ftp://$ftpServer$ftpDestinationDirectory$zipFileName"
try {
$ftpSession.UploadFile($remoteFilePath, $sourcePath)
Write-Host "[FTP] OK "+ (Get-Date -Format "yyyy-MM-dd HH:mm:ss") + " ZIP $zipFileName wysłany na FTP."
"[FTP] OK "+ (Get-Date -Format "yyyy-MM-dd HH:mm:ss") + " ZIP $zipFileName wysłany na FTP." >> $LogFile
} catch {
Write-Host "[FTP] ERROR "+ (Get-Date -Format "yyyy-MM-dd HH:mm:ss") + " ZIP $zipFileName nie wysłany na FTP."
"[FTP] ERROR "+ (Get-Date -Format "yyyy-MM-dd HH:mm:ss") + " ZIP $zipFileName nie wysłany na FTP." >> $LogFile
}
# Skopiuj plik do innego katalogu, zmieniając nazwę na numer dnia tygodnia
$dayOfWeek = (Get-Date).DayOfWeek.value__
$newFileName = "$dayOfWeek-$($zipFileName.Substring(15))"
$newPath = Join-Path $destinationPath $newFileName
try {
Copy-Item -Path $backupPath\$zipFileName -Destination $newPath
Write-Host "[CLO] OK "+ (Get-Date -Format "yyyy-MM-dd HH:mm:ss") + " Plik $newFileName skopiowany do katalogu CLOUD."
"[CLO] OK "+ (Get-Date -Format "yyyy-MM-dd HH:mm:ss") + " Plik $newFileName skopiowany do katalogu CLOUD." >> $LogFile
} catch {
Write-Host "[CLO] ERROR "+ (Get-Date -Format "yyyy-MM-dd HH:mm:ss") + " Plik $newFileName nie został skopiowany do katalogu CLOUD."
"[CLO] ERROR "+ (Get-Date -Format "yyyy-MM-dd HH:mm:ss") + " Plik $newFileName nie został skopiowany do katalogu CLOUD." >> $LogFile
}
} else {
Write-Host "[ZIP] ERROR "+ (Get-Date -Format "yyyy-MM-dd HH:mm:ss") + " Plik $zipFileName nie istnieje pod ścieżką: $sourcePath"
"[ZIP] ERROR "+ (Get-Date -Format "yyyy-MM-dd HH:mm:ss") + " Plik $zipFileName nie istnieje pod ścieżką: $sourcePath" >> $LogFile
}
}
}
# Funkcja do usuwania plików starszych niż określona liczba dni i zawierających określony ciąg znaków w nazwie
function Remove-OldFilesWithPattern($path, $daysToKeepTMP, $databaseName) {
Write-Host "[TMP] OK Sprawdzenie i usuwanie starszych plików z TMP"
"[TMP] OK Sprawdzenie i usuwanie starszych plików z TMP" >> $LogFile
# Budowanie maski plików na podstawie nazwy bazy danych
$fileMask = "*$databaseName.*"
# Pobieranie plików według maski, posortowanych po dacie modyfikacji (od najnowszych do najstarszych)
$files = Get-ChildItem -Path $path -Filter $fileMask | Sort-Object LastWriteTime -Descending
# Zachowanie określonej liczby najnowszych plików
$filesToKeep = $files | Select-Object -First $daysToKeepTMP
# Wyświetlenie plików, które zostaną zachowane
Write-Host "[TMP] Pliki, które zostaną zachowane:"
"[TMP] Pliki, które zostaną zachowane:" >> $LogFile
foreach ($file in $filesToKeep) {
Write-Host "[TMP] - $($file.FullName) (Data modyfikacji: $($file.LastWriteTime))"
"[TMP] - $($file.FullName) (Data modyfikacji: $($file.LastWriteTime))" >> $LogFile
}
# Wyszukanie plików do usunięcia
$filesToDelete = $files | Where-Object { $_ -notin $filesToKeep }
# Usuwanie starych plików
foreach ($file in $filesToDelete) {
Remove-Item -Path $file.FullName -Force
Write-Host "[TMP] OK "+ (Get-Date -Format "yyyy-MM-dd HH:mm:ss") + " Usunięto plik $file.FullName z katalogu TMP"
"[TMP] OK "+ (Get-Date -Format "yyyy-MM-dd HH:mm:ss") + " Usunięto plik $file.FullName z katalogu TMP" >> $LogFile
}
Write-Host "[TMP] OK Operacja usuwania starszych plików z TMP zakończona"
"[TMP] OK Operacja usuwania starszych plików z TMP zakończona" >> $LogFile
}
# Wykonaj kopie wybranych baz danych z kompresją do ZIP
Backup-SelectedDatabasesWithCompression -serverName $serverName -username $username -password $password -backupPath $backupPath -timeout $timeout -databasesToBackup $databasesToBackup