Backup 젬과 Whenever 젬을 이용한 서버 백업 자동화

레일스 프로젝트를 원격 서버로 배포후 제대로 동작하는 것이 확인되면 우선적으로 데이터베이스와 사용자들이 업로드한 파일들을 주기적으로 백업해야 한다. 여러가지 방법이 있지만 이 글에서는 가장 흔히들 사용하는 backup 젬과, crontab 스크립트를 편리하게 작업할 수 있게 해 주는, whenever 젬을 이용하는 방법에 대해서 필자의 짧은 경험과 함께 소개할 것이다.

(1) Backup 젬

backup 젬은 프로젝트의 gemfile로 설치하지 않고 직접 원격 서버에서 설치한다. 물론 레일스 애플리케이션이 서비스되는 서버에는 이미 루비환경이 설치되어 있게 때문에 ssh로 접속한 후 아래와 같은 명령으로 간단하게 설치할 수 있다.

$ gem install backup 

이제 커맨드라인에서 backup 명령을 실행하면 아래와 같이 사용법에 대한 도움말을 볼 수 있다.

$ backup Commands: backup check 
# Check for configuration errors or warnings backup generate:config 
# Generates the main Backup configuration file backup generate:model -t, --trigger=TRIGGER 
# Generates a Backup model file. backup help [COMMAND] 
# Describe available commands or one specific command backup perform -t, --triggers, --trigger=TRIGGER 
# Performs the backup for the specified trigger(s). backup version 
# Display installed Backup version

backup에서는 model이라는 용어를 사용하여 하나의 백업 작업을 정의한다. 따라서 위의 5번째 라인의 명령과 몇가지 옵션을 추가해서 아래와 같이 백업작업을 정의한다.

$ backup generate:model --trigger=daily_db_backup --databases='mysql' --storages='local' --compressor='gzip' --notifiers='mail' 
Generated configuration file: '/home/[user_account]/Backup/config.rb'. 
Generated model file: '/home/[user_account]/Backup/models/daily_db_backup.rb'. 

옵션설명
--trigger : 모델명을 지정한다.
--databases : 데이터베이스명을 지정한다. ex) MySQL, PostgreSQL, MongoDB, Redis, Riak, SQLite
--storages : 백업저장 위치를 지정한다. ex) Amazon S3, Rackspace Cloud Files, Ninefold, Dropbox, FTP, SFTP, SCP, RSync, Local
--compressor : 데이터 압축프로그램을 지정한다. ex) Gzip, Bzip2, xz
--notifiers : 백업작업 완료시 결과를 알려주는 툴을 지정한다. ex) Email (SMTP, Sendmail, Exim and File delivery), Twitter, Campfire, Prowl, Hipchat, Pushover, Nagios, HTTP POST (compatible with a variety of services), Zabbix

위의 명령 실행결과 Backup이라는 폴더에 아래와 같은 파일들이 생성된다.

$ tree Backup 
Backup 
├── config.rb 
└── models 
└── daily_db_backup.rb 
1 directory, 2 files 

모델 파일(daily_db_backup.rb)을 열고 자신의 서버 환경에 맞게 옵션을 변경한다.

# encoding: utf-8 

## 
# Backup Generated: daily_db_backup 
# Once configured, you can run the backup with the following command: 
# 
# $ backup perform -t daily_db_backup [-c ] 
# 
# For more information about Backup's components, see the documentation at: 
# http://backup.github.io/backup 
# 
Model.new(:daily_db_backup, 'Description for daily_db_backup') do

  ## 
  # MySQL [Database] 
  # 
  database MySQL do |db| 
    # To dump all databases, set \`db.name = :all\` (or leave blank) 
    db.name = "my_database_name" 
    db.username = "my_username" 
    db.password = "my_password" 
    db.host = "localhost" 
    db.port = 3306 
    # db.socket = "/tmp/mysql.sock" 
    # Note: when using \`skip_tables\` with the \`db.name = :all\` option, 
    # table names should be prefixed with a database name. 
    # e.g. ["db_name.table_to_skip", ...] 
    # db.skip_tables = ["skip", "these", "tables"] 
    # db.only_tables = ["only", "these", "tables"] 
    db.additional_options = ["--quick", "--single-transaction"] 
  end

  ## 
  # Local (Copy) [Storage] 
  # 
  store_with Local do |local| 
    local.path = "~/backups/" 
    local.keep = 5 
  end 

  ## 
  # Gzip [Compressor] 
  # 
  compress_with Gzip 

  ## 
  # Mail [Notifier] 
  # 
  # The default delivery method for Mail Notifiers is 'SMTP'. 
  # See the documentation for other delivery options. 
  # 
  notify_by Mail do |mail| 
    mail.on_success = true 
    mail.on_warning = true 
    mail.on_failure = true 
    mail.from = "sender@email.com" 
    mail.to = "receiver@email.com" 
    mail.address = "smtp.gmail.com" 
    mail.port = 587 
    mail.domain = "your.host.name" 
    mail.user_name = "sender@email.com" 
    mail.password = "my_password" 
    mail.authentication = "plain" 
    mail.encryption = :starttls 
  end 
end 

