syc-backup 0.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (71) hide show
  1. data/README.rdoc +48 -0
  2. data/Rakefile +7 -0
  3. data/bin/sycbackup +6 -0
  4. data/doc/Backup.html +186 -0
  5. data/doc/Backup/CronEdit.html +381 -0
  6. data/doc/Backup/Environment.html +231 -0
  7. data/doc/Backup/FileBackup.html +363 -0
  8. data/doc/Backup/MySQLBackup.html +305 -0
  9. data/doc/Backup/Options.html +328 -0
  10. data/doc/Backup/Process.html +261 -0
  11. data/doc/Backup/Runner.html +244 -0
  12. data/doc/README_rdoc.html +202 -0
  13. data/doc/Rakefile.html +118 -0
  14. data/doc/TestCronEdit.html +211 -0
  15. data/doc/TestEnvironment.html +156 -0
  16. data/doc/TestFileBackup.html +237 -0
  17. data/doc/TestMySQLBackup.html +167 -0
  18. data/doc/TestOptions.html +156 -0
  19. data/doc/TestProcess.html +236 -0
  20. data/doc/created.rid +18 -0
  21. data/doc/images/add.png +0 -0
  22. data/doc/images/brick.png +0 -0
  23. data/doc/images/brick_link.png +0 -0
  24. data/doc/images/bug.png +0 -0
  25. data/doc/images/bullet_black.png +0 -0
  26. data/doc/images/bullet_toggle_minus.png +0 -0
  27. data/doc/images/bullet_toggle_plus.png +0 -0
  28. data/doc/images/date.png +0 -0
  29. data/doc/images/delete.png +0 -0
  30. data/doc/images/find.png +0 -0
  31. data/doc/images/loadingAnimation.gif +0 -0
  32. data/doc/images/macFFBgHack.png +0 -0
  33. data/doc/images/package.png +0 -0
  34. data/doc/images/page_green.png +0 -0
  35. data/doc/images/page_white_text.png +0 -0
  36. data/doc/images/page_white_width.png +0 -0
  37. data/doc/images/plugin.png +0 -0
  38. data/doc/images/ruby.png +0 -0
  39. data/doc/images/tag_blue.png +0 -0
  40. data/doc/images/tag_green.png +0 -0
  41. data/doc/images/transparent.png +0 -0
  42. data/doc/images/wrench.png +0 -0
  43. data/doc/images/wrench_orange.png +0 -0
  44. data/doc/images/zoom.png +0 -0
  45. data/doc/index.html +106 -0
  46. data/doc/js/darkfish.js +153 -0
  47. data/doc/js/jquery.js +18 -0
  48. data/doc/js/navigation.js +142 -0
  49. data/doc/js/search.js +94 -0
  50. data/doc/js/search_index.js +1 -0
  51. data/doc/js/searcher.js +228 -0
  52. data/doc/rdoc.css +543 -0
  53. data/doc/table_of_contents.html +148 -0
  54. data/lib/backup/cron_edit.rb +127 -0
  55. data/lib/backup/environment.rb +44 -0
  56. data/lib/backup/file_backup.rb +94 -0
  57. data/lib/backup/mysql_backup.rb +58 -0
  58. data/lib/backup/options.rb +199 -0
  59. data/lib/backup/process.rb +99 -0
  60. data/lib/backup/runner.rb +79 -0
  61. data/lib/backup_version.rb +9 -0
  62. data/syc-backup-0.0.1.gem +0 -0
  63. data/syc-backup-0.0.3.gem +0 -0
  64. data/sycbackup.gemspec +20 -0
  65. data/test/test_cron_edit.rb +49 -0
  66. data/test/test_environment.rb +22 -0
  67. data/test/test_file_backup.rb +70 -0
  68. data/test/test_mysql_backup.rb +71 -0
  69. data/test/test_options.rb +189 -0
  70. data/test/test_process.rb +40 -0
  71. metadata +123 -0
@@ -0,0 +1,148 @@
1
+ <!DOCTYPE html>
2
+
3
+ <html>
4
+ <head>
5
+ <meta content="text/html; charset=UTF-8" http-equiv="Content-Type">
6
+
7
+ <title>Table of Contents - RDoc Documentation</title>
8
+
9
+ <link type="text/css" media="screen" href="./rdoc.css" rel="stylesheet">
10
+
11
+ <script type="text/javascript">
12
+ var rdoc_rel_prefix = "./";
13
+ </script>
14
+
15
+ <script type="text/javascript" charset="utf-8" src="./js/jquery.js"></script>
16
+ <script type="text/javascript" charset="utf-8" src="./js/navigation.js"></script>
17
+ <script type="text/javascript" charset="utf-8" src="./js/search_index.js"></script>
18
+ <script type="text/javascript" charset="utf-8" src="./js/search.js"></script>
19
+ <script type="text/javascript" charset="utf-8" src="./js/searcher.js"></script>
20
+ <script type="text/javascript" charset="utf-8" src="./js/darkfish.js"></script>
21
+
22
+
23
+ <body class="indexpage">
24
+ <h1>Table of Contents - RDoc Documentation</h1>
25
+
26
+ <h2>Pages</h2>
27
+ <ul>
28
+ <li class="file">
29
+ <a href="README_rdoc.html">README</a>
30
+
31
+ <img class="toc-toggle" src="images/transparent.png" alt="" title="toggle headings">
32
+ <ul class="initially-hidden">
33
+ <li><a href="README_rdoc.html#label-Backup+utility+for+database%2C+folders+and+files">Backup utility for database, folders and files</a>
34
+ <li><a href="README_rdoc.html#label-Install">Install</a>
35
+ <li><a href="README_rdoc.html#label-Usage">Usage</a>
36
+ <li><a href="README_rdoc.html#label-Supported+Platform">Supported Platform</a>
37
+ <li><a href="README_rdoc.html#label-Notes">Notes</a>
38
+ <li><a href="README_rdoc.html#label-Tests">Tests</a>
39
+ <li><a href="README_rdoc.html#label-Links">Links</a>
40
+ </ul>
41
+ </li>
42
+ <li class="file">
43
+ <a href="Rakefile.html">Rakefile</a>
44
+ </li>
45
+
46
+ </ul>
47
+
48
+ <h2 id="classes">Classes/Modules</h2>
49
+ <ul>
50
+ <li class="module">
51
+ <a href="Backup.html">Backup</a>
52
+ </li>
53
+ <li class="class">
54
+ <a href="Backup/CronEdit.html">Backup::CronEdit</a>
55
+ </li>
56
+ <li class="class">
57
+ <a href="Backup/Environment.html">Backup::Environment</a>
58
+ </li>
59
+ <li class="class">
60
+ <a href="Backup/FileBackup.html">Backup::FileBackup</a>
61
+ </li>
62
+ <li class="class">
63
+ <a href="Backup/MySQLBackup.html">Backup::MySQLBackup</a>
64
+ </li>
65
+ <li class="class">
66
+ <a href="Backup/Options.html">Backup::Options</a>
67
+ </li>
68
+ <li class="class">
69
+ <a href="Backup/Process.html">Backup::Process</a>
70
+ </li>
71
+ <li class="class">
72
+ <a href="Backup/Runner.html">Backup::Runner</a>
73
+ </li>
74
+ <li class="class">
75
+ <a href="TestCronEdit.html">TestCronEdit</a>
76
+ </li>
77
+ <li class="class">
78
+ <a href="TestEnvironment.html">TestEnvironment</a>
79
+ </li>
80
+ <li class="class">
81
+ <a href="TestFileBackup.html">TestFileBackup</a>
82
+ </li>
83
+ <li class="class">
84
+ <a href="TestMySQLBackup.html">TestMySQLBackup</a>
85
+ </li>
86
+ <li class="class">
87
+ <a href="TestOptions.html">TestOptions</a>
88
+ </li>
89
+ <li class="class">
90
+ <a href="TestProcess.html">TestProcess</a>
91
+ </li>
92
+
93
+ </ul>
94
+
95
+ <h2 id="methods">Methods</h2>
96
+ <ul>
97
+
98
+ <li class="method"><a href="Backup/Process.html#method-c-new">::new &mdash; Backup::Process</a>
99
+
100
+ <li class="method"><a href="Backup/Runner.html#method-c-new">::new &mdash; Backup::Runner</a>
101
+
102
+ <li class="method"><a href="Backup/Options.html#method-c-new">::new &mdash; Backup::Options</a>
103
+
104
+ <li class="method"><a href="Backup/MySQLBackup.html#method-c-new">::new &mdash; Backup::MySQLBackup</a>
105
+
106
+ <li class="method"><a href="Backup/FileBackup.html#method-c-new">::new &mdash; Backup::FileBackup</a>
107
+
108
+ <li class="method"><a href="Backup/Environment.html#method-c-ruby">::ruby &mdash; Backup::Environment</a>
109
+
110
+ <li class="method"><a href="Backup/CronEdit.html#method-i-add_command">#add_command &mdash; Backup::CronEdit</a>
111
+
112
+ <li class="method"><a href="Backup/FileBackup.html#method-i-backup">#backup &mdash; Backup::FileBackup</a>
113
+
114
+ <li class="method"><a href="Backup/MySQLBackup.html#method-i-backup">#backup &mdash; Backup::MySQLBackup</a>
115
+
116
+ <li class="method"><a href="Backup/Process.html#method-i-backup">#backup &mdash; Backup::Process</a>
117
+
118
+ <li class="method"><a href="Backup/FileBackup.html#method-i-check_for_inexistent">#check_for_inexistent &mdash; Backup::FileBackup</a>
119
+
120
+ <li class="method"><a href="Backup/CronEdit.html#method-i-cleanup">#cleanup &mdash; Backup::CronEdit</a>
121
+
122
+ <li class="method"><a href="Backup/MySQLBackup.html#method-i-compress">#compress &mdash; Backup::MySQLBackup</a>
123
+
124
+ <li class="method"><a href="Backup/FileBackup.html#method-i-compress">#compress &mdash; Backup::FileBackup</a>
125
+
126
+ <li class="method"><a href="TestCronEdit.html#method-i-crontab_count">#crontab_count &mdash; TestCronEdit</a>
127
+
128
+ <li class="method"><a href="Backup/CronEdit.html#method-i-remove_command">#remove_command &mdash; Backup::CronEdit</a>
129
+
130
+ <li class="method"><a href="Backup/Runner.html#method-i-run">#run &mdash; Backup::Runner</a>
131
+
132
+ <li class="method"><a href="TestProcess.html#method-i-setup">#setup &mdash; TestProcess</a>
133
+
134
+ <li class="method"><a href="TestFileBackup.html#method-i-setup">#setup &mdash; TestFileBackup</a>
135
+
136
+ <li class="method"><a href="TestProcess.html#method-i-teardown">#teardown &mdash; TestProcess</a>
137
+
138
+ <li class="method"><a href="TestFileBackup.html#method-i-teardown">#teardown &mdash; TestFileBackup</a>
139
+
140
+ </ul>
141
+
142
+
143
+ <footer id="validator-badges">
144
+ <p><a href="http://validator.w3.org/check/referer">[Validate]</a>
145
+ <p>Generated by <a href="https://github.com/rdoc/rdoc">RDoc</a> 3.12.
146
+ <p>Generated with the <a href="http://deveiate.org/projects/Darkfish-Rdoc/">Darkfish Rdoc Generator</a> 3.
147
+ </footer>
148
+
@@ -0,0 +1,127 @@
1
+ require 'open3'
2
+
3
+ module Backup
4
+
5
+ # Adds or removes a command to the user's crontab. To make sure that the
6
+ # Ruby application is invoked as a cron job it needs the environment
7
+ # variables that are available when run from command line. To meet these
8
+ # requirements the environment variables are read and added to the crontab. If
9
+ # variables already exist in the crontab they are overridden.
10
+ class CronEdit
11
+
12
+ # Temporary file that holds the entries to be written to the crontab
13
+ CRON_ENTRIES_FILE = ".cron_entries"
14
+
15
+ # Adds a command to the user's crontab. If the provided command is empty
16
+ # add_command will exit the application with exit status -1.
17
+ # The method uses the <tt>crontab -l</tt> and <tt>crontab file</tt> command.
18
+ # If the crontab call fails the error message and exit status of
19
+ # <tt>crontab</tt> will be returned and the application exits
20
+ def add_command(command, environment=[])
21
+ command = command.strip.squeeze(" ")
22
+
23
+ if command.empty?
24
+ STDERR.puts "Cannot add empty command to cron"
25
+ exit -1
26
+ end
27
+
28
+ read_crontab_command = 'crontab -l'
29
+
30
+ stdout, stderr, status = Open3.capture3(read_crontab_command)
31
+
32
+ entries = [] + environment
33
+
34
+ stdout.split(/\n/).each do |entry|
35
+ entry = entry.strip.squeeze(" ")
36
+ variable = entry.match(/\A\w+(?=\=)/).to_s
37
+ unless variable.empty?
38
+ entries << entry unless environment.grep(/\A#{variable}/)
39
+ else
40
+ entries << entry
41
+ end
42
+ end
43
+
44
+ unless entries.include? command
45
+ entries << command
46
+
47
+ cron_entries_file = CRON_ENTRIES_FILE
48
+ File.open(cron_entries_file, 'w') do |f|
49
+ entries.each {|entry| f.puts entry}
50
+ end
51
+
52
+ write_crontab_command = "crontab #{cron_entries_file}"
53
+
54
+ stdout, stderr, status = Open3.capture3(write_crontab_command)
55
+
56
+ cleanup
57
+
58
+ unless status.exitstatus == 0
59
+ STDERR.puts "There is a problem executing command"
60
+ STDERR.puts write_crontab_command
61
+ STDERR.puts stderr
62
+ exit status.exitstatus
63
+ end
64
+ end
65
+
66
+ command
67
+
68
+ end
69
+
70
+ # Removes a command from the user's crontab. If the provided command is
71
+ # empty remove_command will exit the application with exit status -1.
72
+ # The method uses the <tt>crontab -l</tt> and <tt>crontab file</tt> command.
73
+ # If the crontab call fails the error message and exit status of
74
+ # <tt>crontab</tt> will be returned and the application exits
75
+ def remove_command(command)
76
+ command = command.strip.squeeze(" ")
77
+
78
+ if command.empty?
79
+ STDERR.puts "Cannot delete empty command from crontab"
80
+ exit -1
81
+ end
82
+
83
+ read_crontab_command = "crontab -l"
84
+
85
+ stdout, stderr, status = Open3.capture3(read_crontab_command)
86
+
87
+ unless status.exitstatus == 0
88
+ STDERR.puts "There is a problem executing command"
89
+ STDERR.puts read_crontab_command
90
+ STDERR.puts stderr
91
+ exit status.existatus
92
+ end
93
+
94
+ entries = stdout.split(/\n/).each {|entry| entry.strip.squeeze(" ")}
95
+
96
+ entries.delete(command)
97
+
98
+ cron_entries_file = CRON_ENTRIES_FILE #".cron_entries"
99
+
100
+ File.open(cron_entries_file, 'w') do |file|
101
+ entries.each {|entry| file.puts entry}
102
+ end
103
+
104
+ write_crontab_command = "crontab #{cron_entries_file}"
105
+
106
+ stdout, stderr, status = Open3.capture3(write_crontab_command)
107
+
108
+ cleanup
109
+
110
+ unless status.exitstatus == 0
111
+ STDERR.puts "There is a problem executing command"
112
+ STDERR.puts write_crontab_command
113
+ STDERR.puts stderr
114
+ exit status.exitstatus
115
+ end
116
+
117
+ command
118
+
119
+ end
120
+
121
+ # Removes the CRON_ENTRIES_FILE after the values have been written to
122
+ # crontab
123
+ def cleanup
124
+ File.delete CRON_ENTRIES_FILE if File.exists? CRON_ENTRIES_FILE
125
+ end
126
+ end
127
+ end
@@ -0,0 +1,44 @@
1
+ module Backup
2
+
3
+ # Reads and filters the user's environment variables to meet Ruby and Gem
4
+ # requirements to run the application as a cron job
5
+ class Environment
6
+
7
+ # Contains the environment variable names that are required to run a Ruby
8
+ # application from as a cron job
9
+ VARIABLES = ["RVM_BIN_PATH",
10
+ "GEM_HOME",
11
+ "SHELL",
12
+ "MY_RUBY_HOME",
13
+ "USER",
14
+ "RVM_PATH",
15
+ "RVM_PREFIX",
16
+ "PATH",
17
+ "RVM_VERSION",
18
+ "HOME",
19
+ "LOGNAME",
20
+ "GEM_PATH",
21
+ "RUBY_VERSION"]
22
+
23
+ # Retrieves the environment variables that are required running a Ruby
24
+ # application as a cron job. The variable are returned in an Array
25
+ def self.ruby
26
+ file = ".current_environment.tmp"
27
+ system ("env > #{file}")
28
+
29
+ lines = []
30
+
31
+ File.open(file, 'r') do |f|
32
+ while line = f.gets
33
+ variable = line.chomp.match(/\A\w+(?=\=)/).to_s
34
+ lines << line.chomp if VARIABLES.find_index variable.upcase
35
+ end
36
+ end
37
+
38
+ File.delete file
39
+
40
+ lines
41
+ end
42
+
43
+ end
44
+ end
@@ -0,0 +1,94 @@
1
+ require 'fileutils'
2
+ require 'open3'
3
+
4
+ # Backup contains functions to backup a MySQL database and files and directories
5
+ # to a default or specified backup directory. Instead of instant backup the
6
+ # invoked command can be added to a crontab and invoked based on the provided
7
+ # schedule that is a parameter of the --cron option. The backed up files are
8
+ # per default compressed but this can be ommitted
9
+ module Backup
10
+
11
+ # Backup directories and files to a backup directory
12
+ class FileBackup
13
+
14
+ # Initializes the files to be backed up. If no file is provided an error
15
+ # is returned
16
+ def initialize(files=[])
17
+ @files = files
18
+ end
19
+
20
+ # Compress the files to the backup directory
21
+ def compress(files, backup_folder)
22
+ inexistent_files = check_for_inexistent files
23
+ unless inexistent_files.empty?
24
+ STDERR.puts "Cannot compress inexistent files"
25
+ STDERR.puts "Following #{inexistent_files.size} file(s) do not exist"
26
+ STDERR.puts inexistent_files.join(" ")
27
+ exit 2
28
+ end
29
+
30
+ timestamp = Time.now.strftime("%Y%m%d-%H%M%S")
31
+ backup_folder += '/' unless backup_folder.match(/.*\/\Z/)
32
+ compress_file = backup_folder + timestamp + "_" + "files.tar.gz"
33
+
34
+ tar_command = "tar cfz #{compress_file} " + files.join(" ")
35
+
36
+ stdout_str, stderr_str, status = Open3.capture3(tar_command)
37
+
38
+ unless status.exitstatus == 0
39
+ STDERR.puts "There was a problem running tar command"
40
+ STDERR.puts "--> #{tar_command}"
41
+ STDERR.puts stderr_str
42
+ exit(2)
43
+ end
44
+
45
+ status.exitstatus
46
+
47
+ end
48
+
49
+ # The files to be backed up are initilized when creating an instance of
50
+ # FileBackup. These files are then backed up to the backup directory
51
+ def backup(backup_folder)
52
+
53
+ inexistent_files = []
54
+
55
+ @files.each do |file|
56
+ inexistent_files << file unless File.exists? file
57
+ end
58
+
59
+ unless inexistent_files.empty?
60
+ STDERR.puts "Cannot backup inexistent files"
61
+ STDERR.puts "Following #{inexistent_files.size} file(s) do not exist"
62
+ STDERR.puts "#{inexistent_files.join(', ')}"
63
+ exit 1
64
+ end
65
+
66
+ backup_folder += '/' unless backup_folder.match(/.*\/\Z/)
67
+
68
+ Dir.mkdir backup_folder unless File.exists? backup_folder
69
+
70
+ backup_files = []
71
+
72
+ @files.each.with_index do |file, index|
73
+ backup_files << backup_file = backup_folder+File.basename(file)
74
+ FileUtils.cp file, backup_file
75
+ end
76
+
77
+ backup_files
78
+
79
+ end
80
+
81
+ # Checks if the files all exist. Files that do not exist are returned in
82
+ # an Array
83
+ def check_for_inexistent (files)
84
+ inexistent_files = []
85
+ files.each do |f|
86
+ inexistent_files << f unless File.exists? f
87
+ end
88
+
89
+ inexistent_files
90
+ end
91
+
92
+ end
93
+
94
+ end
@@ -0,0 +1,58 @@
1
+ require 'open3'
2
+
3
+ module Backup
4
+
5
+ # MySQLBackup creates a dump file of a MySQL database with _mysqldump_ and
6
+ # returns the dump file.
7
+ class MySQLBackup
8
+
9
+ # database is the database to be backed up with the user that has the
10
+ # credentials to access the database with the provided password
11
+ def initialize(database, user, password)
12
+ @database = database
13
+ @user = user
14
+ @password = password
15
+ end
16
+
17
+ # Compresses the MySQL dump file. If an error occurs when compressing the
18
+ # file an error message is printed and the application terminates
19
+ def compress(backup_file)
20
+ tar_file = backup_file + '.tar.gz'
21
+ tar_command = "tar cfz #{tar_file} #{backup_file}"
22
+ stdout_str, stderr_str, status = Open3.capture3(tar_command)
23
+ unless status.exitstatus == 0
24
+ File.delete tar_file if File.exists? tar_file
25
+ STDERR.puts "There was a problem compressing the backup file"
26
+ STDERR.puts "-->#{tar_command}"
27
+ STDERR.puts stderr_str
28
+ exit(2)
29
+ end
30
+
31
+ status.exitstatus
32
+
33
+ end
34
+
35
+ # Creates a MySQL dump file and returns the file
36
+ def backup(backup_folder="./")
37
+ Dir.mkdir backup_folder unless File.exists? backup_folder
38
+
39
+ timestamp = Time.now.strftime('%Y%m%d-%H%M%S')
40
+ backup_file = backup_folder + @database + '_' + timestamp + '.sql'
41
+ mysqldump = "mysqldump -u#{@user} -p#{@password} #{@database}"
42
+
43
+ backup_command = "#{mysqldump} > #{backup_file}"
44
+ stdout_str, stderr_str, status = Open3.capture3(backup_command)
45
+ unless status.exitstatus == 0
46
+ File.delete backup_file if File.exists? backup_file
47
+ STDERR.puts "There was a problem running mysqldump"
48
+ STDERR.puts "--> #{backup_command}"
49
+ STDERR.puts stderr_str
50
+ exit(1)
51
+ end
52
+
53
+ backup_file
54
+
55
+ end
56
+
57
+ end
58
+ end