tens3 0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/README +46 -0
- data/bin/tens3_get +60 -0
- data/bin/tens3_put +104 -0
- metadata +77 -0
data/README
ADDED
@@ -0,0 +1,46 @@
|
|
1
|
+
tens3 : dead simple s3 backups
|
2
|
+
|
3
|
+
* uses s3 to backup a directory of files
|
4
|
+
* uses fadvise to be easy on filesystem caches and disks
|
5
|
+
* purges files after X days
|
6
|
+
* streams files rather than loading them entirely into memory
|
7
|
+
|
8
|
+
|
9
|
+
license:
|
10
|
+
|
11
|
+
This code is available as Open Source Software under the MIT license.
|
12
|
+
|
13
|
+
|
14
|
+
ruby dependencies:
|
15
|
+
|
16
|
+
fadvise
|
17
|
+
right_aws
|
18
|
+
|
19
|
+
|
20
|
+
configuration:
|
21
|
+
|
22
|
+
tens3.yml:
|
23
|
+
|
24
|
+
amazon_access_key_id: "someid"
|
25
|
+
amazon_secret_access_key: "somekey"
|
26
|
+
backup_dir: "/some/path/"
|
27
|
+
purge_threshold: 3
|
28
|
+
bucket_name: "somebucket"
|
29
|
+
|
30
|
+
|
31
|
+
usage:
|
32
|
+
|
33
|
+
backup a directory of files:
|
34
|
+
|
35
|
+
$ ./tens3_put tens3.conf
|
36
|
+
|
37
|
+
restore a file from a backup:
|
38
|
+
|
39
|
+
$ ./tens3_get tens3.conf date somefile ./somefile
|
40
|
+
|
41
|
+
The date is the date that the file was backed up in a YYYYMMDD format.
|
42
|
+
|
43
|
+
|
44
|
+
caveats:
|
45
|
+
|
46
|
+
The script will only backup files at one directory level, it does not recurse into subdirectories.
|
data/bin/tens3_get
ADDED
@@ -0,0 +1,60 @@
|
|
1
|
+
#! /usr/bin/ruby
|
2
|
+
|
3
|
+
## Copyright 2009, Joe Williams <joe@joetify.com>
|
4
|
+
##
|
5
|
+
## Permission is hereby granted, free of charge, to any person
|
6
|
+
## obtaining a copy of this software and associated documentation
|
7
|
+
## files (the "Software"), to deal in the Software without
|
8
|
+
## restriction, including without limitation the rights to use,
|
9
|
+
## copy, modify, merge, publish, distribute, sublicense, and/or sell
|
10
|
+
## copies of the Software, and to permit persons to whom the
|
11
|
+
## Software is furnished to do so, subject to the following
|
12
|
+
## conditions:
|
13
|
+
##
|
14
|
+
## The above copyright notice and this permission notice shall be
|
15
|
+
## included in all copies or substantial portions of the Software.
|
16
|
+
##
|
17
|
+
## THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
18
|
+
## EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
19
|
+
## OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
20
|
+
## NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
21
|
+
## HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
22
|
+
## WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
23
|
+
## FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
24
|
+
## OTHER DEALINGS IN THE SOFTWARE.
|
25
|
+
|
26
|
+
|
27
|
+
require 'rubygems'
|
28
|
+
require 'right_aws'
|
29
|
+
require 'socket'
|
30
|
+
require 'fadvise'
|
31
|
+
|
32
|
+
tens3_config = YAML.load(File.open(ARGV[0]))
|
33
|
+
|
34
|
+
AWS_KEY = tens3_config['amazon_access_key_id']
|
35
|
+
AWS_SECRET = tens3_config['amazon_secret_access_key']
|
36
|
+
BUCKET_NAME = tens3_config['bucket_name']
|
37
|
+
|
38
|
+
S3 = RightAws::S3Interface.new(AWS_KEY, AWS_SECRET)
|
39
|
+
def main
|
40
|
+
if ARGV.length != 4
|
41
|
+
puts "tens3_get usage:\n# tens3_get CONFIG BACKUPDATE REMOTEFILENAME LOCALFILEWITHPATH"
|
42
|
+
else
|
43
|
+
s3 = RightAws::S3Interface.new(AWS_KEY, AWS_SECRET)
|
44
|
+
remote_file_name = "#{ARGV[1]}_#{ARGV[2]}"
|
45
|
+
local_file_name = "#{ARGV[3]}"
|
46
|
+
|
47
|
+
puts "[ #{Time.now} ] IFNO :: Creating local file at #{local_file_name}"
|
48
|
+
file = File.open(local_file_name, File::CREAT|File::RDWR)
|
49
|
+
file.fadvise(0, 0, :dont_need)
|
50
|
+
|
51
|
+
puts "[ #{Time.now} ] INFO :: Streaming #{remote_file_name} from S3 to #{local_file_name}"
|
52
|
+
rhdr = s3.get(BUCKET_NAME, remote_file_name) do |chunk|
|
53
|
+
file.write(chunk)
|
54
|
+
end
|
55
|
+
|
56
|
+
file.close
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
main
|
data/bin/tens3_put
ADDED
@@ -0,0 +1,104 @@
|
|
1
|
+
#! /usr/bin/ruby
|
2
|
+
|
3
|
+
## Copyright 2009, Joe Williams <joe@joetify.com>
|
4
|
+
##
|
5
|
+
## Permission is hereby granted, free of charge, to any person
|
6
|
+
## obtaining a copy of this software and associated documentation
|
7
|
+
## files (the "Software"), to deal in the Software without
|
8
|
+
## restriction, including without limitation the rights to use,
|
9
|
+
## copy, modify, merge, publish, distribute, sublicense, and/or sell
|
10
|
+
## copies of the Software, and to permit persons to whom the
|
11
|
+
## Software is furnished to do so, subject to the following
|
12
|
+
## conditions:
|
13
|
+
##
|
14
|
+
## The above copyright notice and this permission notice shall be
|
15
|
+
## included in all copies or substantial portions of the Software.
|
16
|
+
##
|
17
|
+
## THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
18
|
+
## EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
19
|
+
## OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
20
|
+
## NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
21
|
+
## HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
22
|
+
## WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
23
|
+
## FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
24
|
+
## OTHER DEALINGS IN THE SOFTWARE.
|
25
|
+
|
26
|
+
|
27
|
+
require 'rubygems'
|
28
|
+
require 'right_aws'
|
29
|
+
require 'socket'
|
30
|
+
require 'fadvise'
|
31
|
+
require 'time'
|
32
|
+
require 'ftools'
|
33
|
+
|
34
|
+
tens3_config = YAML.load(File.open(ARGV[0]))
|
35
|
+
|
36
|
+
BACKUP_DIR = tens3_config['backup_dir']
|
37
|
+
AWS_KEY = tens3_config['amazon_access_key_id']
|
38
|
+
AWS_SECRET = tens3_config['amazon_secret_access_key']
|
39
|
+
PURGE_THRESHOLD = tens3_config['purge_threshold']
|
40
|
+
BUCKET_NAME = tens3_config['bucket_name']
|
41
|
+
|
42
|
+
S3 = RightAws::S3Interface.new(AWS_KEY, AWS_SECRET)
|
43
|
+
|
44
|
+
def file_list
|
45
|
+
ls = Dir.entries(BACKUP_DIR)
|
46
|
+
ls.delete(".")
|
47
|
+
ls.delete("..")
|
48
|
+
ls
|
49
|
+
end
|
50
|
+
|
51
|
+
def backup
|
52
|
+
puts "[ #{Time.now} ] INFO :: Creating bucket #{BUCKET_NAME}"
|
53
|
+
S3.create_bucket(BUCKET_NAME)
|
54
|
+
|
55
|
+
file_list.each do |file|
|
56
|
+
puts "[ #{Time.now} ]"
|
57
|
+
full_path = "#{BACKUP_DIR}#{file}"
|
58
|
+
|
59
|
+
unless File.directory?(full_path)
|
60
|
+
backup_file = File.open(full_path, 'rb')
|
61
|
+
backup_file.fadvise(0, file.size, :sequential)
|
62
|
+
|
63
|
+
puts "[ #{Time.now} ] INFO :: Calculating SHA1 for #{full_path}"
|
64
|
+
sha1_output = `sha1sum #{full_path}`
|
65
|
+
sha1 = sha1_output.split[0]
|
66
|
+
|
67
|
+
puts "[ #{Time.now} ] INFO :: Backing up #{full_path} (#{File.size(full_path)} bytes) - #{sha1}"
|
68
|
+
S3.put(BUCKET_NAME, "#{Time.now.strftime("%Y%m%d")}_#{file}", backup_file)
|
69
|
+
|
70
|
+
puts "[ #{Time.now} ] INFO :: #{Time.now.strftime("%Y%m%d")}_#{file} has been uploaded to bucket #{BUCKET_NAME}"
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
def purge
|
76
|
+
today = Time.now
|
77
|
+
seconds_in_day = 86400
|
78
|
+
bucket_list = S3.list_bucket(BUCKET_NAME)
|
79
|
+
purge_list = Hash.new
|
80
|
+
|
81
|
+
bucket_list.each do |file|
|
82
|
+
purge_list.store(file[:key], file[:last_modified])
|
83
|
+
end
|
84
|
+
|
85
|
+
purge_list.each do |key, value|
|
86
|
+
time_diff = (today - Time.parse(value))/seconds_in_day
|
87
|
+
if time_diff > PURGE_THRESHOLD
|
88
|
+
puts "[ #{Time.now} ] INFO :: #{key} is #{time_diff} days old (>#{PURGE_THRESHOLD}), purging from s3"
|
89
|
+
S3.delete(BUCKET_NAME, key)
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
end
|
94
|
+
|
95
|
+
def main
|
96
|
+
if ARGV.length != 1
|
97
|
+
puts "tens3_put usage:\n# tens3_put CONFIG"
|
98
|
+
else
|
99
|
+
backup
|
100
|
+
purge
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
main
|
metadata
ADDED
@@ -0,0 +1,77 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: tens3
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: "0.1"
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- joe williams
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2009-11-03 00:00:00 -08:00
|
13
|
+
default_executable:
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: fadvise
|
17
|
+
type: :runtime
|
18
|
+
version_requirement:
|
19
|
+
version_requirements: !ruby/object:Gem::Requirement
|
20
|
+
requirements:
|
21
|
+
- - ">="
|
22
|
+
- !ruby/object:Gem::Version
|
23
|
+
version: "0"
|
24
|
+
version:
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: right_aws
|
27
|
+
type: :runtime
|
28
|
+
version_requirement:
|
29
|
+
version_requirements: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: "0"
|
34
|
+
version:
|
35
|
+
description:
|
36
|
+
email: joe@joetify.com
|
37
|
+
executables:
|
38
|
+
- tens3_put
|
39
|
+
- tens3_get
|
40
|
+
extensions: []
|
41
|
+
|
42
|
+
extra_rdoc_files:
|
43
|
+
- README
|
44
|
+
files:
|
45
|
+
- bin/tens3_get
|
46
|
+
- bin/tens3_put
|
47
|
+
- README
|
48
|
+
has_rdoc: true
|
49
|
+
homepage: http://github.com/joewilliams/tens3
|
50
|
+
licenses: []
|
51
|
+
|
52
|
+
post_install_message:
|
53
|
+
rdoc_options: []
|
54
|
+
|
55
|
+
require_paths:
|
56
|
+
- lib
|
57
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: "0"
|
62
|
+
version:
|
63
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
64
|
+
requirements:
|
65
|
+
- - ">="
|
66
|
+
- !ruby/object:Gem::Version
|
67
|
+
version: "0"
|
68
|
+
version:
|
69
|
+
requirements: []
|
70
|
+
|
71
|
+
rubyforge_project:
|
72
|
+
rubygems_version: 1.3.5
|
73
|
+
signing_key:
|
74
|
+
specification_version: 3
|
75
|
+
summary: easy backups to s3
|
76
|
+
test_files: []
|
77
|
+
|