Skip to content

Instantly share code, notes, and snippets.

@Kimserey
Last active September 30, 2015 22:09
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Kimserey/7c0790b9ff27575949df to your computer and use it in GitHub Desktop.
Save Kimserey/7c0790b9ff27575949df to your computer and use it in GitHub Desktop.
Sqlite backup script
@echo off
cls
C:\"Program Files (x86)"\"Microsoft SDKs"\F#\4.0\Framework\v4.0\Fsi.exe .\script.fsx %1 %2 %3
//
// Backup script
// Generate backup for Sqlite dbs
//
// Arguments [ 1:db path; 2:base output path; 3:instance name ]
//
open System
open System.Text
open System.IO
open System.Text.RegularExpressions
open System.Diagnostics
open System.Globalization
type BackupResult =
| BackupSuccess of TimeSpan
| BackupFailure of string * exn * TimeSpan
| BackupTimeout of TimeSpan
type ClearExpiredBackupResult =
| ExpiredBackupCleaningSuccess of string
| ExpiredBackupCleaningFailure of string * exn
| ExpiredBackupCleaningNotNeeded of string
type FileDb = {
name: string
path: string
}
let regexMath pattern input = Regex.IsMatch(input, pattern)
let masterdataRegexPattern = "masterdata.(\d+|\^).db"
let generateBackup dbPath bakupPath db =
let timer = Stopwatch.StartNew ()
try
let psi =
new ProcessStartInfo(
"sqlite3",
sprintf """%s/%s ".timeout 20000" ".backup %s/%s""" dbPath db bakupPath db,
CreateNoWindow = false, ErrorDialog = false, LoadUserProfile = false,
UseShellExecute = false, WindowStyle = ProcessWindowStyle.Normal,
RedirectStandardInput = true,
RedirectStandardOutput = true,
RedirectStandardError = true (* set this to false to allow printing of verbose messages *))
let proc = Process.Start psi
match proc.WaitForExit (TimeSpan.FromSeconds(20.).TotalMilliseconds |> int) with
| true when proc.ExitCode = 0 -> BackupSuccess timer.Elapsed
| true -> BackupFailure ("Exited with error code " + string proc.ExitCode, null, timer.Elapsed)
| false -> BackupTimeout timer.Elapsed
with
| ex -> BackupFailure ("Unexpected failure with " + ex.Message, ex, timer.Elapsed)
let deleteExpiredBackups basePath (date: DateTime) =
printfn "\nStart clearing expired backup:\n-------------------"
Directory.GetDirectories(basePath)
|> Seq.map (fun x ->
try
let backupDate = DateTime.Parse(x.Split([|'\\'; '/'|]) |> Seq.last, CultureInfo.InvariantCulture)
if backupDate < date.AddDays(-7.) then
Directory.Delete(x, true)
ExpiredBackupCleaningSuccess ("Success clearing: " + x)
else ExpiredBackupCleaningNotNeeded ("Not expired: " + x)
with
| ex -> ExpiredBackupCleaningFailure ("Failed to clear: " + x + " - " + ex.Message, ex))
|> Seq.iter (function
| ExpiredBackupCleaningSuccess message -> printfn "%s" message
| ExpiredBackupCleaningFailure (message, ex) -> printfn "%s" message
| ExpiredBackupCleaningNotNeeded message -> printfn "%s" message)
basePath, date
let getBackupFolder instanceName (basePath: string, date: DateTime) =
let fullPath = basePath.Replace("\\", "/").TrimEnd('/') + "/" + date.ToString("yyyy-MM-dd") + "/" + instanceName
Directory.CreateDirectory(fullPath) |> ignore //create directory if does not exists
fullPath
let generateBackups dbPath backupFolder =
printfn "\nStart generating backups:\n-------------------"
Directory.GetFiles dbPath
|> Seq.map (fun x -> { path = x.Split([|'\\'; '/'|]) |> Seq.rev |> Seq.skip(1) |> Seq.rev |> String.concat "/"
name = x.Split([|'\\'; '/'|]) |> Seq.last })
|> Seq.filter (fun x -> regexMath masterdataRegexPattern x.name |> not)
|> Seq.map (fun f ->
printfn "Generating backup for %s/%s" backupFolder f.name
generateBackup f.path backupFolder f.name)
|> Seq.iter (fun r -> match r with
| BackupSuccess i -> printfn "Sucess %f sec" i.TotalSeconds
| BackupFailure (message, ex, i) -> printfn "%s %f sec" message i.TotalSeconds
| BackupTimeout i -> printfn "Timeout after %f sec" i.TotalSeconds)
//Main function
match fsi.CommandLineArgs with
| [| script; dbPath; outputPath; instanceName |] ->
//delete expired backups - create backup folder - generates backups
DateTime.Now
|> deleteExpiredBackups outputPath
|> getBackupFolder instanceName
|> generateBackups dbPath
printfn "------\nDone"
| _ -> failwith "Arguments missing please specify 1:dbpath 2:outputpath 3:instanceName"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment