remotebackup 0.51.1 → 0.70.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,3 +1,10 @@
1
+ == 0.70.0
2
+ * build tool change to Jeweler
3
+ * change config file format xml to yaml
4
+ * accept debian system
5
+ * you can use utf-8 file name
6
+ * you can use key base authenticity
7
+
1
8
  == 0.50.1 2008-06-23
2
9
 
3
10
  * 1 major enhancement:
data/Gemfile ADDED
@@ -0,0 +1,13 @@
1
+ source "http://rubygems.org"
2
+ # Add dependencies required to use your gem here.
3
+ # Example:
4
+ # gem "activesupport", ">= 2.3.5"
5
+ gem "net-scp"
6
+ # Add dependencies to develop your gem here.
7
+ # Include everything needed to run rake, tests, features, etc.
8
+ group :development do
9
+ gem "rspec", "~> 2.3.0"
10
+ gem "bundler", "~> 1.0.0"
11
+ gem "jeweler", "~> 1.6.4"
12
+ gem "rcov", ">= 0"
13
+ end
data/LICENSE.txt ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2011 Takeshi Morita
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README ADDED
@@ -0,0 +1,88 @@
1
+ RemoteBackupとは?
2
+ 1.リモートホスト上にあるディレクトリをローカルにscpでコピーすることでバックアップする
3
+ 2.ファイルの更新日時を見て、更新されているファイルだけをコピー
4
+ 3.リストアする際は日付を指定して、指定された日付の状態をリストアすることができる。
5
+ 1.に関しては、対象のリモートホスト上にsshデーモンが動作してさえすれば、リモートホストはなにもインストールする必要がないという利点があります。
6
+ 2.に関しては、必要なファイルのみ取得するので、バックアップの時間の節約や、容量の節約ができます。
7
+ 3.に関しては、リモートサーバのバックアップはrsyncが一般的だと思いますが、過去のデータを取り出すような機能はないため、間違ってサーバのファイルをいじった後に同期が取られた場合は元に戻せません。その点RemoteBackupは過去をさかのぼって、指定された日付のファイルツリーを復元することができます。
8
+ cronにRemoteBackupを登録することで、定期的なバックアップが容易にできます。
9
+
10
+ インストール手順
11
+ shellで下記のコマンドを実行
12
+  sudo gem install remotebackup
13
+
14
+ バックアップ手順
15
+ 1. 下記のフォーマットでバックアップを行うための設定ファイルを作成します。
16
+ バックアップ名(適当な英数字):
17
+ server: ホスト名
18
+ user: ホストにログインできるユーザ名
19
+ password: ユーザのパスワード
20
+ key: 秘密鍵のパス
21
+ passphrase: 秘密鍵のパスフレーズ
22
+ path: バックアップしたいディレクトリのフルパス</path>
23
+ ignore_list:
24
+ - 無視したいディレクトリおよびファイルの正規表現
25
+ :
26
+ :
27
+
28
+ 例)サーバ192.168.0.10のホストにtakesyというユーザ(パスワードが openthesesami)で/www配下を.svnや.bkというディレクトリもしくはファイル以外をバックアップし、さらにサーバ192.168.0.12のホストにbkuserというユーザ(公開鍵認証)で/export配下をバックアップする場合。
29
+ web:
30
+ server: 192.168.0.10
31
+ user: takesy
32
+ password: openthesesami
33
+ path: /www
34
+ ignore_list:
35
+ - \.svn
36
+ - \.bk
37
+
38
+ nfs:
39
+ server: 192.168.0.12
40
+ user: bkuser
41
+ key: /home/morita/.ssh/id_rsa
42
+ path: /export
43
+
44
+ 2. 下記のコマンドを実行することにより、バックアップ開始.
45
+
46
+ remote_backup [-f 1.で作成した設定ファイル。デフォルトはbacup.yml] [-o 出力したいディレクトリ デフォルトはカレントディレクトリ] [-v どのファイルをコピーしているか等の情報を表示]
47
+
48
+ 上記実行により、レポジトリとしてカレントディレクトリもしくは-oで指定したディレクトリに1.で設定したnameの名前でディレクトリが作成されます。
49
+ 上記例だとwebとnfsという名前のディレクトリができます。
50
+ バックアップされたファイルは、ファイル名+バックアップ日時の名前で保存され、さらにファイル情報として、実行日時.ymlというバックアップしたファイルの属性等が記述されたファイルが作成されます。このファイルはリストアする時に使用します。
51
+ また、前回のバックアップ時と比較して変更がなかった場合は作成されません。
52
+ ------------------------------------------------------------------------------
53
+ リストア手順
54
+
55
+ 1.リストアするためには下記のコマンドを実行する。
56
+
57
+ restore_backup -f file -o output_dir [-v vervose]
58
+
59
+ fileには、バックアップで作成された日付+ymlを指定します。
60
+ output_dirにはリストアしたいディレクトリのパスを指定します。
61
+ 例:
62
+ restore_backup -f ./web/2008_06_25_06_40.yml -o /tmp/www
63
+
64
+ ------------------------------------------------------------------------------
65
+ RemoteBackup処理概要
66
+
67
+ 1.sshを使用し、リモートサーバ上でls -laを再帰的に実行し、下記のツリー情報を作成する。
68
+ directory:
69
+ - バックアップ対象ディレクトリからの相対パス
70
+ (複数ある場合は上記フォーマットが続く)
71
+
72
+ symbolic:
73
+ バックアップ対象ディレクトリからの相対パス+シンボリックファイル名:
74
+  source: シンボリック元のパス
75
+ (複数ある場合は上記フォーマットが続く)
76
+
77
+ file:
78
+ バックアップ対象ディレクトリからの相対パス+ファイル名:
79
+ size: ファイルのサイズ
80
+ file_name: ファイル名+バックアップ日時
81
+ date: ファイルの更新日付
82
+  (複数ある場合は上記フォーマットが続く)
83
+
84
+ 2. 前回バックアップした際のツリー情報と今回のツリー情報と比べてファイルの更新日付が新しくなっているファイル(初回時はすべて)をリモートサーバからscpでコピーし、file_nameに設定されているファイル名で保存。
85
+
86
+ 3. 今回のツリー情報を保存。
87
+
88
+ 4.リストアする際はツリー情報に基づいて、ディレクトリ、symbolicファイルを作成し、ファイルをfile_nameに設定されているファイル名+バックアップ日時からファイル名にリネームすることで、ツリー状態を復元する。
data/README.rdoc CHANGED
@@ -21,40 +21,36 @@ remote ssh backup is backup files on remote server with ssh. It's not required a
21
21
  == SYNOPSIS:
