Add backup setting feature.
This commit is contained in:
parent
9592608857
commit
512970d590
|
@ -439,6 +439,10 @@ class Admin::SitePanelController < OrbitAdminController
|
|||
end
|
||||
end
|
||||
end
|
||||
when 'apply_change_backup_setting'
|
||||
Thread.new do
|
||||
system("bundle exec rake exec_commands:change_backup_setting[#{params[:id]}]")
|
||||
end
|
||||
else
|
||||
Thread.new do
|
||||
cmds = params[:commands].split('////')
|
||||
|
@ -516,6 +520,27 @@ class Admin::SitePanelController < OrbitAdminController
|
|||
@site_server = SiteServer.find(params[:id])
|
||||
end
|
||||
def update_backup_setting
|
||||
@site_server = SiteServer.find(params[:id])
|
||||
site_server_params = params.require(:site_server).permit! rescue {}
|
||||
need_rewrite_backup_setting = false
|
||||
site_server_params["site_server_file_backups_attributes"].each do |k, v|
|
||||
if v["_destroy"] == 'true'
|
||||
need_rewrite_backup_setting = true
|
||||
end
|
||||
end if site_server_params["site_server_file_backups_attributes"]
|
||||
site_server_params["site_server_db_backups_attributes"].each do |k, v|
|
||||
if v["_destroy"] == 'true'
|
||||
need_rewrite_backup_setting = true
|
||||
end
|
||||
end if site_server_params["site_server_db_backups_attributes"]
|
||||
@site_server.update_attributes(site_server_params)
|
||||
unless need_rewrite_backup_setting
|
||||
need_rewrite_backup_setting = ((@site_server.site_server_file_backups.where(:need_rewrite=>true).count + @site_server.site_server_db_backups.where(:need_rewrite=>true).count) != 0)
|
||||
end
|
||||
if need_rewrite_backup_setting
|
||||
@site_server.update(:need_rewrite_backup_setting=>true)
|
||||
end
|
||||
redirect_back_custom
|
||||
end
|
||||
private
|
||||
def site_cert_params
|
||||
|
|
|
@ -17,7 +17,12 @@ class SiteServer
|
|||
field :need_update_site_ids, type: Array, default: []
|
||||
field :super_user_changed, type: Boolean, type: false
|
||||
field :removed_super_users, type: Array, default: []
|
||||
field :need_rewrite_backup_setting, type: Boolean, default: false
|
||||
has_many :site_server_file_backups, :autosave => true, :dependent => :destroy
|
||||
has_many :site_server_db_backups, :autosave => true, :dependent => :destroy
|
||||
has_many :site_super_users, :autosave => true, :dependent => :destroy
|
||||
accepts_nested_attributes_for :site_server_file_backups, :allow_destroy => true
|
||||
accepts_nested_attributes_for :site_server_db_backups, :allow_destroy => true
|
||||
accepts_nested_attributes_for :site_super_users, :allow_destroy => true
|
||||
def check_super_user_changed
|
||||
self.update(:super_user_changed => (self.site_super_users.where(:is_changed=>true).count != 0 || self.removed_super_users.count != 0))
|
||||
|
|
|
@ -0,0 +1,143 @@
|
|||
class SiteServerDbBackup
|
||||
include Mongoid::Document
|
||||
include Mongoid::Timestamps
|
||||
PeriodsTypes=['day','week','month']
|
||||
belongs_to :site_server
|
||||
field :disable, type: Boolean, default: false
|
||||
field :backup_time, type: String, default: '03:00'
|
||||
field :path , type: String ,default: '/home/backup/db'
|
||||
field :period, type: Integer, default: 0 # 0 => daily , 1 => weekly , 2 => monthly
|
||||
field :retain_count, type: Integer, default: 7
|
||||
field :need_rewrite, type: Boolean, default: true
|
||||
|
||||
before_save do
|
||||
if self.changed?
|
||||
self.need_rewrite = true
|
||||
end
|
||||
end
|
||||
def to_crontab_script(return_string=true)
|
||||
# minute , hour, day(of month, 1~31), month(1~12), day(of week,0~6)
|
||||
crontab_time = ['*', '*', '*', '*', '*']
|
||||
hour, minute = self.backup_time.split(':').map{|s| s.to_i}
|
||||
crontab_time[0] = minute.to_s rescue '0'
|
||||
crontab_time[1] = hour.to_s rescue '0'
|
||||
if self.period == 1 #weekly
|
||||
crontab_time[4] = '0' #every Sunday
|
||||
elsif self.period == 2 #monthly
|
||||
crontab_time[2] = '1' #day 1 of every month
|
||||
end
|
||||
if self.retain_count
|
||||
retain_text = "1 week ago"
|
||||
if self.period != 0 || self.retain_count != 7
|
||||
retain_text = "#{self.retain_count} #{PeriodsTypes[self.period]} ago"
|
||||
end
|
||||
scripts = ["#{crontab_time.join(' ')} mongodump -o #{self.path}/`date \"+\\%Y\\%m\\%d\"`_db"]
|
||||
if hour < 23
|
||||
next_hour = hour + 1
|
||||
crontab_time[1] = next_hour.to_s
|
||||
else
|
||||
crontab_time[1] = ((hour + 1) % 24).to_s
|
||||
if self.period == 1 #weekly
|
||||
crontab_time[4] = '1' #every Sunday + 1 = Monday
|
||||
elsif self.period == 2 #monthly
|
||||
crontab_time[2] = '2' #day 1 of every month + 1 = 2
|
||||
end
|
||||
retain_text += " 1 day ago"
|
||||
end
|
||||
scripts << "#{crontab_time.join(' ')} rm -fr #{self.path}/`date --date=\"#{retain_text}\" \"+\\%Y\\%m\\%d\"`_db"
|
||||
end
|
||||
if return_string
|
||||
scripts.join("\n")
|
||||
else
|
||||
scripts
|
||||
end
|
||||
end
|
||||
def self.read_from_crontab_line(crontab_line, crontab_lines)
|
||||
if crontab_line.include?('mongodump')
|
||||
tmp = crontab_line.split(/\s+[^\s]*mongodump\s+/) # ex: ["0 3 * * *", "-o /home/backup/db/`date \"+\\%Y\\%m\\%d\"`_db"]
|
||||
if tmp.count == 2
|
||||
crontab_time = tmp[0].split(/\s+/)
|
||||
path = File.dirname(tmp[1].split('-o')[1].strip) rescue nil
|
||||
if path
|
||||
if crontab_time[4] != '*' #weekly
|
||||
period = 1
|
||||
period_unit = 1.week
|
||||
elsif crontab_time[2] != '*' #monthly
|
||||
period = 2
|
||||
period_unit = 1.month
|
||||
else #daily
|
||||
period = 0
|
||||
period_unit = 1.day
|
||||
end
|
||||
time = "#{crontab_time[1].rjust(2, "0")}:#{crontab_time[0].rjust(2, "0")}"
|
||||
regex_path = /\s+#{::Regexp.escape(path)}\//
|
||||
match_line = crontab_lines.select{|l| l.match(/\s+(|\/usr\/bin\/)rm/) && l.match(regex_path)}.first
|
||||
if match_line.nil?
|
||||
retain_count = nil
|
||||
else
|
||||
retain_text = match_line.scan(/`\s*date\s+\-\-date=[\'\"]([^\'\"]+)[\'\"]/).flatten.first
|
||||
tmp_retain_count, tmp_period = retain_text.sub(/\s+ago/, '').split(/\s+/)
|
||||
tmp_retain_count = tmp_retain_count.to_i
|
||||
retain_count = (tmp_retain_count.send(tmp_period) / period_unit rescue nil)
|
||||
end
|
||||
return [time, path, period, retain_count]
|
||||
else
|
||||
return nil
|
||||
end
|
||||
else
|
||||
return nil
|
||||
end
|
||||
else
|
||||
return nil
|
||||
end
|
||||
end
|
||||
def self.clean_crontab_setting(crontab_lines_str)
|
||||
crontab_lines = crontab_lines_str.split("\n")
|
||||
related_path = []
|
||||
crontab_lines.each do |crontab_line|
|
||||
if crontab_line.include?('mongodump')
|
||||
tmp = crontab_line.split(/\s+[^\s]*mongodump\s+/) # ex: ["0 3 * * *", "-o /home/backup/db/`date \"+\\%Y\\%m\\%d\"`_db"]
|
||||
output_dir = File.dirname(tmp[1].split('-o')[1].strip) rescue nil
|
||||
if output_dir
|
||||
related_path << output_dir
|
||||
end
|
||||
end
|
||||
end
|
||||
related_path_reg = Regexp.union(related_path.map{|s| /\s+#{::Regexp.escape(s)}\//})
|
||||
crontab_lines_str = crontab_lines.map do |crontab_line|
|
||||
if crontab_line.match(related_path_reg)
|
||||
nil
|
||||
else
|
||||
crontab_line
|
||||
end
|
||||
end.compact.join("\n")
|
||||
end
|
||||
def self.write_crontab_setting(site_server, crontab_lines_str)
|
||||
new_crontab_lines = self.where(:site_server_id=> site_server.id, :disable=>false).map{|db_backup| db_backup.to_crontab_script(false)}
|
||||
crontab_lines = crontab_lines_str.split("\n")
|
||||
exists_indices = new_crontab_lines.map do |sub_crontab_lines|
|
||||
match_reg = ::Regexp.new(sub_crontab_lines[0].gsub(/\s+/, '\s+'))
|
||||
crontab_lines.index{|l| l.match(match_reg)}
|
||||
end
|
||||
removed_related_path = []
|
||||
crontab_lines.each_with_index do |crontab_line, i|
|
||||
if crontab_line.include?('mongodump') && exists_indices.exclude?(i)
|
||||
tmp = crontab_line.split(/\s+[^\s]*mongodump\s+/) # ex: ["0 3 * * *", "-o /home/backup/db/`date \"+\\%Y\\%m\\%d\"`_db"]
|
||||
output_dir = File.dirname(tmp[1].split('-o')[1].strip) rescue nil
|
||||
if output_dir
|
||||
removed_related_path << output_dir
|
||||
end
|
||||
end
|
||||
end
|
||||
removed_related_path.each_with_index do |path|
|
||||
regex_path = /\s+#{::Regexp.escape(path)}\//
|
||||
crontab_lines = crontab_lines.select{|l| l.match(regex_path).nil?}
|
||||
end
|
||||
exists_indices.each_with_index do |idx, i|
|
||||
if idx.nil?
|
||||
crontab_lines << new_crontab_lines[i]
|
||||
end
|
||||
end
|
||||
crontab_lines_str = crontab_lines.compact.join("\n")
|
||||
end
|
||||
end
|
|
@ -0,0 +1,176 @@
|
|||
class SiteServerFileBackup
|
||||
include Mongoid::Document
|
||||
include Mongoid::Timestamps
|
||||
PeriodsTypes=['daily','weekly','monthly']
|
||||
DefaultConf='/etc/rsnapshot.conf'
|
||||
belongs_to :site_server
|
||||
field :disable, type: Boolean, default: false
|
||||
field :backup_time, type: String, default: '04:15'
|
||||
field :path , type: String ,default: '/home/backup/orbit'
|
||||
field :period, type: Integer, default: 0 # 0 => daily , 1 => weekly , 2 => monthly
|
||||
field :retain_count, type: Integer, default: 7
|
||||
field :rsnapshot_conf_path, type: String, default: DefaultConf
|
||||
field :backup_dir, type: String, default: '/home/{{user_name}}'
|
||||
field :backup_prefix, type: String, default: 'localhost/'
|
||||
field :need_rewrite, type: Boolean, default: true
|
||||
|
||||
before_create do
|
||||
other_rsnapshot_conf_path = self.class.pluck(:rsnapshot_conf_path)
|
||||
if other_rsnapshot_conf_path.include?(self.rsnapshot_conf_path)
|
||||
max_postfix = other_rsnapshot_conf_path.select{|s| s.start_with?('/etc/')}.map{|s| tmp = File.basename(s).split('.conf')[0].match(/\d+/); tmp ? tmp[0].to_i : 0}.max
|
||||
self.rsnapshot_conf_path = "#{self.rsnapshot_conf_path.split('.conf')[0]}#{max_postfix + 1}.conf"
|
||||
end
|
||||
end
|
||||
before_save do
|
||||
if self.changed?
|
||||
self.need_rewrite = true
|
||||
end
|
||||
end
|
||||
def to_crontab_script
|
||||
# minute , hour, day(of month, 1~31), month(1~12), day(of week,0~6)
|
||||
crontab_time = ['*', '*', '*', '*', '*']
|
||||
time = self.backup_time.split(':').map{|s| s.sub(/0(\d)/){$1}} rescue []
|
||||
crontab_time[0] = time[1].to_i.to_s rescue '0'
|
||||
crontab_time[1] = time[0].to_i.to_s rescue '0'
|
||||
if self.period == 1 #weekly
|
||||
crontab_time[4] = '0' #every Sunday
|
||||
elsif self.period == 2 #monthly
|
||||
crontab_time[2] = '1' #day 1 of every month
|
||||
end
|
||||
extra_arg = ''
|
||||
if self.rsnapshot_conf_path != DefaultConf
|
||||
extra_arg = " -c #{rsnapshot_conf_path} "
|
||||
end
|
||||
"#{crontab_time.join(' ')} /usr/bin/rsnapshot #{extra_arg}#{period_text}"
|
||||
end
|
||||
def period_text
|
||||
PeriodsTypes[self.period]
|
||||
end
|
||||
def retain_text
|
||||
"retain\t#{self.period_text}\t#{self.retain_count}"
|
||||
end
|
||||
def override_text(contents, org_regex, new_text)
|
||||
exist_flag = false
|
||||
contents = contents.gsub(org_regex).with_index do |s, i|
|
||||
if i == 0
|
||||
exist_flag = true
|
||||
"#{new_text}#{(s[-1] == "\n" ? "\n" : '')}"
|
||||
else
|
||||
"##{s}"
|
||||
end
|
||||
end
|
||||
unless exist_flag
|
||||
contents += "\n#{new_text}"
|
||||
end
|
||||
contents
|
||||
end
|
||||
def gsub_rsnapshot_conf(contents)
|
||||
contents = self.override_text(contents, /^retain\s+[^\n]*(\n|$)/m, self.retain_text)
|
||||
contents = self.override_text(contents, /^snapshot_root\s+[^\n]*(\n|$)/m, self.snapshot_root)
|
||||
contents = self.override_text(contents, /^backup\s+[^\n]*(\n|$)/m, self.backup_path)
|
||||
end
|
||||
def backup_path
|
||||
home_dir = self.backup_dir
|
||||
if home_dir.include?('{{user_name}}')
|
||||
user_name = self.site_server.account
|
||||
home_dir = home_dir.sub('{{user_name}}', user_name)
|
||||
self.backup_dir = home_dir
|
||||
self.save
|
||||
end
|
||||
backup_text = "backup\t#{home_dir}/\t#{self.backup_prefix}"
|
||||
extra_exclude_path = []
|
||||
if self.class.class_variable_defined?(:@@db_backup_paths)
|
||||
extra_exclude_path = @@db_backup_paths.select{|p| p.start_with?(home_dir)}
|
||||
end
|
||||
if self.path.start_with?(home_dir)
|
||||
extra_exclude_path << self.path if extra_exclude_path.exclude?(self.path)
|
||||
end
|
||||
if extra_exclude_path.count != 0
|
||||
tmp = []
|
||||
extra_exclude_path.each do |s|
|
||||
if tmp.count == 0
|
||||
tmp << s
|
||||
else
|
||||
if tmp.exclude?(s)
|
||||
s2 = File.dirname(s)
|
||||
idx = tmp.index{|ss| File.dirname(ss) == s2}
|
||||
if idx
|
||||
tmp[idx] = s2
|
||||
else
|
||||
tmp << s
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
backup_text += "\t#{tmp.map{|p| "exclude=#{p}"}.join(',')}"
|
||||
end
|
||||
backup_text
|
||||
end
|
||||
def snapshot_root
|
||||
"snapshot_root\t#{self.path}"
|
||||
end
|
||||
def self.read_from_crontab_line(crontab_line)
|
||||
if crontab_line.include?('rsnapshot')
|
||||
tmp = crontab_line.split(/\s+[^\s]*rsnapshot\s+/) # ex: ["15 4 * * *", "daily"], ["15 4 * * *", "-c /etc/rsnapshot.conf daily"]
|
||||
if tmp.count == 2
|
||||
crontab_time = tmp[0].split(/\s+/)
|
||||
period_text = tmp[1]
|
||||
rsnapshot_conf_path = DefaultConf
|
||||
if period_text.start_with?('-c')
|
||||
tmp2 = period_text.split(/\s+/)
|
||||
if tmp2.count == 3
|
||||
rsnapshot_conf_path = tmp2[1]
|
||||
period_text = tmp2[2]
|
||||
else
|
||||
period_text = tmp2.last
|
||||
end
|
||||
end
|
||||
if PeriodsTypes.include?(period_text)
|
||||
period = PeriodsTypes.index(period_text)
|
||||
else
|
||||
period = 0
|
||||
end
|
||||
time = "#{crontab_time[1].rjust(2, "0")}:#{crontab_time[0].rjust(2, "0")}"
|
||||
return [time, rsnapshot_conf_path, period]
|
||||
else
|
||||
return nil
|
||||
end
|
||||
else
|
||||
return nil
|
||||
end
|
||||
end
|
||||
def self.clean_crontab_setting(crontab_lines_str)
|
||||
crontab_lines = crontab_lines_str.split("\n")
|
||||
crontab_lines_str = crontab_lines.map do |crontab_line|
|
||||
if crontab_line.include?('rsnapshot')
|
||||
nil
|
||||
else
|
||||
crontab_line
|
||||
end
|
||||
end.compact.join("\n")
|
||||
end
|
||||
def self.init_class_variables(site_server)
|
||||
@@db_backup_paths = SiteServerDbBackup.where(:site_server_id=> site_server.id, :disable=>false).pluck(:path)
|
||||
end
|
||||
def self.write_crontab_setting(site_server, crontab_lines_str)
|
||||
new_crontab_lines = self.where(:site_server_id=> site_server.id, :disable=>false).flat_map{|file_backup| file_backup.to_crontab_script.split("\n")}
|
||||
crontab_lines = crontab_lines_str.split("\n")
|
||||
exists_indices = new_crontab_lines.map do |new_crontab_line|
|
||||
match_reg = ::Regexp.new(new_crontab_line.gsub(/\s+/, '\s+'))
|
||||
crontab_lines.index{|l| l.match(match_reg)}
|
||||
end
|
||||
crontab_lines = crontab_lines.map.with_index do |crontab_line, i|
|
||||
if crontab_line.include?('rsnapshot') && exists_indices.exclude?(i)
|
||||
nil
|
||||
else
|
||||
crontab_line
|
||||
end
|
||||
end
|
||||
exists_indices.each_with_index do |idx, i|
|
||||
if idx.nil?
|
||||
crontab_lines << new_crontab_lines[i]
|
||||
end
|
||||
end
|
||||
crontab_lines_str = crontab_lines.compact.join("\n")
|
||||
end
|
||||
end
|
|
@ -0,0 +1,77 @@
|
|||
<!-- <%= type.classify %> -->
|
||||
<%
|
||||
relation_field = "#{f.object_name}_#{type.pluralize}"
|
||||
records = f.object.send(relation_field)
|
||||
%>
|
||||
<div class="tab-pane fade <%= @active_class %>" id="<%=type%>">
|
||||
<!-- Add -->
|
||||
<div class="add-target">
|
||||
<% records.each do |record| %>
|
||||
<%= f.fields_for relation_field, record do |f| %>
|
||||
<%= render :partial => "backup_form_block", :locals=>{:f=>f} %>
|
||||
<% end %>
|
||||
<% end %>
|
||||
</div>
|
||||
<p class="add-btn">
|
||||
<%= hidden_field_tag "#{relation_field}_count", records.count %>
|
||||
<a class="btn btn-primary add_backup_setting <%=type%>" href="#"><%= t("client_management.add_backup_setting") %></a>
|
||||
</p>
|
||||
</div>
|
||||
<style type="text/css">
|
||||
.block_remove_btn{
|
||||
color: red;
|
||||
margin-right: 0.3em;
|
||||
background: transparent;
|
||||
border: 1px solid red;
|
||||
margin-bottom: 1em;
|
||||
padding: 0.4em 0.8em;
|
||||
cursor: pointer;
|
||||
}
|
||||
.block_remove_btn:hover{
|
||||
font-size: 1.3em;
|
||||
top: 0.3em;
|
||||
position: relative;
|
||||
}
|
||||
.backup_form_block{
|
||||
border: 0.3em solid #666;
|
||||
margin-bottom: 0.5em;
|
||||
padding-bottom: 1em;
|
||||
}
|
||||
.main-forms fieldset .form-actions{
|
||||
background: #fff;
|
||||
}
|
||||
</style>
|
||||
<script type="text/javascript">
|
||||
$(document).ready(function(){
|
||||
$(document).on('click', ".add_backup_setting.<%=type%>", function(){
|
||||
var _this = $(this);
|
||||
var new_id = _this.prev().attr('value');
|
||||
var old_id = new RegExp("new_<%=relation_field%>", "g");
|
||||
var on = $('.language-nav li.active').index();
|
||||
var le = _this.parent('.add-btn').prev('.add-target').children('.start-line').length;
|
||||
_this.prev().attr('value', parseInt(new_id) + 1);
|
||||
_this.parent().siblings('.add-target').append(("<%= escape_javascript(add_attribute 'backup_form_block', f, relation_field) %>").replace(old_id, new_id));
|
||||
_this.parent('.add-btn').prev('.add-target').children('.start-line').eq(le).children('.input-append').find('.tab-content').each(function() {
|
||||
_this.children('.tab-pane').eq(on).addClass('in active').siblings().removeClass('in active');
|
||||
});
|
||||
formTip();
|
||||
});
|
||||
$(document).on('click','.backup_timers',function(){
|
||||
var _this = $(this);
|
||||
_this.not('.hasDatepicker').ui_timepicker({timeFormat: 'HH:mm'});
|
||||
_this.trigger('focus');
|
||||
})
|
||||
$(document).on('click','.block_remove_btn',function(){
|
||||
var backup_form_block = $(this).parents('.backup_form_block').eq(0);
|
||||
if(backup_form_block.hasClass("new_record")){
|
||||
backup_form_block.remove()
|
||||
}else{
|
||||
if(window.confirm('<%=t("client_management.are_you_sure_to_delete")%>')){
|
||||
backup_form_block.addClass('hide');
|
||||
backup_form_block.find('.should_destroy').val('true');
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
</script>
|
|
@ -0,0 +1,45 @@
|
|||
<% object_name_underscore = f.object_name.gsub(/[\[\]]/,'_') %>
|
||||
<div class="backup_form_block <%= f.object.new_record? ? 'new_record' : '' %>">
|
||||
<span class="block_remove_btn">X</span>
|
||||
<div style="clear: both;"></div>
|
||||
<div class="control-group">
|
||||
<%= f.label :disable ,t("client_management.disable"), :class => "control-label muted" %>
|
||||
<div class="controls">
|
||||
<%= f.check_box :disable, :title=> t("client_management.disable") %>
|
||||
</div>
|
||||
</div>
|
||||
<div class="control-group">
|
||||
<% default_backup_time = f.object.fields["backup_time"].options[:default] %>
|
||||
<%= f.label :backup_time ,t("client_management.backup_time"), :class => "control-label muted" %>
|
||||
<div class="controls">
|
||||
<%= f.text_field :backup_time, :placeholder => default_backup_time, :class=>"backup_timers" %>
|
||||
<div class="hint">Eg: <%=default_backup_time%></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="control-group">
|
||||
<% default_path = f.object.fields["path"].options[:default] %>
|
||||
<%= f.label :path ,"Path", :class => "control-label muted" %>
|
||||
<div class="controls">
|
||||
<%= f.text_field :path, :placeholder => "Path(ex: #{default_path})" %>
|
||||
<div class="hint">Eg: <%=default_path%></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="control-group">
|
||||
<%= f.label :period , t("client_management.period"), :class => "control-label muted" %>
|
||||
<div class="controls">
|
||||
<%= f.select :period, f.object.class::PeriodsTypes.map.with_index{|c, i| [t("client_management.period_type.#{c}"),i]} %>
|
||||
</div>
|
||||
</div>
|
||||
<div class="control-group">
|
||||
<% default_retain_count = f.object.fields["retain_count"].options[:default] %>
|
||||
<%= f.label :retain_count , t("client_management.retain_count"), :class => "control-label muted" %>
|
||||
<div class="controls">
|
||||
<%= f.number_field :retain_count, :placeholder => "ex: #{default_retain_count}" %>
|
||||
<div class="hint">Eg: <%=default_retain_count%></div>
|
||||
</div>
|
||||
</div>
|
||||
<% unless f.object.new_record? %>
|
||||
<%= f.hidden_field :id %>
|
||||
<%= f.hidden_field :_destroy, :value => nil, :class => 'should_destroy' %>
|
||||
<% end %>
|
||||
</div>
|
|
@ -68,6 +68,7 @@
|
|||
<a class="btn btn-info" href = "<%= admin_site_panel_edit_server_info_path+"?id=#{site_server.id.to_s}" %>"><%=t(:edit)%></a>
|
||||
<a class="btn btn-danger" href = "#" onclick="if(window.confirm('Do you really want to delete <%=site_server.server_name%>?')) { window.location.href = '<%= admin_site_panel_edit_server_info_path+"?id=#{site_server.id.to_s}&type=delete" %>';}"><%=t(:remove)%></a>
|
||||
<a class="btn btn-primary" href = "<%= admin_site_panel_sites_list_path+"?server_name=#{site_server.server_name}" %>"><%= t('client_management.see_sites') %></a>
|
||||
<a class="btn btn-success" href = "<%= backup_setting_admin_site_panel_path(site_server) %>"><%= t('client_management.backup_setting') %></a>
|
||||
<a class="btn btn-dark btn-inverse detect_sites" href="javascript:void(0)" data-key="<%=site_server.server_name%>">Detect sites</a>
|
||||
<a title="<%=t('client_management.super_manager_management')%>" class="btn btn-primary super_manager_management" href="<%=super_manager_management_admin_site_panel_path(:id=>site_server.id) %>"><%=t('client_management.super_manager_management')%></a>
|
||||
</td>
|
||||
|
|
|
@ -0,0 +1,145 @@
|
|||
<%= form_for @site_server, :url => {:action=>"update_backup_setting"}, :html => {:class => 'form-horizontal main-forms'} do |f| %>
|
||||
<% content_for :page_specific_css do %>
|
||||
<%= stylesheet_link_tag "lib/main-forms" %>
|
||||
<% end %>
|
||||
<% content_for :page_specific_javascript do %>
|
||||
<% end %>
|
||||
<style type="text/css">
|
||||
#info_texts{
|
||||
white-space: pre;
|
||||
}
|
||||
</style>
|
||||
<%#= f.error_messages %>
|
||||
<fieldset>
|
||||
<h3><%= "#{f.object.server_name} (IP: #{f.object.ip}) " %></h3>
|
||||
<div>
|
||||
<% if f.object.need_rewrite_backup_setting %>
|
||||
<a href="javascript:void(0)" class="btn btn-success apply_change_backup_setting" data-id="<%=f.object.id%>"><%= t('client_management.apply_change') %></a>
|
||||
<hr>
|
||||
<% end %>
|
||||
</div>
|
||||
<!-- Input Area -->
|
||||
<div class="input-area">
|
||||
|
||||
<!-- Module Tabs -->
|
||||
<div class="nav-name"><strong><%= t(:type) %></strong></div>
|
||||
<ul class="nav nav-pills module-nav">
|
||||
<li class="active">
|
||||
<a href="#file_backup" data-toggle="tab"><%= t("client_management.file_backup") %></a>
|
||||
</li>
|
||||
<li class="">
|
||||
<a href="#db_backup" data-toggle="tab"><%= t("client_management.db_backup") %></a>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<!-- Module -->
|
||||
<div class="tab-content module-area">
|
||||
<%= render :partial => "backup_form", :locals=>{:f=>f,:type=>"file_backup",:@active_class=>"in active"} %>
|
||||
<%= render :partial => "backup_form", :locals=>{:f=>f,:type=>"db_backup",:@active_class=>""} %>
|
||||
</div>
|
||||
<div class="form-actions">
|
||||
<%= f.submit t('submit'), class: 'btn btn-primary' %>
|
||||
</div>
|
||||
</div>
|
||||
</fieldset>
|
||||
<style type="text/css">
|
||||
.remove_btn{
|
||||
float: left;
|
||||
color: red;
|
||||
line-height: 2rem;
|
||||
cursor: pointer;
|
||||
font-weight: bold;
|
||||
}
|
||||
.remove_btn:hover{
|
||||
font-size: 1.3em;
|
||||
}
|
||||
</style>
|
||||
<script type="text/javascript">
|
||||
var close_info = false;
|
||||
var timeout_id;
|
||||
var status_relation = {"starting":"<span style=\"color: skyblue;\">starting</span>","execing":"<span style=\"color: skyblue;\">execing</span>","detecting":"<span style=\"color: skyblue;\">detecting</span>","error":"<span style=\"color: red;\">error</span>","finish": "<span style=\"color: darkseagreen;\">finish</span>","closed":"<span style=\"color: red;\">closed</span>"};
|
||||
var need_close_info = false;
|
||||
function see_infos(key){
|
||||
key = key || "";
|
||||
if(!close_info){
|
||||
var request = $.post("<%=admin_site_panel_edit_server_info_path%>",{"type":'see_infos',"key":key});
|
||||
request.done(function(data){
|
||||
var infos = request.responseJSON.infos;
|
||||
var status = request.responseJSON.status;
|
||||
if($("#info_texts").length == 0)
|
||||
return infos.join("\n")
|
||||
else{
|
||||
if(status == "")
|
||||
var status_text = "not yet create";
|
||||
else
|
||||
var status_text = status_relation[status];
|
||||
if(!status_text){
|
||||
status_text = "<span style=\"color: skyblue;\">"+status+"</span>";
|
||||
}
|
||||
$("#info_texts").html(status_text+"<div style='clear:both;'></div>"+infos.join("\n"));
|
||||
msg_end.scrollIntoView();
|
||||
if(need_close_info && status != 'execing'){
|
||||
close_info = true;
|
||||
window.setTimeout(function(){
|
||||
if(window.confirm("<%=t('client_management.finished_reload_page')%>")){
|
||||
window.location.reload();
|
||||
}
|
||||
},1000);
|
||||
}else{
|
||||
if(status == 'execing'){
|
||||
need_close_info = true;
|
||||
}
|
||||
timeout_id = window.setTimeout(see_infos(key),1000);
|
||||
}
|
||||
}
|
||||
})
|
||||
}else{
|
||||
window.clearTimeout(timeout_id);
|
||||
}
|
||||
};
|
||||
function show_infos_dialog(key){
|
||||
key = key || "";
|
||||
close_info = true;
|
||||
window.clearTimeout(timeout_id);
|
||||
close_info = false;
|
||||
if($("#dialog-confirm").length == 0){
|
||||
$("#main-wrap").before("<div id='dialog-confirm' title='site infos'>"+
|
||||
"<div style='clear:both;'></div><div id='info_texts'>"+see_infos(key)+"</div><div id='msg_end' style='height:0px; overflow:hidden'></div>"+
|
||||
"</div>");
|
||||
}else{
|
||||
see_infos(key);
|
||||
};
|
||||
$( "#dialog-confirm" ).dialog({
|
||||
resizable: true,
|
||||
minHeight: 100,
|
||||
maxHeight: 400,
|
||||
width: '80%',
|
||||
modal: true,
|
||||
open: function(){
|
||||
$(this).parent().css("top",$(document).height() - $(window).height() + "px");
|
||||
},
|
||||
close: function(){
|
||||
close_info = true;
|
||||
need_close_info = false;
|
||||
},
|
||||
buttons: {
|
||||
"<%= t('client_management.confirm') %>": function(){
|
||||
$( this ).dialog( "close" );
|
||||
},
|
||||
"stop update": function(){
|
||||
close_info = true;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
$(document).ready(function(){
|
||||
$('.apply_change_backup_setting').click(function(){
|
||||
var item = $(this);
|
||||
var item_id = item.attr("data-id");
|
||||
$.post("<%=admin_site_panel_edit_site_path%>",{'id': item_id,'type':'apply_change_backup_setting'}).done(function(){
|
||||
show_infos_dialog("change_backup_setting_" + item_id);
|
||||
});
|
||||
});
|
||||
})
|
||||
</script>
|
||||
<% end %>
|
|
@ -15,6 +15,13 @@ en:
|
|||
confirm_new_password: "Confirm new password"
|
||||
super_manager_management: "Super Manager Management"
|
||||
create_super_manager: Create Super Manager For Site
|
||||
backup_setting: "Backup Setting"
|
||||
add_backup_setting: "Add Backup Setting"
|
||||
file_backup: "File Backup"
|
||||
db_backup: "DB Backup"
|
||||
backup_time: "Backup Time"
|
||||
period: "Period"
|
||||
retain_count: "Retain Count"
|
||||
enable_api: Enable API
|
||||
api_key: API Key
|
||||
setting: Setting
|
||||
|
|
|
@ -15,6 +15,13 @@ zh_tw:
|
|||
confirm_new_password: "確認新密碼"
|
||||
super_manager_management: "管理網站超級管理者"
|
||||
create_super_manager: 創建網站超級管理者
|
||||
backup_setting: "備份設定"
|
||||
add_backup_setting: "新增備份設定"
|
||||
file_backup: "檔案備份"
|
||||
db_backup: "資料庫備份"
|
||||
backup_time: "備份時間"
|
||||
period: "週期"
|
||||
retain_count: "保留"
|
||||
enable_api: 開啟API
|
||||
api_key: API Key
|
||||
setting: 設定
|
||||
|
|
|
@ -68,6 +68,9 @@ Rails.application.routes.draw do
|
|||
patch 'create_cert'
|
||||
end
|
||||
member do
|
||||
get 'backup_setting'
|
||||
post 'update_backup_setting'
|
||||
patch 'update_backup_setting'
|
||||
get "super_manager_management"
|
||||
patch "update_super_manager_management"
|
||||
get "super_manager_management_for_site"
|
||||
|
|
|
@ -0,0 +1,96 @@
|
|||
require 'net/ssh'
|
||||
require 'pathname'
|
||||
require 'json'
|
||||
require 'base64'
|
||||
namespace :exec_commands do
|
||||
desc "Change Server Backup Setting Script"
|
||||
task :change_backup_setting,[:site_server_id] => :environment do |task,args|
|
||||
if args.site_server_id.present?
|
||||
site_server = SiteServer.find(args.site_server_id)
|
||||
else
|
||||
raise StandardError.new('Please Specify Server ID!')
|
||||
end
|
||||
thread_key = "change_backup_setting_#{site_server.id}"
|
||||
@thread = Multithread.where(:key=>thread_key).first
|
||||
begin
|
||||
if @thread.nil?
|
||||
@thread = Multithread.create(:key=>thread_key,:status=>{"infos"=>[],"status"=>"execing"})
|
||||
else
|
||||
@thread.update(:status=>{"infos"=>[],"status"=>"execing"})
|
||||
end
|
||||
ip = site_server.ip
|
||||
user = site_server.account
|
||||
password = site_server.password
|
||||
@password = password
|
||||
begin
|
||||
Net::SSH.start(ip , user , password: password) do |ssh|
|
||||
end
|
||||
rescue Net::SSH::HostKeyMismatch
|
||||
system("ssh-keygen -f \"$HOME/.ssh/known_hosts\" -R #{ip}")
|
||||
rescue Errno::ENOTTY
|
||||
system("ssh-add \"$HOME/.ssh/id_rsa\"")
|
||||
end
|
||||
Net::SSH.start(ip , user , password: password) do |ssh|
|
||||
@no_stdout = true
|
||||
crontab_lines_str = exec_ssh_command_by_sudo_and_see_output(ssh,"sudo -p 'sudo password:' crontab -l", false, true)
|
||||
if site_server.site_server_file_backups.count != 0
|
||||
SiteServerFileBackup.init_class_variables(site_server)
|
||||
rsnapshot_conf_default = SiteServerFileBackup::DefaultConf
|
||||
rsnapshot_conf_exist = check_file_exist_for_ssh(ssh, rsnapshot_conf_default)
|
||||
update_thread_infos_for_exec("Checking file backups config...")
|
||||
if rsnapshot_conf_exist
|
||||
rsnapshot_conf_contents = read_file_for_ssh(ssh, rsnapshot_conf_default)
|
||||
else
|
||||
rsnapshot_sample_conf = File.expand_path("../../../rsnapshot_sample.conf", __FILE__)
|
||||
rsnapshot_conf_contents = File.read(rsnapshot_sample_conf)
|
||||
write_file_for_ssh(ssh, rsnapshot_conf_default, rsnapshot_conf_contents)
|
||||
end
|
||||
site_server.site_server_file_backups.each do |file_backup|
|
||||
rsnapshot_conf_path = file_backup.rsnapshot_conf_path
|
||||
if check_file_exist_for_ssh(ssh, rsnapshot_conf_path)
|
||||
tmp = read_file_for_ssh(ssh, rsnapshot_conf_path)
|
||||
else
|
||||
tmp = rsnapshot_conf_contents.clone
|
||||
end
|
||||
tmp = file_backup.gsub_rsnapshot_conf(tmp)
|
||||
write_file_for_ssh(ssh, rsnapshot_conf_path, tmp)
|
||||
mkdir_for_ssh(ssh, file_backup.path)
|
||||
end
|
||||
update_thread_infos_for_exec("Finish writing file backups config!")
|
||||
end
|
||||
site_server.site_server_db_backups do |db_backup|
|
||||
mkdir_for_ssh(ssh, db_backup.path)
|
||||
end
|
||||
crontab_lines_str = SiteServerFileBackup.write_crontab_setting(site_server, crontab_lines_str)
|
||||
crontab_lines_str = SiteServerDbBackup.write_crontab_setting(site_server, crontab_lines_str)
|
||||
write_crontab_for_ssh(ssh, crontab_lines_str)
|
||||
update_thread_infos_for_exec("Finish setting backups!")
|
||||
end
|
||||
site_server.site_server_file_backups.update_all(:need_rewrite=>false)
|
||||
site_server.site_server_db_backups.update_all(:need_rewrite=>false)
|
||||
site_server.update(:need_rewrite_backup_setting=>false)
|
||||
@thread.update(:status=>@thread.status.merge({"status"=>"finish"}))
|
||||
rescue => e
|
||||
@thread.update(:status=>{"infos"=>@thread.status["infos"].push(e.message),"status"=>"error"})
|
||||
@thread.update(:status=>{"infos"=>@thread.status["infos"].push(e.backtrace.join("\n")),"status"=>"error"})
|
||||
end
|
||||
end
|
||||
def mkdir_for_ssh(ssh, dir)
|
||||
exec_ssh_command_by_sudo_and_see_output(ssh,"sudo -p 'sudo password:' sh -c \"mkdir -p #{dir}\"", false)
|
||||
end
|
||||
def write_crontab_for_ssh(ssh, crontab_lines_str)
|
||||
exec_ssh_command_by_sudo_and_see_output(ssh,"x='#{crontab_lines_str.gsub("\n", '\n').gsub("'","'\"'\"'")}'; sudo -p 'sudo password:' sh -c \"echo '$x'| crontab -\"", false)
|
||||
end
|
||||
def read_file_for_ssh(ssh, file_name)
|
||||
exec_ssh_command_by_sudo_and_see_output(ssh,"sudo -p 'sudo password:' sh -c \"cat #{file_name}\"", false, true)
|
||||
end
|
||||
def write_file_for_ssh(ssh, file_name, contents)
|
||||
exec_ssh_command_by_sudo_and_see_output(ssh,"x='#{contents.gsub("\n", '\n').gsub("'","'\"'\"'")}';sudo -p 'sudo password:' sh -c \"echo '$x' > #{file_name}\"", false)
|
||||
end
|
||||
def copy_file_for_ssh(ssh, src, dst)
|
||||
exec_ssh_command_by_sudo_and_see_output(ssh,"sudo -p 'sudo password:' bash -l -c 'cp #{src} #{dst}'", 1)
|
||||
end
|
||||
def check_file_exist_for_ssh(ssh, file_name)
|
||||
exec_ssh_command_by_sudo_and_see_output(ssh,"sudo -p 'sudo password:' bash -l -c 'if [ -e #{file_name} ]; then echo 1; else echo 0; fi'", false, true).include?('1')
|
||||
end
|
||||
end
|
|
@ -164,6 +164,79 @@ namespace :create_site do
|
|||
end
|
||||
end
|
||||
end
|
||||
update_thread_infos("Detecting Backup Setting on #{site_server.server_name}...")
|
||||
crontab_lines = exec_ssh_command_by_sudo_and_see_output(ssh,"sudo -p 'sudo password:' crontab -l;crontab -l",false,false)
|
||||
file_backups = crontab_lines.select{|s| s.match(/^\s*[^\s#]/) && s.include?('rsnapshot')}.map{|s| SiteServerFileBackup.read_from_crontab_line(s)}.compact
|
||||
rsnapshot_confs_path = ([SiteServerFileBackup::DefaultConf] + file_backups.map{|time, rsnapshot_conf_path, period| rsnapshot_conf_path}).uniq
|
||||
retain_settings = {}
|
||||
backup_dir_info = {}
|
||||
snapshot_root_info = {}
|
||||
rsnapshot_confs_path.each do |rsnapshot_conf_path|
|
||||
backup_retain_lines = exec_ssh_command_by_sudo_and_see_output(ssh,"sudo -p 'sudo password:' grep -E '^\\s*retain\\s+' #{rsnapshot_conf_path}",false,false).map{|s| s.strip}.select{|s| s.present?}
|
||||
backup_retain_lines = backup_retain_lines
|
||||
next if backup_retain_lines.blank?
|
||||
part_retain_settings = backup_retain_lines.map{|s| (s.strip.split(/\s+/)[1..2] rescue nil)}.compact.to_h
|
||||
retain_settings[rsnapshot_conf_path] = part_retain_settings
|
||||
|
||||
backup_dir_subinfo = exec_ssh_command_by_sudo_and_see_output(ssh,"sudo -p 'sudo password:' grep -E '^\s*backup' #{rsnapshot_conf_path}",false,false).map{|s| s.strip}.select{|s| s.present?} # ex: ["backup\t/home/rulingcom\tlocalhost/"]
|
||||
backup_dir_info[rsnapshot_conf_path] = backup_dir_subinfo.map{|s| s.strip.split(/\s+/)[1..2]}
|
||||
|
||||
snapshot_root_subinfo = exec_ssh_command_by_sudo_and_see_output(ssh,"sudo -p 'sudo password:' grep -E '^\s*snapshot_root' #{rsnapshot_conf_path}",false,false).map{|s| s.strip}.select{|s| s.present?}.last # ex: "snapshot_root\t/home/backup/orbit"
|
||||
snapshot_root_info[rsnapshot_conf_path] = snapshot_root_subinfo.strip.split(/\s+/)[1] rescue nil #only single snapshot_root in a conf
|
||||
end
|
||||
file_backups_group = file_backups.group_by{|time, rsnapshot_conf_path, period| rsnapshot_conf_path}
|
||||
file_backup_ids = []
|
||||
retain_settings.each do |rsnapshot_conf_path, part_retain_settings|
|
||||
path = snapshot_root_info[rsnapshot_conf_path]
|
||||
if path.nil?
|
||||
path = '/home/backup/orbit'
|
||||
end
|
||||
backup_dir_subinfo = backup_dir_info[rsnapshot_conf_path]
|
||||
tmp = file_backups_group[rsnapshot_conf_path]
|
||||
unused_period = part_retain_settings.map{|period_text, retain_count| SiteServerFileBackup::PeriodsTypes.index(period_text).to_i} - tmp.map{|time, rsnapshot_conf_path, period| period}
|
||||
unused_retain_settings = unused_period.map{|period| [period, part_retain_settings[SiteServerFileBackup::PeriodsTypes[period]]]}
|
||||
backup_dir_subinfo.each do |backup_dir, backup_prefix|
|
||||
unused_retain_settings.each do |period, retain_count|
|
||||
file_backup_data = {:site_server=>@site_server, :disable=>true, :period=>period, :path=>path, :retain_count=>retain_count, :rsnapshot_conf_path=>rsnapshot_conf_path, :backup_dir=>backup_dir, :backup_prefix=>backup_prefix}
|
||||
file_backup = SiteServerFileBackup.where(file_backup_data.except(:disable)).first
|
||||
if file_backup.nil?
|
||||
file_backup = SiteServerFileBackup.create(file_backup_data)
|
||||
else
|
||||
file_backup.update_attributes(file_backup_data)
|
||||
end
|
||||
file_backup_ids << file_backup.id
|
||||
end
|
||||
tmp.each do |time, rsnapshot_conf_path, period|
|
||||
retain_count = part_retain_settings[SiteServerFileBackup::PeriodsTypes[period]]
|
||||
if retain_count
|
||||
file_backup_data = {:site_server=>@site_server, :disable=>false, :backup_time=>time, :path=>path, :period=>period, :retain_count=>retain_count, :rsnapshot_conf_path=>rsnapshot_conf_path, :backup_dir=>backup_dir, :backup_prefix=>backup_prefix}
|
||||
file_backup = SiteServerFileBackup.where(file_backup_data.except(:disable)).first
|
||||
if file_backup.nil?
|
||||
file_backup = SiteServerFileBackup.create(file_backup_data)
|
||||
else
|
||||
file_backup.update_attributes(file_backup_data)
|
||||
end
|
||||
file_backup_ids << file_backup.id
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
SiteServerFileBackup.where(:id.in=>file_backup_ids).update_all(:need_rewrite=>false)
|
||||
db_backup_ids = []
|
||||
db_backup_infos = crontab_lines.select{|s| s.match(/^\s*[^\s#]/) && s.include?('mongodump')}.map{|s| SiteServerDbBackup.read_from_crontab_line(s, crontab_lines)}.compact
|
||||
db_backup_infos.each do |backup_time, path, period, retain_count|
|
||||
next if backup_time.nil?
|
||||
db_backup_data = {:site_server=>@site_server, :disable=>false, :period=>period, :path=>path, :backup_time=>backup_time, :retain_count=>retain_count}
|
||||
db_backup = SiteServerDbBackup.where(db_backup_data.except(:disable)).first
|
||||
if db_backup.nil?
|
||||
db_backup = SiteServerDbBackup.create(db_backup_data)
|
||||
else
|
||||
db_backup.update_attributes(db_backup_data)
|
||||
end
|
||||
db_backup_ids << db_backup.id
|
||||
end
|
||||
SiteServerDbBackup.where(:id.in=>db_backup_ids).update_all(:need_rewrite=>false)
|
||||
update_thread_infos("Finish detecting Backup Setting on #{site_server.server_name}!")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -0,0 +1,238 @@
|
|||
#################################################
|
||||
# rsnapshot.conf - rsnapshot configuration file #
|
||||
#################################################
|
||||
# #
|
||||
# PLEASE BE AWARE OF THE FOLLOWING RULE: #
|
||||
# #
|
||||
# This file requires tabs between elements #
|
||||
# #
|
||||
#################################################
|
||||
|
||||
#######################
|
||||
# CONFIG FILE VERSION #
|
||||
#######################
|
||||
|
||||
config_version 1.2
|
||||
|
||||
###########################
|
||||
# SNAPSHOT ROOT DIRECTORY #
|
||||
###########################
|
||||
|
||||
# All snapshots will be stored under this root directory.
|
||||
#
|
||||
#snapshot_root /var/cache/rsnapshot/
|
||||
snapshot_root /home/backup/orbit
|
||||
|
||||
# If no_create_root is enabled, rsnapshot will not automatically create the
|
||||
# snapshot_root directory. This is particularly useful if you are backing
|
||||
# up to removable media, such as a FireWire or USB drive.
|
||||
#
|
||||
#no_create_root 1
|
||||
|
||||
#################################
|
||||
# EXTERNAL PROGRAM DEPENDENCIES #
|
||||
#################################
|
||||
|
||||
# LINUX USERS: Be sure to uncomment "cmd_cp". This gives you extra features.
|
||||
# EVERYONE ELSE: Leave "cmd_cp" commented out for compatibility.
|
||||
#
|
||||
# See the README file or the man page for more details.
|
||||
#
|
||||
cmd_cp /bin/cp
|
||||
|
||||
# uncomment this to use the rm program instead of the built-in perl routine.
|
||||
#
|
||||
cmd_rm /bin/rm
|
||||
# rsync must be enabled for anything to work. This is the only command that
|
||||
# must be enabled.
|
||||
#
|
||||
cmd_rsync /usr/bin/rsync
|
||||
|
||||
# Uncomment this to enable remote ssh backups over rsync.
|
||||
#
|
||||
#cmd_ssh /usr/bin/ssh
|
||||
|
||||
# Comment this out to disable syslog support.
|
||||
#
|
||||
cmd_logger /usr/bin/logger
|
||||
|
||||
# Uncomment this to specify the path to "du" for disk usage checks.
|
||||
# If you have an older version of "du", you may also want to check the
|
||||
# "du_args" parameter below.
|
||||
#
|
||||
#cmd_du /usr/bin/du
|
||||
|
||||
# Uncomment this to specify the path to rsnapshot-diff.
|
||||
#
|
||||
#cmd_rsnapshot_diff /usr/bin/rsnapshot-diff
|
||||
|
||||
# Specify the path to a script (and any optional arguments) to run right
|
||||
# before rsnapshot syncs files
|
||||
#
|
||||
#cmd_preexec /path/to/preexec/script
|
||||
|
||||
# Specify the path to a script (and any optional arguments) to run right
|
||||
# after rsnapshot syncs files
|
||||
#
|
||||
#cmd_postexec /path/to/postexec/script
|
||||
|
||||
# Paths to lvcreate, lvremove, mount and umount commands, for use with
|
||||
# Linux LVMs.
|
||||
#
|
||||
#linux_lvm_cmd_lvcreate /sbin/lvcreate
|
||||
#linux_lvm_cmd_lvremove /sbin/lvremove
|
||||
#linux_lvm_cmd_mount /bin/mount
|
||||
#linux_lvm_cmd_umount /bin/umount
|
||||
|
||||
#########################################
|
||||
# BACKUP LEVELS / INTERVALS #
|
||||
# Must be unique and in ascending order #
|
||||
# e.g. alpha, beta, gamma, etc. #
|
||||
#########################################
|
||||
|
||||
#retain alpha 6
|
||||
#retain beta 7
|
||||
#retain gamma 4
|
||||
#retain delta 3
|
||||
retain daily 7
|
||||
|
||||
############################################
|
||||
# GLOBAL OPTIONS #
|
||||
# All are optional, with sensible defaults #
|
||||
############################################
|
||||
# Verbose level, 1 through 5.
|
||||
# 1 Quiet Print fatal errors only
|
||||
# 2 Default Print errors and warnings only
|
||||
# 3 Verbose Show equivalent shell commands being executed
|
||||
# 4 Extra Verbose Show extra verbose information
|
||||
# 5 Debug mode Everything
|
||||
#
|
||||
verbose 2
|
||||
# Same as "verbose" above, but controls the amount of data sent to the
|
||||
# logfile, if one is being used. The default is 3.
|
||||
# If you want the rsync output, you have to set it to 4
|
||||
#
|
||||
loglevel 3
|
||||
# If you enable this, data will be written to the file you specify. The
|
||||
# amount of data written is controlled by the "loglevel" parameter.
|
||||
#
|
||||
#logfile /var/log/rsnapshot.log
|
||||
|
||||
# If enabled, rsnapshot will write a lockfile to prevent two instances
|
||||
# from running simultaneously (and messing up the snapshot_root).
|
||||
# If you enable this, make sure the lockfile directory is not world
|
||||
# writable. Otherwise anyone can prevent the program from running.
|
||||
#
|
||||
lockfile /var/run/rsnapshot.pid
|
||||
|
||||
# By default, rsnapshot check lockfile, check if PID is running
|
||||
# and if not, consider lockfile as stale, then start
|
||||
# Enabling this stop rsnapshot if PID in lockfile is not running
|
||||
#
|
||||
#stop_on_stale_lockfile 0
|
||||
# Default rsync args. All rsync commands have at least these options set.
|
||||
#
|
||||
#rsync_short_args -a
|
||||
#rsync_long_args --delete --numeric-ids --relative --delete-excluded
|
||||
# ssh has no args passed by default, but you can specify some here.
|
||||
#
|
||||
#ssh_args -p 22
|
||||
|
||||
# Default arguments for the "du" program (for disk space reporting).
|
||||
# The GNU version of "du" is preferred. See the man page for more details.
|
||||
# If your version of "du" doesnt support the -h flag, try -k flag instead.n#n#du_args -cshnn# If this is enabled, rsync wont span filesystem partitions within a
|
||||
# backup point. This essentially passes the -x option to rsync.
|
||||
# The default is 0 (off).
|
||||
#
|
||||
#one_fs 0
|
||||
|
||||
# The include and exclude parameters, if enabled, simply get passed directly
|
||||
# to rsync. If you have multiple include/exclude patterns, put each one on a
|
||||
# separate line. Please look up the --include and --exclude options in the
|
||||
# rsync man page for more details on how to specify file name patterns.
|
||||
#
|
||||
#include ???
|
||||
#include ???
|
||||
#exclude ???
|
||||
#exclude ???
|
||||
|
||||
# The include_file and exclude_file parameters, if enabled, simply get
|
||||
# passed directly to rsync. Please look up the --include-from and
|
||||
# --exclude-from options in the rsync man page for more details.
|
||||
#
|
||||
#include_file /path/to/include/file
|
||||
#exclude_file /path/to/exclude/file
|
||||
# If your version of rsync supports --link-dest, consider enabling this.
|
||||
# This is the best way to support special files (FIFOs, etc) cross-platform.
|
||||
# The default is 0 (off).
|
||||
#
|
||||
#link_dest 0
|
||||
|
||||
# When sync_first is enabled, it changes the default behaviour of rsnapshot.
|
||||
# Normally, when rsnapshot is called with its lowest interval
|
||||
# (i.e.: "rsnapshot alpha"), it will sync files AND rotate the lowest
|
||||
# intervals. With sync_first enabled, "rsnapshot sync" handles the file sync,
|
||||
# and all interval calls simply rotate files. See the man page for more
|
||||
# details. The default is 0 (off).
|
||||
#
|
||||
#sync_first 0
|
||||
# If enabled, rsnapshot will move the oldest directory for each interval
|
||||
# to [interval_name].delete, then it will remove the lockfile and delete
|
||||
# that directory just before it exits. The default is 0 (off).
|
||||
#
|
||||
#use_lazy_deletes 0
|
||||
|
||||
# Number of rsync re-tries. If you experience any network problems or
|
||||
# network card issues that tend to cause ssh to fail with errors like
|
||||
# "Corrupted MAC on input", for example, set this to a non-zero value
|
||||
# to have the rsync operation re-tried.
|
||||
#
|
||||
#rsync_numtries 0
|
||||
# LVM parameters. Used to backup with creating lvm snapshot before backup
|
||||
# and removing it after. This should ensure consistency of data in some special
|
||||
# cases
|
||||
#
|
||||
# LVM snapshot(s) size (lvcreate --size option).
|
||||
#
|
||||
#linux_lvm_snapshotsize 100M
|
||||
# Name to be used when creating the LVM logical volume snapshot(s).
|
||||
#
|
||||
#linux_lvm_snapshotname rsnapshot
|
||||
|
||||
# Path to the LVM Volume Groups.
|
||||
#
|
||||
#linux_lvm_vgpath /dev
|
||||
# Mount point to use to temporarily mount the snapshot(s).
|
||||
#
|
||||
#linux_lvm_mountpath /path/to/mount/lvm/snapshot/during/backup
|
||||
|
||||
###############################
|
||||
### BACKUP POINTS / SCRIPTS ###
|
||||
###############################
|
||||
|
||||
# LOCALHOST
|
||||
backup /home/rulingcom/ localhost/
|
||||
#backup /home/ localhost/
|
||||
#backup /etc/ localhost/
|
||||
#backup /usr/local/ localhost/
|
||||
#backup /var/log/rsnapshot localhost/
|
||||
#backup /etc/passwd localhost/
|
||||
#backup /home/foo/My Documents/ localhost/
|
||||
#backup /foo/bar/ localhost/ one_fs=1,rsync_short_args=-urltvpog
|
||||
#backup_script /usr/local/bin/backup_pgsql.sh localhost/postgres/
|
||||
# You must set linux_lvm_* parameters below before using lvm snapshots
|
||||
#backup lvm://vg0/xen-home/ lvm-vg0/xen-home/
|
||||
# EXAMPLE.COM
|
||||
#backup_exec /bin/date "+ backup of example.com started at %c"
|
||||
#backup root@example.com:/home/ example.com/ +rsync_long_args=--bwlimit=16,exclude=core
|
||||
#backup root@example.com:/etc/ example.com/ exclude=mtab,exclude=core
|
||||
#backup_exec ssh root@example.com "mysqldump -A > /var/db/dump/mysql.sql"
|
||||
#backup root@example.com:/var/db/dump/ example.com/
|
||||
#backup_exec /bin/date "+ backup of example.com ended at %c"
|
||||
|
||||
# CVS.SOURCEFORGE.NET
|
||||
#backup_script /usr/local/bin/backup_rsnapshot_cvsroot.sh rsnapshot.cvs.sourceforge.net/
|
||||
|
||||
# RSYNC.SAMBA.ORG
|
||||
#backup rsync://rsync.samba.org/rsyncftp/ rsync.samba.org/rsyncftp/
|
||||
|
Loading…
Reference in New Issue