위의 소스 코드에서 19번 라인의 db.name 속성값은 18번 라인의 코멘트와 같이 :all을 지정하여 모든 데이터베이스를 한꺼번에 백업할 수도 있다. 여기서는 불필요한 24번 코드라인을 코멘트 처리하였고, 28, 29번 코드라인은 전체 데이터베이스를 백업할 것이기 때문에 사용할 필요가 없어서 코멘트 처리하였다. 여기서는 project1_production이라는 데이터베이스를 백업하는 것으로 가정한다. 따라서 db.name 값을 project1_production으로 지정한다. 위에서 설명한 바와 같이 모델을 작성하는 커맨드라인을 다시 한번 상기해 보자.

$ backup generate:model --trigger=daily_db_backup --databases='mysql' --storages='local' --compressor='gzip' --notifiers='mail' 

--storages='local'은 백업을 저장할 매체를 지정하는 것인데, 여기서는 local, 즉, 동일한 서버에 저장하겠다는 의미이다. 언급한 바와 같이 scp를 지정하여 다른 서버로 백업본을 저장할 수도 있다. --nofifiers='mail'은 백업 결과를 알려주는 매체를 지정한다. mail로 지정하면, 백업 결과를 이메일로 발송해 준다. 리눅스 서버의 sendmail 기능을 이용하면 구글 SMTP 서비스를 사용하지 않아도 된다. 위의 모델 파일에서 59~65 코드라인을 코멘트 처리하고 아래의 코드라인을 추가한다.

mail.delivery_method = :sendmail

이제부터는 백업이 실행되면 서버의 sendmail 기능을 이용하여 메일을 발송하게 된다. 지금까지 변경한 내용을 반영한 모델 파일의 내용은 아래와 같다.

# encoding: utf-8 
## 
# Backup Generated: daily_db_backup 
# Once configured, you can run the backup with the following command: 
# 
# $ backup perform -t daily_db_backup [-c ] 
# 
# For more information about Backup's components, see the documentation at: 
# http://backup.github.io/backup 
# 
Model.new(:daily_db_backup, 'backups project1_production database') do 

  ## 
  # MySQL [Database] 
  # 
  database MySQL do |db| 
    # To dump all databases, set \`db.name = :all\` (or leave blank) 
    db.name = "project1_production"  
    db.username = "[account-name]" 
    db.password = "[account-pass]" 
    db.host = "localhost" 
    db.port = 3306 
    db.additional_options = ["--quick", "--single-transaction"] 
  end 

  ## 
  # Local (Copy) [Storage] 
  # 
  store_with Local do |local| 
    local.path = "~/backups/" 
    local.keep = 5 
  end 

  ## 
  # Gzip [Compressor] 
  # 
  compress_with Gzip 

  ## 
  # Mail [Notifier] 
  # 
  # The default delivery method for Mail Notifiers is 'SMTP'. 
  # See the documentation for other delivery options. 
  # 
  notify_by Mail do |mail| 
    mail.on_success = true 
    mail.on_warning = true 
    mail.on_failure = true 
    mail.delivery_method = :sendmail 
    mail.from = "sender@email.com" 
    mail.to = "receiver@email.com" 
  end 
end 

자, 이제, 서버의 커맨드라인에서 아래와 같이 백업 명령을 실행해 보자.

$ backup perform -t daily_db_backup 

제대로 동작했다면 서버의 /home/[account-name]/backups/ 폴더에 백업 파일이 저장되고 결과가 메일로 발송되었을 것이다. 추가로 백업 명령의 로그를 저장하고 싶을 때는 아래와 같이 옵션을 추가할 수 있다.

$ backup perform -t daily_db_backup >> /home/[user-account]/Backup/config/cron.log 2>&1 

(2) Whenever 젬

다음은 마지막으로 실행한 명령을 시스템 cron job으로 등록해 보도록 하자. 여기서는 cron job 설정을 편리하게 하기 위해서 whenever 젬을 사용하기로 한다. 이를 위해서 서버로 접속한 후 아래와 같이 whenever 젬을 시스템에 설치한다.

$ gem install whenever

그리고 Backup 디렉토리로 이동한 후 config 디렉토리를 생성한다. whenever 젬에서 필요로로 하는 파일을 생성하기 위해서 아래와 같이 명령을 수행한다.

$ wheneverize . 

위의 명령을 실행하여 생성된 config/schedule.rb 파일을 열고 아래와 같이 수정한다.

every 1.day, :at => '12:00 am' do 
  command "backup perform -t daily_db_backup >> /home/[user-account]/Backup/config/cron.log 2>&1" 
end 

즉, 매일 자정에 백업 작업을 실행하라는 루비 코드를 작성한 것이다. 이제 마지막으로 해야할 일은, 이 스케쥴파일을 실제로 crontab에 반영하기 위해서 crobtab을 업데이트하는 것이다.

$ whenever --update-crontab 

그리고 crontab -l 명령으로 제대로 반영되었는지를 확인한다.

(3) 요약

지금까지 설명한 내용을 요약하면, 데이터베이스 덤프파일을 작성하여 압축한 후 특정 매체에 저장하도록 하였고 이 작업을 cron job으로 등록하여 데이터베이스의 자동 백업을 기능을 구현해 보았다.

**참고문서 **

  1. Backup a Rails Database With the Backup and Whenever Gems
  2. Scheduled Backups with Clockwork and Backup Gem
  3. Schedule Cron Jobs with the Whenever Gem

댓글 남기기

이 사이트는 스팸을 줄이는 아키스밋을 사용합니다. 댓글이 어떻게 처리되는지 알아보십시오.