├── README.md ├── filters ├── backup_duplicacy.sh └── backup_duplicacy.ps1 /README.md: -------------------------------------------------------------------------------- 1 | # Duplicacy Backups 2 | 3 | The scripts here will run automated backups using duplicacy on Windows (powershell) or Linux (bash). The wiki also contains some documentation on how to set up duplicacy and some explanation of what the various commands do. 4 | 5 | See [the wiki](https://github.com/mattjm/duplicacy-script/wiki) for documentation on how to use the scripts. 6 | 7 | 8 | -------------------------------------------------------------------------------- /filters: -------------------------------------------------------------------------------- 1 | e:.*\$RECYCLE\.BIN/.* 2 | e:.*/System\sVolume\sInformation/.* 3 | e:.*/RECYCLER/.* 4 | e:.*/I386.* 5 | e:.*/pagefile.sys 6 | e:.*/MSOCache.* 7 | e:.*UsrClass\.dat\.LOG 8 | e:.*UsrClass\.dat 9 | e:.*/Temporary\sInternet\sFiles/.* 10 | e:(?i).*ntuser.dat.* 11 | e:.*Local\sSettings/Temp.* 12 | e:.*AppData/Local/Temp.* 13 | e:.*AppData/Temp.* 14 | e:.*/Windows/Temp.* 15 | e:(?i).*/Microsoft.*/Windows/.*\.log 16 | e:.*/Microsoft.*/Windows/Cookies.* 17 | e:.*/Microsoft.*/RecoveryStore.* 18 | e:(?i).:/Config\\.Msi.* 19 | e:(?i).*\\.rbf 20 | e:.*/Windows/Installer.* 21 | e:.*/Application\sData/Application\sData.* 22 | e:(?i).:/Config\.Msi.* 23 | e:(?i).*\.rbf 24 | e:(?i).*/Microsoft.*/Windows/.*\.edb 25 | e:(?i).*/Google/Chrome/User\sData/Default/Cookies(-journal)?", "(?i).*/Safari/Library/Caches/.* 26 | e:.*\.tmp 27 | e:.*\.tmp/.* 28 | e:.*\.part 29 | e:.*/iPhoto Library/iPod\sPhoto\sCache/.* 30 | e:.*/Music/Subscription/.* 31 | e:(?i).*/Google/Chrome/.*cache.* 32 | e:(?i).*/Mozilla/Firefox/.*cache.* 33 | e:.*/Google/Chrome/Safe\sBrowsing.* 34 | e:.*/Google/Chrome/User\sData/Default/File\sSystem.* 35 | e:.*/Google/Chrome/User\sData/Default/IndexedDB.* 36 | e:.*/Google/Chrome/User\sData/Default/Local\sStorage.* 37 | e:.*/Google/Chrome/User\sData/Safe\sBrowsing.* 38 | e:.*/(cookies|permissions).sqllite(-.{3})? 39 | e:.*Downloads 40 | e:.*AppData/Local/Akamai.* 41 | e:.*AppData/Roaming/Amazon\sCloud\sDrive.* 42 | e:.*Dashlane/.* 43 | e:.*Spotify/.* 44 | e:.*AppData/Local/Packages.* 45 | e:.*AppData/Roaming/Slack.* 46 | e:.*go/.* 47 | e:.*backup_logs/duplicacy.log -------------------------------------------------------------------------------- /backup_duplicacy.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # assumes binary is named "duplicacy" and is in the PATH of the user running the script 4 | # logging displays stderr and stdout to console and appends both to the log file 5 | 6 | # space separated list of folders to back up 7 | backup_paths=( "/home/user/" "/home/user2" ) 8 | 9 | # where to put logs 10 | log_folder="/home/user/backup_logs/" 11 | log_file_name="duplicacy.log" 12 | log_path=${log_folder}${log_file_name} 13 | 14 | # size in bytes to roll over log 15 | log_max_size=5242880 # default 5 megabytes 16 | 17 | 18 | 19 | rollover_logs () { 20 | 21 | # create log file if it's missing 22 | if [ ! -f "$log_path" ] 23 | then 24 | echo "Log file missing. Creating..." 2>&1 | tee $log_path 25 | touch ${log_path} 26 | fi 27 | 28 | log_size=$(wc -c < "$log_path") 29 | echo "Current log size is: "${log_size} 30 | 31 | #roll over log if max size exceeded 32 | if [ $log_size -gt $log_max_size ] 33 | then 34 | echo "Log exceeds max size of "${log_max_size}". Rolling over log..." 35 | mv $log_path ${log_path}.$(date -Iseconds) 36 | fi 37 | 38 | 39 | } 40 | 41 | rollover_logs 42 | 43 | 44 | for path in "${backup_paths[@]}" 45 | do 46 | echo "running backups for "${path}" at $(date -Iseconds)" 2>&1 | tee -a ${log_path} 47 | cd ${path} 48 | if [ ! $? -eq 0 ] 49 | then 50 | echo "ERROR: Problem switching to path "${path}". Skipping this backup location..." 2>&1 | tee -a ${log_path} 51 | # error is not fatal--we'll skip this one and try the other locations 52 | continue 53 | fi 54 | duplicacy prune -keep 0:360 -keep 30:180 -keep 7:30 -keep 1:7 2>&1 | tee -a ${log_path} 55 | duplicacy backup -stats 2>&1 | tee -a ${log_path} 56 | duplicacy prune --delete-only 2>&1 | tee -a ${log_path} 57 | # duplicacy prune -keep 0:360 -keep 30:180 -keep 7:30 -keep 1:7 -storage b2 2>&1 | tee -a ${log_path} 58 | # duplicacy copy -to b2 -threads 10 2>&1 | tee -a ${log_path} 59 | # duplicacy prune --delete-only -storage b2 2>&1 | tee -a ${log_path} 60 | echo "completed backups and pruning for "${path}" at $(date -Iseconds)" 2>&1 | tee -a ${log_path} 61 | done -------------------------------------------------------------------------------- /backup_duplicacy.ps1: -------------------------------------------------------------------------------- 1 | $duplicacyBinary = "C:\Users\myuser\AppData\Local\Duplicacy\duplicacy.exe" 2 | 3 | # comma separated list of folders to back up 4 | $backupLocations = "C:\Users\myuser", "D:\ORGANIZE" 5 | 6 | #where to put logs 7 | $logFolder = "C:\Users\myuser\Documents\backup_logs\" 8 | $logFileName = "duplicacy.log" 9 | $logPath = ($logFolder + $logFileName) 10 | # size to roll over at in megabytes 11 | $logMaxSize = 5mb 12 | # age after which to delete logs (in days) 13 | $logMaxAge = 30 14 | 15 | 16 | 17 | # function to roll over logs when they get too big 18 | # 19 | # pre-create the log file the first time you run the script since 20 | # this doesn't error check 21 | function Rollover-Logs 22 | { 23 | 24 | 25 | # roll over by size 26 | if ((Get-Item $logPath).Length -gt $logMaxSize) { 27 | 28 | 29 | $currentDate = (Get-Date -UFormat %Y%m%d%H%M%S%Z) 30 | Rename-Item $logPath ($logPath + "." + $currentDate) 31 | echo ("Rolled over logs at " + $currentDate >> $logPath) 32 | 33 | # delete when too old 34 | if ((Get-Item $logPath).LastWriteTime.AddDays(-$logMaxAge) -gt (Get-Date)) { 35 | 36 | 37 | } 38 | 39 | } 40 | } 41 | 42 | Rollover-Logs 43 | 44 | foreach ($location in $backupLocations) { 45 | 46 | 47 | 48 | cd $location 49 | echo ("running backups for " + $location + " at " + (Get-Date -UFormat %Y%m%d%T%Z)) *>> $logPath 50 | & $duplicacyBinary prune -keep 0:360 -keep 30:180 -keep 7:30 -keep 1:7 *>> $logPath 51 | & $duplicacyBinary backup -stats -vss *>> $logPath 52 | & $duplicacyBinary prune --delete-only *>> $logPath 53 | & $duplicacyBinary prune -keep 0:360 -keep 30:180 -keep 7:30 -keep 1:7 -storage b2 *>> $logPath 54 | & $duplicacyBinary copy -to b2 -threads 10 *>> $logPath 55 | & $duplicacyBinary prune --delete-only -storage b2 *>> $logPath 56 | 57 | } 58 | 59 | 60 | 61 | 62 | # SIG # Begin signature block 63 | # MIIFVQYJKoZIhvcNAQcCoIIFRjCCBUICAQExCzAJBgUrDgMCGgUAMGkGCisGAQQB 64 | # gjcCAQSgWzBZMDQGCisGAQQBgjcCAR4wJgIDAQAABBAfzDtgWUsITrck0sYpfvNR 65 | # AgEAAgEAAgEAAgEAAgEAMCEwCQYFKw4DAhoFAAQUNRmWjSxSvU73XjYIDFMHOFOT 66 | # urSgggL4MIIC9DCCAdygAwIBAgIQHB1E92Tt3J5EmITDvfuxkDANBgkqhkiG9w0B 67 | # AQsFADASMRAwDgYDVQQDDAdCYWNrdXBzMB4XDTE3MTAzMTA1MTExMVoXDTE4MTAz 68 | # MTA1MzExMVowEjEQMA4GA1UEAwwHQmFja3VwczCCASIwDQYJKoZIhvcNAQEBBQAD 69 | # ggEPADCCAQoCggEBAKLuwlouwvEDniEdA6PeoXy+qQIDLvguNzrGTb9ue91gaso8 70 | # hwbcn/GKjBz848BRoEf3GXTb7AORiWaxrROHaDIFThy/0e37ay56qi3Stco+c4pv 71 | # ekPiHiBbwOPVwPZx0nB2sAw1/YG/a8jap7ZA3oWtvzkpw6YQa/VJxTIuxx2hVBsl 72 | # YYGsukuRQfu0wd1KCBmwECdH2SMg+Cjv/hmnnxRHBJH4Z/rzXdv38ARcsUgVbzqr 73 | # 13hPLWIzWKxDwfk/Ch6uhi/+Hsy0Hxv1A1xNdKgsfoLCV9+WzTq1KZZPAifMqeg9 74 | # SbrahmfwMOCKsFNqCK6FsikahsSL+NacQHWQLUkCAwEAAaNGMEQwDgYDVR0PAQH/ 75 | # BAQDAgeAMBMGA1UdJQQMMAoGCCsGAQUFBwMDMB0GA1UdDgQWBBTOBJL90YADmaqI 76 | # Jklz54YE5Yh9WjANBgkqhkiG9w0BAQsFAAOCAQEAj1qJPdpnZhzSVJEfMzq4y4LZ 77 | # G4XHELO98j8rGD260GaZG1IoSt0Q1c5vPKSdhXxefFwq9cGTUYTqefCUb+1oC4AR 78 | # x60p/1qK7r1ScKPCL5/dCCCYaH7fqIXfK32eNr/5e2TS30+G7fQGdf2BbYdp89wx 79 | # Ln0JAn9aDZZWcv9fx6q48hSmpXNH1E4hU4h5Sd6Ob1xzrP9GZ1irv4GwtoG4nEku 80 | # DDTV+mq0GQV9Zv44Zp6KMfibgKT4ihP5fYyMHni/4E/qCs3FQxvf0HvWHQCHBSEg 81 | # Iw1gWa5UHcKQ41S+O82WWo9y9OUPvp16VuX2dpX9f1Kk0aQsvB2OfMK8e+5ntjGC 82 | # AccwggHDAgEBMCYwEjEQMA4GA1UEAwwHQmFja3VwcwIQHB1E92Tt3J5EmITDvfux 83 | # kDAJBgUrDgMCGgUAoHgwGAYKKwYBBAGCNwIBDDEKMAigAoAAoQKAADAZBgkqhkiG 84 | # 9w0BCQMxDAYKKwYBBAGCNwIBBDAcBgorBgEEAYI3AgELMQ4wDAYKKwYBBAGCNwIB 85 | # FTAjBgkqhkiG9w0BCQQxFgQUy0NAbSkQjUV7NNXnp+q1XJ0q7PkwDQYJKoZIhvcN 86 | # AQEBBQAEggEAITM3Jvx6qlYE/smdNfiqxntScnK3WEhUDz4PAn5wXzbyPsghgDJ+ 87 | # 89gmUfPGJzeN8xZek3J8kDf+zm8qjmZ75Go6+pXECl+vrgUEqrvaNv3esBjj0OmI 88 | # mHiar/L3KSvIMZCSBm4EtgqAHSHRFN0FE7857NVDCB+8DTH3q67VQNdUdQmsK2EO 89 | # ZZm+WRAUHNvDBSw827qkxxqyXGcktvqbksM05/U46RRXWzF8hI89mnnD49yRPMAT 90 | # izQ4w8CnBPUqDYtfkZWHSZZ0mSWnyInx8Q02TjU9bpsSrFD9wGDoj+DPFutrHLVo 91 | # U1xg23i1hBCaik70mrNkC9aBEhJ7J66aVA== 92 | # SIG # End signature block 93 | --------------------------------------------------------------------------------