目的
社内で色々なバックアップをしていましたが、個別にbashを書いていてメンテナンスしにくいと思ったので、Rubyでまとめてみました。
仕様
- バックアップしたい対象はそれぞれのサーバーで事前に準備(pg_dump等)
- バックアップを集約するサーバーで今回のプログラムを実行
- scpかrsyncのコピーコマンドとバックアップサーバー内の古いバックアップの削除コマンドをサポート
- コマンドの実行に失敗した場合はslackに通知
- バックアップの設定はyamlファイルで管理
- yamlファイルはERBを通して実行する
プログラム
Gemfile
# frozen_string_literal: true
source "https://rubygems.org"
git_source(:github) {|repo_name| "https://github.com/#{repo_name}" }
gem 'slack-ruby-client'
gem 'systemu'
gem 'hashie'
backup.rb
require 'systemu'
require 'slack-ruby-client'
require 'hashie'
require 'erb'
require 'yaml'
require 'fileutils'
def notification(config, content)
Slack.configure do |cfg|
cfg.token = config.slack.token
end
client = Slack::Web::Client.new
client.auth_test
text = "#{config.name}\n#{content}"
client.chat_postMessage(channel: config.slack.channel, text: text, as_user: true)
end
def read_config(path)
Hashie::Mash.new(YAML.load(ERB.new(File.read(path)).result))
end
def scp(command)
status, stdout, stderr = systemu "/usr/bin/scp #{command.from} #{command.to}"
raise "fail scp" unless status.success?
end
def rsync(command)
status, stdout, stderr = systemu "/usr/bin/rsync -azq --delete #{command.from} #{command.to}"
raise "fail rsync" unless status.success?
end
def clean(command)
ymd = (Date.today - command.days ).strftime("%Y%m%d")
re = Regexp.new(command.name_match)
Dir::entries(command.dir).each do |it|
if re =~ it
FileUtils.rm_rf(File.join(command.dir, it)) if $1 < ymd
end
end
end
config = read_config(ARGV[0])
begin
config.commands.each do |command|
case command.type
when 'scp' then
scp(command)
when 'rsync' then
rsync(command)
when 'clean' then
clean(command)
end
end
rescue Exception => e
# エラーのfull_messageにtermcapが入るのを防いでいる
$stderr = $stdout
notification(config, e.full_message)
#puts e.full_message
end
webserver.yaml
name: webserver
slack:
token: <%= ENV['SLACK_API_TOKEN'] %>
channel: "#backup"
commands:
- type: scp
from: vps01:/home/me/backup/<%= Date.today.strftime("%Y%m%d") %>.tar.bz2
to: /home/me/backup/webserver
- type: clean
name_match: ^(\d\d\d\d\d\d\d\d)\.
dir: /home/me/backup/webserver
days: 5
git.yaml
name: git backup
slack:
token: <%= ENV['SLACK_API_TOKEN'] %>
channel: "#backup"
commands:
- type: rsync
from: vps01:/var/git/
to: /home/me/backup/git/<%= Date.today.strftime("%Y%m%d") %>
- type: clean
name_match: ^(\d\d\d\d\d\d\d\d)$
dir: /home/me/backup/git
days: 40
SLACK_API_TOKEN=xxxx bundle exec ruby backup.sh webserver.yaml