22
22
 
23
23
  In a nutshell:
24
- To use remotebackup,you should prepare backup configuretion by xml such below.
25
- <backups>
26
- <backup>
27
- <name>backup name</name>
28
- <server>server name</server>
29
- <user>login name</user>
30
- <password>login password</password>
31
- <path>path for backup</path>
32
- <ignore_list>
33
- <ignore>regular expression for not backup </ignore>
34
- :
35
- </ignore_list>
36
- </backup>
37
- :
38
- </backups>
39
-
40
- /backups
41
- mandatory. root directory. It has children of backup informations
42
- /backups/backup
43
- mandatory. unit of backup information
44
- /backups/backup/name
45
- mandatory. backup information name
46
- /backups/backup/server
24
+ To use remotebackup,you should prepare backup configuretion by yaml such below.
25
+
26
+ name:
27
+ server: server_name
28
+ user: user
29
+ password: password(option)
30
+ key: secret key path(option)
31
+ passphrase: secret key passphrase(option)
32
+ path: path for backup
33
+ ignore_list:
34
+ - regular expression for not backup
35
+ :
36
+ :
37
+
38
+ name
39
+ mandatory. backup name
40
+ server
47
41
  mandatory. remote host address.
48
- /backups/backup/user
42
+ user
49
43
  mandatory. login name to remote host .
50
- /backups/backup/password
51
- mandatory. login password to remote host .
52
- /backups/backup/path
44
+ password
45
+ option. login password to remote host .
46
+ key
47
+ option. private key path
48
+ passphrase
49
+ option. private key passphrase
50
+ path
53
51
  mandatory. path for begin to backup on remote host.
54
- /backups/backup/ignore_list
52
+ ignore_list
55
53
  option. parent of ignore entity.
56
- /backups/backup/ignore
57
- option. don't wish file or directory name under backup path.
58
54
 
59
55
  command:
60
56
 
@@ -62,7 +58,7 @@ command:
62
58
 
63
59
 
64
60
  filename:
65
- file name written backup information. if not specified default is ./backup.xml
61
+ file name written backup information. if not specified default is ./backup.yml
66
62
 
67
63
  output_dir:
68
64
  repository directory. if not specified default is .(current directory)
