ジャンクPCを探すために、毎日ヤフオクとメルカリを巡回している系エンジニアです。
最近、社内システムのバックアップや構成変更等行いました。
AWS上のインスタンスであれば、EBSのスナップショットやS3へのデータ保存が比較的に容易に行うことができます。
他のクラウドサービスやVPS上で動作しているサービスに関しては、NASであるQNAPに保存を行うことにしました。
今回は、QNAPへ保存する際にバックアップを行うシェルスクリプトを作成したので、その際のTipsを紹介したいと思います。
目次
QNAPって?
簡単にQNAPの紹介をします。
一言で言うとQNAPは、「GUI見やすいサービスいろいろあるLinuxベースのNAS」です。
ユーザー管理やアクセスマネジメント、VPN機能などが最初からついています。
Linuxベースでコンソールに入ることができるので、自分でNAS上で動作するスクリプトを作成することも可能です。
サーバーごとのアクセス設定やconfig
バッチ系の処理を行う際に、アクセス先のホスト名やSSH, SCPのユーザーパスなど定数の処理をどうするかという問題がでてきます。
以下のように書いてもいいのですが、いろいろな問題が出てきます。
1 2 3 4 |
HOST="backupdayo.geekfeed.co.jp" USER="backupdayo" KEYFILE="/etc/config/sshkey_backupdayo" BACKUP_DIR="/hppme/backupdayo/backup" |
などなど。
この問題を解決するために、設定は別ファイルで持つのが良いと思います。
そして、複数サーバーのバックアップを効率よく行うために、フォーマットを定めるのが良いでしょう。
以下はJSONを利用した設定ファイルです。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
[ { "hostname": "backup1.geekfeed.co.jp", "user": "backup1", "sshkey": "/home/backup/sshkey_backup", "dbuser": "user", "dbpass": "password", "database": "appdb", "backup_path": "/var/www", "backup_dir": "application", }, { "hostname": "backup2.geekfeed.co.jp", "user": "backup2", "sshkey": "/home/backup/sshkey_backup", "dbuser": "user", "dbpass": "password", "database": "appdb", "backup_path": "/var/www", "backup_dir": "application", }, { "hostname": "backup2.geekfeed.co.jp", "user": "backup2", "sshkey": "/home/backup/sshkey_backup", "dbuser": "user", "dbpass": "password", "database": "appdb", "backup_path": "/var/www", "backup_dir": "application", }, ] |
JSONオブジェクトをシェルスクリプトには、以下のコードを利用します。
1 2 3 4 5 6 7 8 9 10 11 12 13 |
#!/bin/bash #Backup server information CONFIGFILE='/etc/config/jsonconfig' JSON=$(cat ${CONFIGFILE}) LEN=$(echo ${JSON} | jq length) for ((i=0; i<${LEN}; i++)); do ROW=$(echo ${JSON} | jq .[$i]) HOSTNAME=$(echo ${ROW} | jq .hostname) HOSTNAME=${HOSTNAME//\"/} echo ${HOSTNAME} done |
jqコマンドでJSONを扱っています。
11行目ではダブルクオーテーションを値から削除しています。
上記のような形でスクリプトを書けば割とスマートな感じになるんじゃないでしょうか。
リモートアクセス方式
リモートアクセス方法について、SSHにてリモートアクセスしコマンドを実行するためには、認証処理が必要になります。
こちらに関しては公開鍵による認証ほぼ一択だと思います。
パスワード認証をスクリプト上で頑張って実装することはできますが、先程のconfigファイルと合わせて鍵認証を行うほうが効率がいいです。
ファイル転送をSCPで行うことで複数のアクセス情報を持つ必要がないということも利点です。
バックアップ対象のサーバーたちに共通の秘密鍵を持つユーザーを作成すると、同じ認証情報を利用してアクセスすることができます。
こちらに関してはセキュリティをどれくらい求めるかを考えて、各自で判断していただきたいと思います。
リモートログインユーザーをどうするか
バックアップ対象サーバーへのリモートログインユーザーはどうしようという問題です。
こちらもセキュリティの問題に含まれます。
もちろんrootユーザーを使用してもいいと思います。
その場合、鍵の管理やIPアドレスでのアクセス制限をつけてセキュリティ強化を行うと安心でしょう。
私が行ったのは以下の方法です。
tarコマンドやzipコマンドなど、バックアップユーザーが権限を持たないファイルを圧縮する場合にはsudoが必要になります。
sudoに関しては次のセクションで注意点を説明します。
リモートコマンドのTips
以下は私が実際に使用している、バックアップの際にリモートコマンドを実行する際のスクリプトです。
1 2 3 4 5 6 |
ssh -t -t ${LOGINUSER}@${HOSTNAME} -i ${SSHKEY} <<EOC mysqldump -u ${DBUSER} -p${DBPASS} -AE > /tmp/backup/${HOSTNAME}_${TODAY}.sql cd ${BACKUP_PATH} sudo tar cfz /tmp/backup/${HOSTNAME}_${TODAY}.tgz ${BACKUP_DIR} 2>&1 /dev/null sudo chown ${LOGINUSER}. /tmp/backup/* 2>&1 /dev/null EOC |
ヒアドキュメントを利用して一度に複数のコマンドを実行しています。
各行の補足を以下で行います。
1行目
sshコマンドの「t」オプションはssh接続時にローカルの擬似端末を割り当てるオプションです。
このオプションは複数回使用することで強制的に擬似端末を割り当てることができます。
リモートでsudoコマンドを使う時、この擬似端末を要求されることがあるのでつけています。
なくても動作するサーバーもあります。これはOSのバージョンやsudoのバージョンによって変わるようです。
2行目
一般的なmysqldumpです。
一点だけ、「A」オプションはすべてのデータベースのダンプを行うオプションです。
しかしAオプションではデフォルトで入っている「events」というテーブルが含まれません。
「E」オプションをつけることでeventsテーブルを含めたすべてのデータベースをダンプすることができます。
参考:https://qiita.com/crimson_21/items/6171a95f8ddb2861e2e6
バックアップするデータベースが決まっているのであれば、データベース名を指定するほうがスマートだと思います。
3, 4行目
cdコマンドからのsudo tarコマンドです。
tarコマンドは、圧縮対象ディレクトリを絶対パスで指定するとwarningがでます。
絶対パスのディレクトリ構成含めてすべて圧縮するか判断できないからです。
ですので、一度cdコマンドでバックアップ対象のディレクトリがある場所まで移動しています。
これは以下のtarコマンドで以下のように書くことで代替可能です。
1 |
sudo tar -C ${BACKUP_PATH} cfz /tmp/backup/${HOSTNAME}_${TODAY}.tgz ${BACKUP_DIR} 2>&1 /dev/null |
「C」オプションでcdした場合と同じ結果となります。
最後の標準出力と標準エラー出力を捨てている部分ですが、こちらがないとsudoコマンドがうまく動作しませんでした。
詳しくは以下のリンクからどうぞ。
参考:https://www.greptips.com/posts/1172/
5行目
sudo chownコマンドです。tarコマンドをsudo実行しているので、ファイルのオーナーがrootになっています。
このままではscpのファイル転送を行うことができないので、ログインユーザーにパーミッションを変更します。
その他のTips
ファイルの整合性確認方法
バックアップ対象サーバー上で圧縮したファイルと、NASで受け取ったファイルが同一かどうかを確認します。
「sha1sum」コマンドを利用しました。「md5sum」コマンドもQNAPは利用可能です。
以下整合性確認のスクリプトです。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
#バックアップ対象サーバー上の圧縮ファイルのHASH値を求める BACKUP_SIZE=$(ssh ${LOGINUSER}@${HOSTNAME} -i ${SSHKEY} "sha1sum /tmp/backup/${HOSTNAME}_${TODAY}.tgz") BACKUP_SIZE=$(echo ${BACKUP_SIZE} | awk '{ print $1 }') #QNAP上の圧縮ファイルのHASH値を求める BACKUP_SIZE_LOCAL=$(sha1sum ${BACKUPDIR}/${HOSTNAME}/${HOSTNAME}_${TODAY}.tgz) BACKUP_SIZE_LOCAL=$(echo ${BACKUP_SIZE_LOCAL} | awk '{ print $1 }') #比較して処理を行う if [ ${BACKUP_SIZE} -ne ${BACKUP_SIZE_LOCAL} ]; then #一致しない場合の処理 echo "バックアップエラー" else #一致する場合の処理 echo "バックアップ成功" fi |
アラートメール送信
バックアップ成功時や失敗時にメール送信機能がほしい場合は、「sendmail」コマンドでメール送信を行うと簡単です。
1 2 3 4 5 6 7 8 |
#定数の設定 FROMADDR="from@geekfeed.co.jp" TOADDR="to@geekfeed.co.jp" SUBJECT="Server Backup Alert" BODY="Server backup error occurred." #送信 echo -e "From: <${FROMADDR}>\nTo: <${TOADDR}>\nSubject:${SUBJECT}\n\n${BODY}" | /usr/sbin/sendmail ${TOADDR} |
QNAPのcronの設定
わかりにくい部分ですが、
/etc/config/crontab
がcron設定ファイルの本体です。
「crontab -e」で設定を行っても、定期的に本体のファイルで上書きをするので反映されません。
/etc/config/crontab を編集し、
# crontab /etc/config/crontab
上記コマンドで設定を反映してください。
cronの実行時カレントディレクトリ
自分も1回ハマりましたが、cronで設定したスクリプトの実行時のカレントディレクトリは、
スクリプト実行ユーザーのホームディレクトリです。
ですので、スクリプトからの相対パスでコーディングしていたりすると失敗します。
おわりに
バックアップスクリプトというのは頻繁に書くものではないですが、ふとした時に似たようなスクリプトが必要になったりします。
できるだけ再利用できる部品に分けて、ちょちょいと変更するだけでできるといいなーと思います。
紹介した他にTipsや小技があれば教えてください。
ではでは〜。
- AWS Step Functionsの基本を再学習しました - 2024-09-23
- Amazon SESでバウンスメールを管理する - 2024-07-07
- TEAMをv1.1.1にアップデートしカスタムドメインを設定する - 2024-02-17
- コールセンター白書2023とAmazon Connect - 2023-12-25
- Provide dynamic and personalized CX with in-app web call for Amazon Connect - 2023-12-16