Skip to content

Commit

Permalink
Fix incorrect snapshot count when incomplete backup can't be deleted
Browse files Browse the repository at this point in the history
Fix exiting prematurely with code 0 if script pre-hook file does not exist
  • Loading branch information
mattlyons0 committed Feb 22, 2018
1 parent 2939289 commit df05f82
Show file tree
Hide file tree
Showing 3 changed files with 35 additions and 17 deletions.
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,9 @@ See [Do It Yourself Backup System Using Rsync](http://www.sanitarium.net/golug/r
- It is recommended to schedule this command to run regularly in cron or alike
- When scheduling this script run it is best to update `rsync-snapshot` regularly
- Execute `npm update -g rsync-snapshot` to update to latest **minor** version
- Backups will be in a folder named by time and date (ex: `2018-02-21.19-06-26`)
- Anything may be appended (manually) to folder names to add user friendly info (ex: `2018-02-21.19-06-26.createdDatabase`) as long as `.incomplete` is not appended (which is reserved for backups in progress, failed or canceled)
- `ls -1 | sort -r` can be used to sort backups (most recent to least recent)

#### Parameters
*Note: To wrap strings double quotes must be used. Ex: `--shell "ssh -p 2222"` must be used to specify ssh parameters. Single quotes will not be parsed correctly.*
Expand Down
46 changes: 31 additions & 15 deletions lib/Incrementer.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ const debug = require('debug')('RsyncSnapshot:lib:Incrementer');
const spawn = require('child_process').spawn;
const execFile = require('child_process').execFile;
const path = require('path');
const fs = require('fs');

class Incrementer{
constructor(logger, shell, rsyncDest){
Expand Down Expand Up @@ -89,13 +90,15 @@ class Incrementer{
let bashCommand = `mkdir -p '${this.escapeQuotes(this.tempDest)}';`; //Make Temp Dir (even though it will be deleted parent dirs won't be)
bashCommand+= `cd '${this.escapeQuotes(this.remoteDirectory)}';`;
bashCommand+= `find . -maxdepth 1 -type d -name '*.incomplete' | xargs rm -rf;`; //Cleanup old incomplete backups
bashCommand+= `ls -1 | wc -l;`; //Count snapshots (for potential snapshot deletion after backup)
bashCommand+= `ls -1 | wc -l;`; //Folders (So we know when we got all info from ls)
bashCommand+= `ls -1 | sort -r;`; //Print Snapshots 1 on a line most recent to least recent

this.generator.logger.log('stdout')({msgType: 'progress', status: 'Deleting Incomplete Backups'});

let hasError = false;
let ssh = this.runCommand(bashCommand, (error) => {
let folderCount = 0;
let foldersFound = 0;
let ssh = this.runCommand(bashCommand, (error) => {
error = error.toString();
this.generator.logger.log('stderr')('An error occurred connecting to server while preparing for backup:');
this.generator.logger.log('stderr')(error);
Expand All @@ -105,15 +108,20 @@ class Incrementer{

for(let line of output){
if(!line) {
// Whatever
} else if(line.match(/^\d*\s*$/g)){ //Folder Count
try {
this.snapshotCount = Number(line.trim());
} catch(e){
this.generator.logger.log('stderr')(`Error determining number of snapshots, found: ${line}`);
}
continue;
} else if(line.match(/^\d*\s*$/g) && !folderCount){ //Folder Count
folderCount = Number(line.trim());
} else if(line.match(/^\d{4}(-\d{2}){2}.(-?\d{2}){3}(?!.incomplete$)/g)){ //If folder matches the naming format (and is not incomplete)
this.linkDest = path.join(this.remoteDirectory, line);
if(!this.linkDest)
this.linkDest = path.join(this.remoteDirectory, line);

foldersFound++;
this.snapshotCount++;
} else { //Folder but not snapshot folder
foldersFound++;
}

if(folderCount === foldersFound){
resolve(true);
return;
}
Expand Down Expand Up @@ -154,15 +162,23 @@ class Incrementer{
}

executeScriptHook(executablePath){
return new Promise((resolve, reject) => {
return new Promise(async (resolve, reject) => {
executablePath = path.resolve(executablePath);
let scriptName = path.basename(executablePath);

this.generator.logger.log('stdout')({msgType: 'progress', status: `${scriptName} Started`});

let proc;
try {
proc = execFile(executablePath);
await new Promise((resolve, reject) => { //Throw exception if can't execute file
fs.access(executablePath, fs.constants.X_OK, (err) => {
if(err)
reject(err);
else
resolve();
});
});

this.generator.logger.log('stdout')({msgType: 'progress', status: `${scriptName} Started`});

let proc = execFile(executablePath);

proc.stdout.on('data', (data) => {
let str = data.toString();
Expand Down
3 changes: 1 addition & 2 deletions lib/LogGenerator.js
Original file line number Diff line number Diff line change
Expand Up @@ -65,8 +65,7 @@ class LogGenerator {

async setOutputFile(file, level) { //Will reject if file is not writable
if (file) {
if (!path.isAbsolute(file)) //Convert relative path to absolute
file = path.resolve(file);
file = path.resolve(file);

//Will throw exception if can't write
await new Promise((resolve, reject) => {
Expand Down

0 comments on commit df05f82

Please sign in to comment.