data/Rakefile CHANGED
@@ -1,27 +1,49 @@
1
- %w[rubygems rake rake/clean fileutils newgem rubigen].each { |f| require f }
2
- require File.dirname(__FILE__) + '/lib/remotebackup'
3
-
4
- # Generate all the Rake tasks
5
- # Run 'rake -T' to see list of generated tasks (from gem root directory)
6
- $hoe = Hoe.new('remotebackup', Remotebackup::VERSION) do |p|
7
- p.developer('takeshi morita', 'takeshimorita76@gmail.com')
8
- p.changes = p.paragraphs_of("History.txt", 0..1).join("\n\n")
9
- p.rubyforge_name = p.name # TODO this is default value
10
- p.extra_deps = [
11
- ['net-ssh','>= 2.0.4'],
12
- ['net-scp','>= 1.0.1'],
13
- ]
14
- p.extra_dev_deps = [
15
- ['newgem', ">= #{::Newgem::VERSION}"]
16
- ]
17
- p.clean_globs |= %w[**/.DS_Store tmp *.log]
18
- path = (p.rubyforge_name == p.name) ? p.rubyforge_name : "\#{p.rubyforge_name}/\#{p.name}"
19
- p.remote_rdoc_dir = File.join(path.gsub(/^#{p.rubyforge_name}\/?/,''), 'rdoc')
20
- p.rsync_args = '-av --delete --ignore-errors'
21
- end
22
-
23
- require 'newgem/tasks' # load /tasks/*.rake
24
- Dir['tasks/**/*.rake'].each { |t| load t }
25
-
26
- # TODO - want other tests/tasks run by default? Add them to the list
27
- # task :default => [:spec, :features]
1
+ # encoding: utf-8
2
+
3
+ require 'rubygems'
4
+ require 'bundler'
5
+ begin
6
+ Bundler.setup(:default, :development)
7
+ rescue Bundler::BundlerError => e
8
+ $stderr.puts e.message
9
+ $stderr.puts "Run `bundle install` to install missing gems"
10
+ exit e.status_code
11
+ end
12
+ require 'rake'
13
+
14
+ require 'jeweler'
15
+ Jeweler::Tasks.new do |gem|
16
+ # gem is a Gem::Specification... see http://docs.rubygems.org/read/chapter/20 for more options
17
+ gem.name = "remotebackup"
18
+ gem.homepage = "http://github.com/takeshy/remotebackup"
19
+ gem.license = "MIT"
20
+ gem.summary = %Q{version backup tool using scp.}
21
+ gem.description = %Q{version backup tool using scp.}
22
+ gem.email = "laten@nifty.com"
23
+ gem.authors = ["Takeshi Morita"]
24
+ # dependencies defined in Gemfile
25
+ end
26
+ Jeweler::RubygemsDotOrgTasks.new
27
+
28
+ require 'rspec/core'
29
+ require 'rspec/core/rake_task'
30
+ RSpec::Core::RakeTask.new(:spec) do |spec|
31
+ spec.pattern = FileList['spec/**/*_spec.rb']
32
+ end
33
+
34
+ RSpec::Core::RakeTask.new(:rcov) do |spec|
35
+ spec.pattern = 'spec/**/*_spec.rb'
36
+ spec.rcov = true
37
+ end
38
+
39
+ task :default => :spec
40
+
41
+ require 'rake/rdoctask'
42
+ Rake::RDocTask.new do |rdoc|
43
+ version = File.exist?('VERSION') ? File.read('VERSION') : ""
44
+
45
+ rdoc.rdoc_dir = 'rdoc'
46
+ rdoc.title = "MasterRecord #{version}"
47
+ rdoc.rdoc_files.include('README*')
48
+ rdoc.rdoc_files.include('lib/**/*.rb')
49
+ end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.70.0
data/bin/remote_backup CHANGED
@@ -1,6 +1,7 @@
1
1
  #!/usr/bin/env ruby
2
2
  require 'rubygems'
3
3
  require "optparse"
4
+ require "fileutils"
4
5
  require 'logger'
5
6
  require 'remotebackup'
6
7
 
@@ -14,7 +15,7 @@ def opt_parse()
14
15
  begin
15
16
  parser = OptionParser.new do |opt|
16
17
  opt.banner = "Usage: #{File.basename($0)} [Option]"
17
- opt.on("-f","--file config",String,'location config file. default ./backup.xml') {|o|
18
+ opt.on("-f","--file config",String,'location config file. default ./backup.yml') {|o|
18
19
  $config_file = o
19
20
  }
20
21
  opt.on("-o","--outputdir Output Directory",String,"Directory for output. Default #{ENV['HOME']}") {|o|
@@ -34,12 +35,13 @@ def opt_parse()
34
35
  exit 1
35
36
  end
36
37
  unless $config_file
37
- $config_file = "./backup.xml"
38
+ $config_file = "./backup.yml"
38
39
  end
39
40
  unless $config_out_dir
40
41
  $config_out_dir = "."
41
42
  end
42
- $config_out_dir = File::expand_path($config_out_dir)
43
+ $config_out_dir = File::expand_path($config_out_dir)
44
+ FileUtils.mkdir_p($config_out_dir)
43
45
  if !File.file?($config_file)
44
46
  $stderr.puts "config #{$config_file} is not exist."
45
47
  $stderr.puts parser.help
data/lib/node.rb ADDED
@@ -0,0 +1,91 @@
1
+ module Remotebackup
2
+ class Node
3
+ attr_accessor :ftype,:name,:make_map
4
+ Month = {"Jan" => 1, "Feb" => 2, "Mar" => 3, "Apr" => 4, "May" => 5, "Jun" => 6, "Jul" => 7, "Aug" => 8,
5
+ "Sep" => 9, "Oct" => 10, "Nov" => 11, "Dec" => 12}
6
+ LS_INFO = {
7
+ :redhat => {
8
+ :ls_file => /([-a-z]*)\s+(\d+)\s+(\S+)\s+(\S+)\s+(\d*)\s+([A-Z][a-z]*)\s+(\d+)\s+([\d:]*)\s+(.*)/,
9
+ :ls_link => /([-a-z]*)\s+(\d+)\s+(\S+)\s+(\S+)\s+(\d*)\s+([A-Z][a-z]*)\s+(\d+)\s+([\d:]*)\s+(.*)\s+->\s+(.*)/,
10
+ :position =>
11
+ {:access=>1,:link_num=>2,:user=>3,:group=>4,:size=>5,:month=>6,:day=>7,:yt=>8,:name=>9,:arrow=>10,:source=>11}
12
+ },
13
+ :debian => {
14
+ :ls_file => /([-a-z]*)\s+(\d+)\s+(\S+)\s+(\S+)\s+(\d*)\s+([-0-9]*)\s+([\d:]*)\s+(.*)/,
15
+ :ls_link => /([-a-z]*)\s+(\d+)\s+(\S+)\s+(\S+)\s+(\d*)\s+([-0-9]*)\s+([\d:]*)\s+(.*)\s+->\s+(.*)/,
16
+ :position =>
17
+ {:access=>1,:link_num=>2,:user=>3,:group=>4,:size=>5,:day =>6,:time =>7,:name=>8,:arrow=>9,:source=>10}
18
+ }
19
+ }
20
+
21
+ def self.build(out)
22
+ LS_INFO.each do|key,val|
23
+ if val[:ls_file].match(out)
24
+ return Node.new(key,out)
25
+ end
26
+ end
27
+ nil
28
+ end
29
+
30
+ def to_date_time(match)
31
+ if @type == :redhat
32
+ month = Month[match[position[:month]]]
33
+ day = match[position[:day]].to_i
34
+ hour = 0
35
+ minute = 0
36
+ tmp_time = match[position[:yt]]
37
+ if t = /(.*):(.*)/.match(tmp_time)
38
+ year = DateTime.now.year
39
+ hour = t[1].to_i
40
+ minute = t[2].to_i
41
+ else
42
+ year = tmp_time.to_i
43
+ end
44
+ DateTime.new(year,month,day,hour,minute).to_s
45
+ else
46
+ DateTime.parse(match[position[:time]]).to_s
47
+ end
48
+ end
49
+
50
+ def ls_file
51
+ LS_INFO[@type][:ls_file]
52
+ end
53
+
54
+ def ls_link
55
+ LS_INFO[@type][:ls_link]
56
+ end
57
+
58
+ def position
59
+ LS_INFO[@type][:position]
60
+ end
61
+
62
+ def initialize(type,out)
63
+ @type = type
64
+ case out
65
+ when /^-/
66
+ if m = ls_file.match(out)
67
+ @ftype = :file
68
+ @name = m[position[:name]]
69
+ @size = m[position[:size]].to_i
70
+ @date = to_date_time(m)
71
+ @make_map = lambda{ return {"size" => @size, "date" => @date}}
72
+ end
73
+ when /^l/
74
+ if m = ls_link.match(out)
75
+ @ftype = :symbolic
76
+ @name = m[position[:name]]
77
+ @source = m[position[:source]]
78
+ @make_map = lambda{ return {"source" => @source}}
79
+ end
80
+ when /^d/
81
+ if m = ls_file.match(out)
82
+ @ftype = :directory
83
+ @name = m[position[:name]]
84
+ end
85
+ else
86
+ @ftype = :special
87
+ $log.error("#{out} is not regular file. ignore.")
88
+ end
89
+ end
90
+ end
91
+ end
data/lib/remotebackup.rb CHANGED
@@ -1,97 +1,44 @@
1
- $:.unshift(File.dirname(__FILE__)) unless
2
- $:.include?(File.dirname(__FILE__)) || $:.include?(File.expand_path(File.dirname(__FILE__)))
3
1
  require 'rubygems'
4
2
  require 'net/ssh'
5
3
  require 'net/scp'
6
4
  require "stringio"
7
5
  require "fileutils"
8
- require "rexml/document"
9
6
  require "date"
10
7
  require 'logger'
11
8
  require 'yaml'
9
+ require 'node'
12
10
  module Remotebackup
13
- VERSION='0.51.1'
14
- class Node
15
- attr_accessor :ftype,:name,:makeMap
16
- LS_FILE = /([-a-z]*)\s+(\d+)\s+(\S+)\s+(\S+)\s+(\d*)\s+([A-Z][a-z]*)\s+(\d+)\s+([\d:]*)\s+(.*)/
17
- LS_LINK = /([-a-z]*)\s+(\d+)\s+(\S+)\s+(\S+)\s+(\d*)\s+([A-Z][a-z]*)\s+(\d+)\s+([\d:]*)\s+(.*)\s+->\s+(.*)/
18
- Result = {:access=>0,:link_num=>1,:user=>2,:group=>3,:size=>4,:month=>5,:day=>6,:yt=>7,:name=>8,:arrow=>9,:source=>10}
19
- Month = {"Jan" => 1, "Feb" => 2, "Mar" => 3, "Apr" => 4, "May" => 5, "Jun" => 6, "Jul" => 7, "Aug" => 8,
20
- "Sep" => 9, "Oct" => 10, "Nov" => 11, "Dec" => 12}
21
-
22
- def initialize(out)
23
- if out =~ /[^\x20-\x7E]/
24
- $log.error("#{out} includes irregular char. ignore.")
25
- return
26
- end
27
- case out
28
- when /^-/
29
- if LS_FILE.match(out)
30
- @name = $9
31
- @ftype = :file
32
- @size = $5.to_i
33
- month = Month[$6]
34
- day = $7.to_i
35
- hour = 0
36
- minute = 0
37
- tmpTime = $8
38
- if tmpTime =~ /(.*):(.*)/
39
- year = DateTime.now.year
40
- hour = $1.to_i
41
- minute = $2.to_i
42
- else
43
- year = tmpTime.to_i
44
- end
45
- @date = DateTime.new(year,month,day,hour,minute).to_s
46
- @makeMap = lambda{ return {"size" => @size, "date" => @date}}
47
- else
48
- $log.error("#{out} is not recognized. ignore.")
49
- end
50
- when /^l/
51
- if LS_LINK.match(out)
52
- @name = $9
53
- @ftype = :symbolic
54
- @source = $10
55
- @makeMap = lambda{ return {"source" => @source}}
56
- end
57
- when /^d/
58
- if LS_FILE.match(out)
59
- @name = $9
60
- @ftype = :directory
61
- end
62
- else
63
- @ftype = :special
64
- $log.error("#{out} is not regular file. ignore.")
65
- end
66
- end
67
- end
68
11
  class BackupInfo
69
- attr_accessor :fileMap,:mod,:last_file
70
- def initialize(name,server,user,password,path,ignore_list)
12
+ attr_accessor :file_map,:mod,:last_file
13
+ def initialize(args)
71
14
  @mod = false
72
- @name = name
73
- @server = server
74
- @user = user
75
- @password = password
76
- @path = path
77
- @ignore_list = ignore_list
15
+ @name = args["name"] || args["server"]
16
+ @server = args["server"]
17
+ @user = args["user"]
18
+ @options = {}
19
+ @options[:port] = args["port"].to_i if args["port"]
20
+ @options[:password] = args["password"] if args["password"]
21
+ @options[:passphrase] = args["passphrase"] if args["passphrase"]
22
+ if args["key"]
23
+ @options[:keys] = [File.expand_path(args["key"])]
24
+ end
25
+ @path = args["path"]
26
+ @ignore_list = args["ignore_list"] || []
78
27
  @nowTime = DateTime.now
79
- @fileMap = {"file" => Hash.new,"symbolic" => Hash.new,"directory"=>Array.new}
80
- Net::SSH.start(@server,@user,:password=>@password) { |session|
81
- makeFileMapList(session,"")
28
+ @file_map = {"file" => Hash.new,"symbolic" => Hash.new,"directory"=>Array.new}
29
+ Net::SSH.start(@server,@user,@options) { |session|
30
+ make_file_map_list(session,"")
82
31
  }
83
32
  end
84
33
  def ignore_check(target)
85
- if @ignore_list
86
- @ignore_list.each do |ignore|
87
- if target =~ /#{ignore}/
88
- return false
89
- end
34
+ @ignore_list.each do |ignore|
35
+ if target =~ /#{ignore}/
36
+ return false
90
37
  end
91
38
  end
92
39
  return true
93
40
  end
94
- def makeFileMapList(session,target)
41
+ def make_file_map_list(session,target)
95
42
  if target != ""
96
43
  target_path = @path +"/"+target
97
44
  else
@@ -115,24 +62,22 @@ module Remotebackup
115
62
  return
116
63
  end
117
64
  lines = StringIO.new(out).readlines
118
- if lines[0].split().length < 9
119
- @fileMap["directory"].push target unless target == ""
65
+ if !Node.build(lines[0].chomp)
66
+ @file_map["directory"].push target unless target == ""
120
67
  makeFileMap(session,target,lines)
121
68
  else
122
- node = Node.new(lines[0].chomp)
69
+ node = Node.build(lines[0].chomp)
123
70
  if node.ftype == :symbolic
124
- @fileMap["symbolic"][File.basename(@path)] = node.makeMap.call
71
+ @file_map["symbolic"][File.basename(@path)] = node.make_map.call
125
72
  elsif node.ftype == :file
126
- @fileMap["file"][File.basename(@path)] = node.makeMap.call
73
+ @file_map["file"][File.basename(@path)] = node.make_map.call
127
74
  end
128
75
  end
129
76
  end
130
77
  def makeFileMap(session,target,lines)
131
78
  lines.each do |line|
132
- if line.split().length < 9
133
- next
134
- end
135
- node = Node.new(line.chomp)
79
+ node = Node.build(line.chomp)
80
+ next unless node
136
81
  if not node.name or node.name == "." or node.name == ".."
137
82
  next
138
83
  end
@@ -146,13 +91,13 @@ module Remotebackup
146
91
  end
147
92
  case node.ftype
148
93
  when :directory
149
- makeFileMapList(session,target_name)
94
+ make_file_map_list(session,target_name)
150
95
  when :special
151
96
  next
152
97
  when :file
153
- @fileMap["file"][target_name] = node.makeMap.call
98
+ @file_map["file"][target_name] = node.make_map.call
154
99
  when :symbolic
155
- @fileMap["symbolic"][target_name] = node.makeMap.call
100
+ @file_map["symbolic"][target_name] = node.make_map.call
156
101
  end
157
102
  end
158
103
  end
@@ -160,7 +105,7 @@ module Remotebackup
160
105
  output_dir = out_dir + "/" + @name
161
106
  f = output_dir + "/" + date_to_filename + ".yml"
162
107
  File.open(f,"w") do |f|
163
- f.write YAML.dump(@fileMap)
108
+ f.write YAML.dump(@file_map)
164
109
  end
165
110
  end
166
111
  def cleanFileInfo()
@@ -183,32 +128,33 @@ module Remotebackup
183
128
  def differencial_copy(out_dir)
184
129
  output_dir = out_dir + "/" + @name
185
130
  FileUtils.mkdir_p(output_dir)
186
- oldFileInfoMap = load_last_yaml(output_dir)
187
- @fileMap["directory"].each do |dir|
188
- unless oldFileInfoMap["directory"].include?(dir)
131
+ old_file_info_map = load_last_yaml(output_dir)
132
+ @file_map["directory"].each do |dir|
133
+ unless old_file_info_map["directory"].include?(dir)
189
134
  @mod = true
190
135
  msg_out "create directory:#{dir}"
191
136
  FileUtils.mkdir_p(output_dir + "/" + dir)
192
137
  end
193
138
  end
194
- oldFileMap = oldFileInfoMap["symbolic"]
195
- @fileMap["symbolic"].each do |key,val|
196
- if !oldFileMap[key] || oldFileMap[key]["source"] != val["source"]
139
+ old_file_map = old_file_info_map["symbolic"]
140
+ @file_map["symbolic"].each do |key,val|
141
+ if !old_file_map[key] || old_file_map[key]["source"] != val["source"]
197
142
  @mod = true
198
- if !oldFileMap[key]
143
+ if !old_file_map[key]
199
144
  msg_out "create symbolic:#{key}"
200
145
  else
201
146
  msg_out "modified symbolic:#{key}"
202
147
  end
203
148
  end
204
149
  end
205
- oldFileMap = oldFileInfoMap["file"]
206
- Net::SSH.start(@server, @user, :password => @password) do |ssh|
207
- @fileMap["file"].each do |key,val|
208
- if !oldFileMap[key] || oldFileMap[key]["date"] != val["date"]
150
+ old_file_map = old_file_info_map["file"]
151
+ Net::SSH.start(@server, @user,@options) do |ssh|
152
+ @file_map["file"].each do |key,val|
153
+ key = key.dup.force_encoding("utf-8")
154
+ if !old_file_map[key] || old_file_map[key]["date"] != val["date"]
209
155
  @mod = true
210
156
  file_name = output_dir + "/" + key + date_to_filename
211
- orig = "#{@path}/#{key}".gsub(/ /,"\\ ").gsub(/\(/,"\\(").gsub(/\)/,"\\)").gsub(/&/,"\\\\&").gsub(/\=/,"\\=")
157
+ orig = "#{@path}/#{key}"
212
158
  msg_out "scp #{orig} #{file_name}"
213
159
  begin
214
160
  ssh.scp.download!(orig,file_name)
@@ -217,13 +163,13 @@ module Remotebackup
217
163
  next
218
164
  end
219
165
  val["file_name"] = file_name
220
- if !oldFileMap[key]
166
+ if !old_file_map[key]
221
167
  msg_out "create file:#{key}"
222
168
  else
223
169
  msg_out "modified file:#{key}"
224
170
  end
225
171
  else
226
- val["file_name"] = oldFileMap[key]["file_name"]
172
+ val["file_name"] = old_file_map[key]["file_name"]
227
173
  end
228
174
  end
229
175
  end
@@ -243,33 +189,15 @@ module Remotebackup
243
189
  def initialize(config_file,config_out_dir)
244
190
  @config_file = config_file
245
191
  @config_out_dir = config_out_dir
246
- @doc = REXML::Document.new(File.open(@config_file))
247
- @top = @doc.elements["/backups"]
192
+ @doc = YAML.load_file(@config_file)
248
193
  @conf_backups = Array.new
249
- unless @top
250
- oops("/backups is not set in #{@config_file}.")
251
- end
252
- @top.each_element do |backup|
253
- bkup_info = Hash.new
254
- backup.each_element do |elem|
255
- if elem.name == "ignore_list"
256
- ignores = Array.new
257
- elem.each_element do |ignore|
258
- if ignore.text
259
- ignores.push(ignore.text)
260
- end
261
- end
262
- bkup_info["ignore_list"] = ignores
263
- else
264
- bkup_info[elem.name] = elem.text
265
- end
266
- end
267
- @conf_backups.push(bkup_info)
194
+ @doc.each do |key,val|
195
+ @conf_backups.push(val.merge(:name => key))
268
196
  end
269
197
  end
270
198
  def start
271
199
  @conf_backups.each do |conf|
272
- bkup = BackupInfo.new(conf["name"],conf["server"],conf["user"],conf["password"],conf["path"],conf["ignore_list"])
200
+ bkup = BackupInfo.new(conf)
273
201
  msg_out "--------------------------------"
274
202
  msg_out "Backup start #{conf['name']}"
275
203
  msg_out "--------------------------------"
Binary file
@@ -0,0 +1,67 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = "remotebackup"
8
+ s.version = "0.70.0"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["Takeshi Morita"]
12
+ s.date = "2011-12-27"
13
+ s.description = "version backup tool using scp."
14
+ s.email = "laten@nifty.com"
15
+ s.executables = ["remote_backup", "restore_backup"]
16
+ s.extra_rdoc_files = [
17
+ "ChangeLog",
18
+ "LICENSE.txt",
19
+ "README",
20
+ "README.rdoc"
21
+ ]
22
+ s.files = [
23
+ "ChangeLog",
24
+ "Gemfile",
25
+ "LICENSE.txt",
26
+ "README",
27
+ "README.rdoc",
28
+ "Rakefile",
29
+ "VERSION",
30
+ "bin/remote_backup",
31
+ "bin/restore_backup",
32
+ "lib/node.rb",
33
+ "lib/remotebackup.rb",
34
+ "pkg/remotebackup-0.70.0.gem",
35
+ "remotebackup.gemspec"
36
+ ]
37
+ s.homepage = "http://github.com/takeshy/remotebackup"
38
+ s.licenses = ["MIT"]
39
+ s.require_paths = ["lib"]
40
+ s.rubygems_version = "1.8.11"
41
+ s.summary = "version backup tool using scp."
42
+
43
+ if s.respond_to? :specification_version then
44
+ s.specification_version = 3
45
+
46
+ if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
47
+ s.add_runtime_dependency(%q<net-scp>, [">= 0"])
48
+ s.add_development_dependency(%q<rspec>, ["~> 2.3.0"])
49
+ s.add_development_dependency(%q<bundler>, ["~> 1.0.0"])
50
+ s.add_development_dependency(%q<jeweler>, ["~> 1.6.4"])
51
+ s.add_development_dependency(%q<rcov>, [">= 0"])
52
+ else
53
+ s.add_dependency(%q<net-scp>, [">= 0"])
54
+ s.add_dependency(%q<rspec>, ["~> 2.3.0"])
55
+ s.add_dependency(%q<bundler>, ["~> 1.0.0"])
56
+ s.add_dependency(%q<jeweler>, ["~> 1.6.4"])
57
+ s.add_dependency(%q<rcov>, [">= 0"])
58
+ end
59
+ else
60
+ s.add_dependency(%q<net-scp>, [">= 0"])
61
+ s.add_dependency(%q<rspec>, ["~> 2.3.0"])
62
+ s.add_dependency(%q<bundler>, ["~> 1.0.0"])
63
+ s.add_dependency(%q<jeweler>, ["~> 1.6.4"])
64
+ s.add_dependency(%q<rcov>, [">= 0"])
65
+ end
66
+ end
67
+
metadata CHANGED
@@ -1,111 +1,122 @@
1
- --- !ruby/object:Gem::Specification
1
+ --- !ruby/object:Gem::Specification
2
2
  name: remotebackup
3
- version: !ruby/object:Gem::Version
4
- version: 0.51.1
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.70.0
5
+ prerelease:
5
6
  platform: ruby
6
- authors:
7
- - takeshi morita
7
+ authors:
8
+ - Takeshi Morita
8
9
  autorequire:
9
10
  bindir: bin
10
11
  cert_chain: []
11
-
12
- date: 2008-12-03 00:00:00 -05:00
13
- default_executable:
14
- dependencies:
15
- - !ruby/object:Gem::Dependency
16
- name: net-ssh
17
- type: :runtime
18
- version_requirement:
19
- version_requirements: !ruby/object:Gem::Requirement
20
- requirements:
21
- - - ">="
22
- - !ruby/object:Gem::Version
23
- version: 2.0.4
24
- version:
25
- - !ruby/object:Gem::Dependency
12
+ date: 2011-12-27 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
26
15
  name: net-scp
16
+ requirement: &10185040 !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
27
22
  type: :runtime
28
- version_requirement:
29
- version_requirements: !ruby/object:Gem::Requirement
30
- requirements:
31
- - - ">="
32
- - !ruby/object:Gem::Version
33
- version: 1.0.1
34
- version:
35
- - !ruby/object:Gem::Dependency
36
- name: newgem
23
+ prerelease: false
24
+ version_requirements: *10185040
25
+ - !ruby/object:Gem::Dependency
26
+ name: rspec
27
+ requirement: &10183620 !ruby/object:Gem::Requirement
28
+ none: false
29
+ requirements:
30
+ - - ~>
31
+ - !ruby/object:Gem::Version
32
+ version: 2.3.0
33
+ type: :development
34
+ prerelease: false
35
+ version_requirements: *10183620
36
+ - !ruby/object:Gem::Dependency
37
+ name: bundler
38
+ requirement: &10182360 !ruby/object:Gem::Requirement
39
+ none: false
40
+ requirements:
41
+ - - ~>
42
+ - !ruby/object:Gem::Version
43
+ version: 1.0.0
44
+ type: :development
45
+ prerelease: false
46
+ version_requirements: *10182360
47
+ - !ruby/object:Gem::Dependency
48
+ name: jeweler
49
+ requirement: &10181140 !ruby/object:Gem::Requirement
50
+ none: false
51
+ requirements:
52
+ - - ~>
53
+ - !ruby/object:Gem::Version
54
+ version: 1.6.4
37
55
  type: :development
38
- version_requirement:
39
- version_requirements: !ruby/object:Gem::Requirement
40
- requirements:
41
- - - ">="
42
- - !ruby/object:Gem::Version
43
- version: 1.1.0
44
- version:
45
- - !ruby/object:Gem::Dependency
46
- name: hoe
56
+ prerelease: false
57
+ version_requirements: *10181140
58
+ - !ruby/object:Gem::Dependency
59
+ name: rcov
60
+ requirement: &10196620 !ruby/object:Gem::Requirement
61
+ none: false
62
+ requirements:
63
+ - - ! '>='
64
+ - !ruby/object:Gem::Version
65
+ version: '0'
47
66
  type: :development
48
- version_requirement:
49
- version_requirements: !ruby/object:Gem::Requirement
50
- requirements:
51
- - - ">="
52
- - !ruby/object:Gem::Version
53
- version: 1.8.0
54
- version:
55
- description: remote ssh backup is backup files on remote server with ssh. It's not required any program on remote server.Only download files which changed size or mday. And you can restore not only last version but also past version.
56
- email:
57
- - takeshimorita76@gmail.com
58
- executables:
67
+ prerelease: false
68
+ version_requirements: *10196620
69
+ description: version backup tool using scp.
70
+ email: laten@nifty.com
71
+ executables:
59
72
  - remote_backup
60
73
  - restore_backup
61
74
  extensions: []
62
-
63
- extra_rdoc_files:
64
- - History.txt
65
- - Manifest.txt
66
- - PostInstall.txt
75
+ extra_rdoc_files:
76
+ - ChangeLog
77
+ - LICENSE.txt
78
+ - README
67
79
  - README.rdoc
68
- files:
69
- - History.txt
70
- - Manifest.txt
71
- - PostInstall.txt
80
+ files:
81
+ - ChangeLog
82
+ - Gemfile
83
+ - LICENSE.txt
84
+ - README
72
85
  - README.rdoc
73
86
  - Rakefile
74
- - lib/remotebackup.rb
75
- - script/console
76
- - script/destroy
77
- - script/generate
87
+ - VERSION
78
88
  - bin/remote_backup
79
89
  - bin/restore_backup
80
- - test/test_helper.rb
81
- - test/test_remotebackup.rb
82
- has_rdoc: true
83
- homepage: http://net-ssh.rubyforge.org/remotebackup
90
+ - lib/node.rb
91
+ - lib/remotebackup.rb
92
+ - pkg/remotebackup-0.70.0.gem
93
+ - remotebackup.gemspec
94
+ homepage: http://github.com/takeshy/remotebackup
95
+ licenses:
96
+ - MIT
84
97
  post_install_message:
85
- rdoc_options:
86
- - --main
87
- - README.rdoc
88
- require_paths:
98
+ rdoc_options: []
99
+ require_paths:
89
100
  - lib
90
- required_ruby_version: !ruby/object:Gem::Requirement
91
- requirements:
92
- - - ">="
93
- - !ruby/object:Gem::Version
94
- version: "0"
95
- version:
96
- required_rubygems_version: !ruby/object:Gem::Requirement
97
- requirements:
98
- - - ">="
99
- - !ruby/object:Gem::Version
100
- version: "0"
101
- version:
101
+ required_ruby_version: !ruby/object:Gem::Requirement
102
+ none: false
103
+ requirements:
104
+ - - ! '>='
105
+ - !ruby/object:Gem::Version
106
+ version: '0'
107
+ segments:
108
+ - 0
109
+ hash: -238872459189926738
110
+ required_rubygems_version: !ruby/object:Gem::Requirement
111
+ none: false
112
+ requirements:
113
+ - - ! '>='
114
+ - !ruby/object:Gem::Version
115
+ version: '0'
102
116
  requirements: []
103
-
104
- rubyforge_project: remotebackup
105
- rubygems_version: 1.3.1
117
+ rubyforge_project:
118
+ rubygems_version: 1.8.11
106
119
  signing_key:
107
- specification_version: 2
108
- summary: remote ssh backup is backup files on remote server with ssh
109
- test_files:
110
- - test/test_remotebackup.rb
111
- - test/test_helper.rb
120
+ specification_version: 3
121
+ summary: version backup tool using scp.
122
+ test_files: []
data/Manifest.txt DELETED
@@ -1,13 +0,0 @@
1
- History.txt
2
- Manifest.txt
3
- PostInstall.txt
4
- README.rdoc
5
- Rakefile
6
- lib/remotebackup.rb
7
- script/console
8
- script/destroy
9
- script/generate
10
- bin/remote_backup
11
- bin/restore_backup
12
- test/test_helper.rb
13
- test/test_remotebackup.rb
data/PostInstall.txt DELETED
@@ -1,7 +0,0 @@
1
-
2
- For more information on remotebackup, see http://remotebackup.rubyforge.org
3
-
4
- NOTE: Change this information in PostInstall.txt
5
- You can also delete it if you don't want it.
6
-
7
-
data/script/console DELETED
@@ -1,10 +0,0 @@
1
- #!/usr/bin/env ruby
2
- # File: script/console
3
- irb = RUBY_PLATFORM =~ /(:?mswin|mingw)/ ? 'irb.bat' : 'irb'
4
-
5
- libs = " -r irb/completion"
6
- # Perhaps use a console_lib to store any extra methods I may want available in the cosole
7
- # libs << " -r #{File.dirname(__FILE__) + '/../lib/console_lib/console_logger.rb'}"
8
- libs << " -r #{File.dirname(__FILE__) + '/../lib/remotebackup.rb'}"
9
- puts "Loading remotebackup gem"
10
- exec "#{irb} #{libs} --simple-prompt"
data/script/destroy DELETED
@@ -1,14 +0,0 @@
1
- #!/usr/bin/env ruby
2
- APP_ROOT = File.expand_path(File.join(File.dirname(__FILE__), '..'))
3
-
4
- begin
5
- require 'rubigen'
6
- rescue LoadError
7
- require 'rubygems'
8
- require 'rubigen'
9
- end
10
- require 'rubigen/scripts/destroy'
11
-
12
- ARGV.shift if ['--help', '-h'].include?(ARGV[0])
13
- RubiGen::Base.use_component_sources! [:rubygems, :newgem, :newgem_theme, :test_unit]
14
- RubiGen::Scripts::Destroy.new.run(ARGV)
data/script/generate DELETED
@@ -1,14 +0,0 @@
1
- #!/usr/bin/env ruby
2
- APP_ROOT = File.expand_path(File.join(File.dirname(__FILE__), '..'))
3
-
4
- begin
5
- require 'rubigen'
6
- rescue LoadError
7
- require 'rubygems'
8
- require 'rubigen'
9
- end
10
- require 'rubigen/scripts/generate'
11
-
12
- ARGV.shift if ['--help', '-h'].include?(ARGV[0])
13
- RubiGen::Base.use_component_sources! [:rubygems, :newgem, :newgem_theme, :test_unit]
14
- RubiGen::Scripts::Generate.new.run(ARGV)
data/test/test_helper.rb DELETED
@@ -1,3 +0,0 @@
1
- require 'stringio'
2
- require 'test/unit'
3
- require File.dirname(__FILE__) + '/../lib/remotebackup'
@@ -1,11 +0,0 @@
1
- require File.dirname(__FILE__) + '/test_helper.rb'
2
-
3
- class TestRemotebackup < Test::Unit::TestCase
4
-
5
- def setup
6
- end
7
-
8
- def test_truth
9
- assert true
10
- end
11
- end