Edited at

bashでscpするシェルスクリプト

やりたいこと

各サーバーのログファイルを定期的に取得し保存する。保存元のサーバーでシェルスクリプトを書いてみました。


  • 保存したログファイルは保持期間が過ぎていれば削除する

  • webとapiのログファイルは当日日付、batchは前日日付

  • bashのバージョンはGNU bash, version 4.2.46

#!/bin/bash -eu

# sshログイン
SSH_LOGIN="-i ~/.ssh/id_rsa [username]@"

# ファイル保持期間
PERIOD=5

# 前日日付
PRE_Y="$(date '-d 1 day ago' +%Y)"
PRE_M="$(date '-d 1 day ago' +%m)"
PRE_D="$(date '-d 1 day ago' +%d)"
PRE_YMD=${PRE_Y}${PRE_M}${PRE_D}

# 当日日付
TO_YMD="$(date +%Y%m%d)"

# エラーメッセージ
error_msg=""

# 各サーバーのコピー元ファイルとコピー先ディレクトリのハッシュ
declare -A WEB
WEB["/var/log/nginx/www.hoge.jp/*.log-${TO_YMD}.gz"]="/server_logs_backup/web@/var/log/nginx/"

declare -A API
API["/var/log/nginx/api.hoge.jp/*.log-${TO_YMD}.gz"]="/server_logs_backup/api@/nginx/"

declare -A BATCH
BATCH["/home/hoge/app/logs/${PRE_YMD}.php.gz"]="/server_logs_backup/batch@/app/logs/"

# 各ホストのIPとサーバーのハッシュ
declare -A HOST
HOST["IP address"]="WEB"
HOST["IP address"]="API"
HOST["IP address"]="BATCH"

# サーバーとコピー元ファイルのハッシュ
declare -A SERVER
SERVER["WEB"]=${!WEB[@]}
SERVER["API"]=${!API[@]}
SERVER["BATCH"]=${!BATCH[@]}

# コピー先を取得する
function get_dest {
eval echo '$'{$1[$2]/@/$3}
}

# エラー時のメール送信
function send_alert {
echo "Subject: [ERROR] log backup fails
To: [宛先のアドレス]
From: [送信者のアドレス]

${1}" | /usr/sbin/sendmail -t
}

# HOSTのキーからipを取得
for ip in ${!HOST[@]}; do

# ipからサーバーを取得
for server in ${HOST[$ip][@]}; do

# サーバーからコピー元ファイルを取得
for src in ${SERVER[$server][@]}; do
# コピー先を取得
dest=`get_dest ${server} ${src} ${ip##*.}`

# 保持期間がすぎているファイルを削除
find ${dest} -mtime +${PERIOD} -type f | xargs rm -rf

# コピー元ファイルが存在するか確認
if [ $(ssh ${SSH_LOGIN}${ip} "ls $src >& /dev/null;" echo \$?) -eq 0 ]; then

# 存在すればコピー先にscpする
/usr/bin/scp ${SSH_LOGIN}${ip}:${src} ${dest}

# scpコマンドでエラーが出た場合はerror_msgを貯める
if [ $? -ne 0 ]; then
BODY="[ERROR] ${ip} ${server} ${src} ${dest}"
echo ${BODY} >> "${log_file}"
error_msg+="${BODY}
"

fi

fi

done

done

done

# error_msgが空でなければメール送信
if [ -n "${error_msg}" ]; then
send_alert "${error_msg}"
fi

exit 0