backup_demon 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,15 @@
1
+ ---
2
+ !binary "U0hBMQ==":
3
+ metadata.gz: !binary |-
4
+ Y2M0Nzk4YzkwOGI1OWVkZmVjNzFlMmQ1NDMwOGY3YTJlMmFkZTE4OA==
5
+ data.tar.gz: !binary |-
6
+ ZDViNGE3NzcyN2MwMTE1MTcwZTgxYzU4MzFiZjA4NTVmODg5YmI1NA==
7
+ !binary "U0hBNTEy":
8
+ metadata.gz: !binary |-
9
+ Y2E0YTljNGFiYzMwZmU3MzNkYTU3OWQ1YmE5YWE2ZmM5MmVjMTYxZGUwMTlh
10
+ OWU3ZTIzOTBhNTBkYTk1Yzk2N2VmZjYzZDEwODU5NWU4ZGZjNThhZWE2ZDY1
11
+ ZDU1NDcxMDFhOGM4YmZiN2RkOGFlZDE2Njk5NDEzOTUyYmRhYWU=
12
+ data.tar.gz: !binary |-
13
+ ZGFlNTgzNzkzOGRlYjAxMjQ5NzAxMDdlZDdmMjRhYmMzMGQ4YWY1NjJiMmFi
14
+ YzdmNWFjODgxMjM5MjAwMWJiMTc2ZDRlYjdhMDk2ZjE2MGUwMjViNWNkZDdl
15
+ NWEyYzBhOGFlODU5ZGY2YzIxN2FiNTg2MGVkMjZmNWE2NTFkNWQ=
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source "https://rubygems.org"
2
+
3
+ gemspec
data/Gemfile.lock ADDED
@@ -0,0 +1,16 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ backup_demon (0.0.1)
5
+ thor (~> 0.18)
6
+
7
+ GEM
8
+ remote: https://rubygems.org/
9
+ specs:
10
+ thor (0.18.1)
11
+
12
+ PLATFORMS
13
+ ruby
14
+
15
+ DEPENDENCIES
16
+ backup_demon!
@@ -0,0 +1,24 @@
1
+ $LOAD_PATH.unshift 'lib'
2
+ require 'backup_demon/version'
3
+
4
+ Gem::Specification.new do |s|
5
+ s.name = "backup_demon"
6
+ s.version = BackupDemon::Version
7
+ s.summary = "BackupDemon backs up to external drives"
8
+ s.homepage = "https://github.com/ryanfaerman"
9
+ s.email = ["ry@nwitty.com"]
10
+ s.authors = ["Ryan Faerman"]
11
+
12
+ s.files = `git ls-files`.split($/).reject{ |f| f =~ /^examples/ }
13
+ s.executables = s.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
14
+ # s.test_files = s.files.grep(%r{^(test|spec|features)/})
15
+ s.require_paths = ["lib"]
16
+
17
+ # s.extra_rdoc_files = [ "LICENSE.txt", "CHANGELOG.md", "README.md", "CONTRIBUTING.md" ]
18
+ # s.rdoc_options = ["--charset=UTF-8"]
19
+
20
+ s.add_dependency "thor", "~> 0.18"
21
+
22
+ s.description = %s{
23
+ BackupDemon is a daemon for backing up directories to an external drive}
24
+ end
data/bin/backup_demon ADDED
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env ruby
2
+ $LOAD_PATH.unshift 'lib'
3
+ require 'backup_demon/cli'
4
+
5
+ BackupDemon::CLI.start(ARGV)
@@ -0,0 +1,68 @@
1
+ require 'thor'
2
+ require 'backup_demon'
3
+ require 'yaml'
4
+
5
+ module BackupDemon
6
+ class CLI < Thor
7
+
8
+ class_option :config, :aliases => ["-c"], :type => :string
9
+
10
+ desc "start", "run the BackupDemon Daemon"
11
+ option :daemon, aliases: ["-d"], type: :boolean, default: false
12
+ option :interval, aliases: ["-i"], type: :numeric
13
+ option :pid, aliases: ["-p"], type: :string
14
+ option :device, aliases: ["-s"], type: :string
15
+ option :mount, aliases: ["-m"], type: :string
16
+ option :directories, type: :string
17
+
18
+ def start(directories = nil)
19
+ load_config
20
+
21
+ directories = directories.to_s.split(',').map(&:strip) unless directories.nil?
22
+
23
+ daemon = BackupDemon::Daemon.new(
24
+ directories || BackupDemon.config.directories,
25
+ BackupDemon.config.device,
26
+ BackupDemon.config.mount
27
+ )
28
+
29
+ if BackupDemon.config.daemon
30
+ Process.daemon(true)
31
+ end
32
+
33
+ if BackupDemon.config.pid
34
+ File.open(BackupDemon.config.pid, 'w') { |f| f << daemon.pid }
35
+ end
36
+
37
+ daemon.run!(BackupDemon.config.interval)
38
+ end
39
+
40
+ desc "stop", "stop the BackupDemon Daemon"
41
+ option :pid, aliases: ["-p"], type: :string
42
+ def stop(pid = nil)
43
+ load_config
44
+ pidfile = BackupDemon.config.pid
45
+
46
+ if pidfile && File.exists?(pidfile)
47
+ File.foreach(pidfile) do |pid|
48
+ begin
49
+ Process.kill("KILL", pid.to_i)
50
+ rescue
51
+ puts "Nothing to stop"
52
+ end
53
+ end
54
+ end
55
+ end
56
+
57
+ protected
58
+ def load_config
59
+ opts = {}
60
+ if options[:config]
61
+ opts = YAML.load_file(File.expand_path(options[:config]))
62
+ end
63
+
64
+ BackupDemon.config = opts.merge!(options)
65
+ end
66
+
67
+ end
68
+ end
@@ -0,0 +1,39 @@
1
+ require "ostruct"
2
+ require "backup_demon/core_ext/hash"
3
+
4
+ module BackupDemon
5
+ class Config
6
+ attr_accessor :options
7
+
8
+ def initialize(options = {})
9
+ @options = {
10
+ daemon: false,
11
+ interval: 5,
12
+ pid: nil,
13
+ device: "/dev/sdb1",
14
+ mount: "/mnt/backuphdd",
15
+ directories: ""
16
+ }.merge!(options.symbolize_keys!)
17
+ end
18
+
19
+ def timeout
20
+ @options[:timeout].to_f
21
+ end
22
+
23
+ def interval
24
+ @options[:interval].to_f
25
+ end
26
+
27
+ def directories
28
+ @options[:directories]
29
+ end
30
+
31
+ def method_missing(name)
32
+ name = name.to_sym
33
+ if @options.has_key?(name)
34
+ @options[name]
35
+ end
36
+ end
37
+
38
+ end
39
+ end
@@ -0,0 +1,12 @@
1
+ class Hash
2
+ def symbolize_keys
3
+ inject({}) do |options, (key, value)|
4
+ options[(key.to_sym rescue key) || key] = value
5
+ options
6
+ end
7
+ end
8
+
9
+ def symbolize_keys!
10
+ self.replace(self.symbolize_keys)
11
+ end
12
+ end
@@ -0,0 +1,42 @@
1
+ module BackupDemon
2
+ class Daemon
3
+ def initialize(directories, device_path, mount_point = "/mnt/backuphdd")
4
+ @directories = [directories].flatten
5
+ @drive = Device.new(device_path)
6
+ @mount_point = mount_point
7
+ end
8
+
9
+ def run(interval = 5.0)
10
+ interval = Float(interval)
11
+ procline 'waiting for drive...'
12
+
13
+ # puts "#{@drive.exists?} && #{@drive.different?} (#{@drive.exists? && @drive.different?})"
14
+ # puts "#{@drive.previous.inspect} != #{@drive.current.inspect} || #{@drive.current.nil?}"
15
+ if @drive.exists? && @drive.different?
16
+ procline 'Found Drive'
17
+ if @drive.mount(@mount_point)
18
+ @directories.each do |source|
19
+ procline "Backing up #{source}"
20
+ Sync.start(source, @drive.mount_point)
21
+ end
22
+ end
23
+ end
24
+
25
+ Kernel.sleep(interval)
26
+ end
27
+
28
+ def run!(interval = 5.0)
29
+ loop do
30
+ run(interval)
31
+ end
32
+ end
33
+
34
+ def procline(string)
35
+ $0 = "backup-demon: #{string}"
36
+ end
37
+
38
+ def pid
39
+ @pid ||= Process.pid
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,61 @@
1
+ require 'fileutils'
2
+
3
+ module BackupDemon
4
+ class Device
5
+ attr_reader :device, :mounted, :mount_point
6
+ def initialize(device)
7
+ @device = device
8
+ @mounted = false
9
+ @previous = nil
10
+ end
11
+
12
+ def exists?
13
+ File.exists?(@device)
14
+ end
15
+
16
+ def different?
17
+ begin
18
+ @previous != File.stat(@device)
19
+ rescue
20
+ false
21
+ end
22
+ end
23
+
24
+ def self.mounted
25
+ raw_mount_list = `mount`
26
+ mount_list = {}
27
+ raw_mount_list.split("\n").each do |line|
28
+ items = line.split(' ')
29
+ mount_list[items[0]] = items[2]
30
+ end
31
+ mount_list.select { |k, v| k =~ /^\/.*/} # only real devices
32
+ end
33
+
34
+ def mount(mount_point)
35
+ @mount_point = mount_point
36
+ FileUtils.mkdir_p(@mount_point) unless File.exists?(@mount_point)
37
+ puts "mount #{@device} #{@mount_point}"
38
+
39
+ if mounted?
40
+ @previous = File.stat(@device)
41
+ true
42
+ else
43
+ false
44
+ end
45
+ end
46
+
47
+ def mounted?
48
+ Device.mounted.keys.include?(@device)
49
+ true
50
+ end
51
+
52
+ def unmount
53
+ puts "umount #{@device}"
54
+ end
55
+
56
+ def unmounted?
57
+ !mounted?
58
+ true
59
+ end
60
+ end
61
+ end
@@ -0,0 +1,8 @@
1
+ module BackupDemon
2
+ class Sync
3
+ def self.start(source, destination)
4
+ puts "Syncing #{source} to #{destination}"
5
+ sleep 2
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,3 @@
1
+ module BackupDemon
2
+ Version = VERSION = '0.0.1'
3
+ end
@@ -0,0 +1,22 @@
1
+ require 'backup_demon/sync'
2
+ require 'backup_demon/device'
3
+ require 'backup_demon/daemon'
4
+ require 'backup_demon/config'
5
+
6
+ module BackupDemon
7
+
8
+ def self.config=(options = {})
9
+ @config = Config.new(options)
10
+ end
11
+
12
+ def self.config
13
+ @config ||= Config.new
14
+ end
15
+
16
+ def self.configure
17
+ yield config
18
+ end
19
+ end
20
+
21
+
22
+ # BackupDemon::Daemon.new(['tmp/banana', 'tmp/jones'], 'tmp/device', 'tmp/mount/point').run!
metadata ADDED
@@ -0,0 +1,71 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: backup_demon
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Ryan Faerman
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2013-03-31 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: thor
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ~>
18
+ - !ruby/object:Gem::Version
19
+ version: '0.18'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ~>
25
+ - !ruby/object:Gem::Version
26
+ version: '0.18'
27
+ description: ! "\n BackupDemon is a daemon for backing up directories to an external
28
+ drive"
29
+ email:
30
+ - ry@nwitty.com
31
+ executables:
32
+ - backup_demon
33
+ extensions: []
34
+ extra_rdoc_files: []
35
+ files:
36
+ - Gemfile
37
+ - Gemfile.lock
38
+ - backup_demon.gemspec
39
+ - bin/backup_demon
40
+ - lib/backup_demon.rb
41
+ - lib/backup_demon/cli.rb
42
+ - lib/backup_demon/config.rb
43
+ - lib/backup_demon/core_ext/hash.rb
44
+ - lib/backup_demon/daemon.rb
45
+ - lib/backup_demon/device.rb
46
+ - lib/backup_demon/sync.rb
47
+ - lib/backup_demon/version.rb
48
+ homepage: https://github.com/ryanfaerman
49
+ licenses: []
50
+ metadata: {}
51
+ post_install_message:
52
+ rdoc_options: []
53
+ require_paths:
54
+ - lib
55
+ required_ruby_version: !ruby/object:Gem::Requirement
56
+ requirements:
57
+ - - ! '>='
58
+ - !ruby/object:Gem::Version
59
+ version: '0'
60
+ required_rubygems_version: !ruby/object:Gem::Requirement
61
+ requirements:
62
+ - - ! '>='
63
+ - !ruby/object:Gem::Version
64
+ version: '0'
65
+ requirements: []
66
+ rubyforge_project:
67
+ rubygems_version: 2.0.3
68
+ signing_key:
69
+ specification_version: 4
70
+ summary: BackupDemon backs up to external drives
71
+ test_files: []