hb

#!/bin/bash

#  作業用メモ
#  ■日付を指定して、その案件のその日付ファイルが存在しなくてもエラーでとめたりしない。なぜならある案件の契約が終了とした場合、このスクリプトも対象案件から外さないと、途中でとまる可能性あるから
#  対応として対象件数をログにのこしておく。それで途中でとまらないようにしておく
#  → warning でわかる。filecount を追加した
#
# ./hhhhdata_sftp_bk1.sh 20230119
#    エラー処理
#    ・対象ファイル(指定hhhhサーバのファイルない)が存在しなくてもエラーにはしない
#    ・対象ファイル(指定日付のファイルない)が存在しなくてもエラーにはしない
#    ・sftpしないだけ
#    ・途中でサーバの数が増えても、このスクリプトが途中でおちないこと(ないホストデータはとれないけどね)
#    ・途中でサーバの数が減っても、このスクリプトが途中でおちないこと(ないホストデータはとれないけどね)
#    ■実行後に確認後のためにファイル数をだしたらいいかとおもったけどやめた。面倒だから
#  確認方法が、これまでのファイル数にするか、1ファイルだけなのでファイルサイズにするか、それともチェック処理不要にするか
#  どれかにするかは別途検討する
#  → grep -o で件数わかるからこれでいいかもね 
# ■ファイル数の確認はできない too meny 引数でむり → 文字通の Fetchg をカウントすることで解決。だがファイル数多い場合の確認は必要
# ■sftp中にエラーをキャッチできるようにする それでエラーを回避する → catch は無理だが、No route/refused の文字が含まれてるかを確認すう
#--------------------


#-----------------------------------
#
#  hhhh backup/log データ取得スクリプトBK1サーバ起動用)
#  
#  概要
#    rsyncを実行しリモートサーバ(hhhh統合監視サーバ)に接続、各hostディレクトリ配下に存在する、ファイルを一括で取得する。
#    但し、一部履歴ファイルについては、対象となる日付のファイルのみ取得
#    また、ローカルサーバ内において、上記3種類の履歴ファイル数が、一定世代分を超えた場合はその超えた分を削除する
#
#  Examples:
#    1. ./${SCRIPTNAME} 
#    日付パラメータ指定なし。昨日の日付のファイルをリモートサーバより取得する
#
#    2. ./${SCRIPTNAME} {YYYYMMDD}
#    日付パラメータ指定あり。パラメータの指定日付のファイルをリモートサーバより取得する
#
#  対象ファイル
#    リモートサーバ内にある、/data/AAAA/backup/配下のファイルをすべて(但し3種類の履歴ファイルは除く)
#
#    以下、3種類の履歴ファイルについては、指定した対象日付ファイルのみ取得する。
#    ・/data/AAAA/backup/${HOSTNAME}/export/${TARGET_DATE}_${HOSTNAME}_export.tar.gz
#    ・/data/AAAA/backup/${HOSTNAME}/log/event/${HOSTNAME}_hhhh_event_${TARGET_DATE}*.csv.gz
#    ・/data/AAAA/backup/${HOSTNAME}/log/${HOSTNAME}_STATUS_${TARGET_DATE}-*.log
#    ※上記、3種類の履歴ファイルについては、一度ファイルをローカルのtmpディレクトリに取得・保存後、別処理でmvで対象ディレクトリに移動する 
#    ※上記、3種類の履歴ファイルについては、一定世代分を超えた場合はその超えた分を削除する
#
#  前提条件
#    ・実行権限の付与
#    ・./log ディレクトリが存在すること(この配下に実行ログを出力)
#
#  Note:
#    ・sftpを実行しリモートサーバに接続、対象ディレクトリ配下に存在する、指定日のgz,logファイルを取得
#      BK1環境用(SAG3環境から hhhh用 gz,logファイルを取得)
#      BK2環境用(BK1環境から hhhh用 gz,logファイルを取得)
#    ・Bk1/BK2用の違いは、取得元リモートサーバとそのディレクトリが異なる
#    ・./log配下に格納するログファイルは、月別のログファイルとする。3カ月分を過ぎたファイルは、本スクリプト起動時に削除する
#    ・おおよそのファイル数は、ファイル3種類 x 約20監視サーバ
#    ・/data/AAAA/collect配下のファイルは、取得不要
#    ・/data/AAAA/export配下のファイルは、取得不要
#
#-----------------------------------

#-----------------
# 変数設定
#----------------

# ローカルサーバ
#SCRIPT_HOMEDIR=/usr/local/script/backup_shell
SCRIPT_HOMEDIR=/code/backup_shell # ★★本番ではここ変える可能性高い
SCRIPT_NAME=$0
#OUTPUT_HOMEDIR=${SCRIPT_HOMEDIR}/outputcsv_DCYCPMDB1 # sftp結果を格納する、出力先ホームディレクト
YYYYMM=`date '+%Y%m'` # 年月
LOG_NAME="$(basename $0 | sed -e 's/.sh//g')_${YYYYMM}.log"
#LOG=/code/sftp_shell/log/${LOG_NAME}
LOG=${SCRIPT_HOMEDIR}/log/${LOG_NAME}
DEBUG_FLAG=1 # 0:ログファイルのみ 1:ログファイルと標準出力
#OUTPUT_HOMEDIR="/tmp" # from_remoteserver_sftp_result
#OUTPUT_HOMEDIR="./from_remoteserver_sftp_result"
#hhhh_HOSTNAME_LIST_FILE="./hhhh_hostname_list.txt"

# リモートサーバ(BK1/Bk2でこの箇所を切り替える)
REMOTE_IPADDRESS="172.30.0.55" # service_rrdtool_web
REMOTE_USER="mmmm"
REMOTE_PW="mmmm1212"
REMOTE_DATA_AAAA_BACKUP_DIR="/var/www/html/test_hhhh/AAAA/backup"
#REMOTE_TARGET_HOMEDIR="/var/www/html/test_hhhh/AAAA"

OUTPUT_TMP_DIR="/tmp/hhhhdata_tmp"
OUTPUT_DIR="/data/AAAA/backup"
MAX_LEAVE_BACKUP_FILE_COUNT=4 # 3ファイル残したいなら4を指定。90ファイル残す場合は91を指定。# $2 残す最大ファイル数+1(この数-1を超えると削除対象となる) 4を指定すると3個のみ残る。それ以上は削除


#----------------
# ログ関数
# 第1引数:error level 第2引数:ログ出力文字列
#----------------
function log () {
    time=$(date '+%Y/%m/%d %T')
    errorlevel=$1
    if [ ${DEBUG_FLAG} -eq 1 ]; then
      echo -e "$time $errorlevel [${BASH_LINENO[0]}] ${@:2:($#-1)}" | tee -a ${LOG}  # ファイルと標準出力両方
    else
      echo -e "$time $errorlevel [${BASH_LINENO[0]}] ${@:2:($#-1)}" >> ${LOG}  # ファイルのみに出力
    fi   
}

#----------------
# ファイル削除 日付でソートし、指定数以上のファイルが存在する場合、古いファイルから削除
# $1 削除対象となるファイル名パターン 
#----------------
function deletefile () {
  delete_target_file=`eval echo $1` # 変数に変数を入れるのでここで文字列で取得し、evalを使用することで変数を展開

#  log "[INFO ]" "start deletefile() "
#  log "[INFO ]" "target delete file pattern: ${delete_target_file}"
#  log "[INFO ]" "matching target file all count: `ls -t ${delete_target_file} | wc -l`"

  # 日付でソートし、指定数以上のファイルが存在する場合、古いファイルから削除
  if test -n "`ls -t ${delete_target_file} | tail +${MAX_LEAVE_BACKUP_FILE_COUNT}`"; then
#    log "[INFO ]" "delete file count: `ls -t ${delete_target_file} | tail +${MAX_LEAVE_BACKUP_FILE_COUNT} | wc -l`"
    log "[INFO ]" "execute delete because the number of stored files exceeds the threshold. delete file count: `ls -t ${delete_target_file} | tail +${MAX_LEAVE_BACKUP_FILE_COUNT} | wc -l`"  # 保管しているファイル数が閾値を超えたため削除を実行する
    log "[INFO ]" "delete file list: `ls -t ${delete_target_file} | tail +${MAX_LEAVE_BACKUP_FILE_COUNT}`"
    rm `ls -t ${delete_target_file} | tail +${MAX_LEAVE_BACKUP_FILE_COUNT}`   # +3:2個だけ残し他は削除  +91 90個分を残し他は削除 /tmp/work だけだとパスがなく、ファイル名しか表示されないの
    if [ $? -gt 0 ]; then
      log "[ERROR]" "remove-command failed"
    fi
  fi
}


#----------------
# main
#----------------
log "[INFO ]" ""
log "[INFO ]" "start ${SCRIPT_NAME} $@"

#----------------
# 1 引数チェック
#----------------
if [ "$#" -eq 0 ]; then
  # 引数無し:昨日の年月日を対象日としてセット
  TARGET_DATE=`date --date '1 day ago' "+%Y%m%d"`
  # YYYYMM=`date --date '1 day ago' "+%Y%m"` 
  log "[INFO ]" "target date is yesterday. [${TARGET_DATE}]"

elif [ "$#" -eq 1 ]; then
  # 引数1:日付指定あり。指定日付をを対象日としてセット
  TARGET_DATE=$1 
  log "[INFO ]" "input parameter target date : ${TARGET_DATE}" 

  # 日付形式チェック 日付変換を仮に行い、変換不可の場合、NG
  if [ "`date +'%Y%m%d' -d ${TARGET_DATE} 2> /dev/null`" -eq ${TARGET_DATE} ]; then
      log "[INFO ]" "target date is format ok : ${TARGET_DATE}"
  else
      log "[ERROR]" "target date is format ng : ${TARGET_DATE}"
      exit 1
  fi

else 
  log "[ERROR]" "parametar error!!"
  exit 1
fi


#----------------
# 2 ssh接続事前確認
#----------------
# リモートサーバに接続確認(サーバ初回接続時は、ファイル数取得時に他の文字列も含んでしまうため切り分けて処理)
ret=`expect -c "
set timeout 3
spawn ssh ${REMOTE_USER}@${REMOTE_IPADDRESS}
expect \"Are you sure you want to continue connecting (yes/no)?\" {
    send \"yes\n\"
    expect \"${REMOTE_USER}@${REMOTE_IPADDRESS}'s pppp:\"
    send \"${REMOTE_PW}\n\"
} \"${REMOTE_USER}@${REMOTE_IPADDRESS}'s pppp:\" {
    send \"${REMOTE_PW}\n\"
}
expect eof
exit
"`

# サーバが起動していない場合
if "${ret}" == *"No route"* ; then
  log "[ERROR]" "remote server connect failed(No route)"
  log "[ERROR]" ${ret}
  exit
fi

# リモートサーバのsshが起動していない場合
if "${ret}" == *refused* ; then
  log "[ERROR]" "remote server ssh failed"
  log "[ERROR]" ${ret}
  exit
fi

log "[INFO ]" "${ret}" 
log "[INFO ]" "remote server connect ok!!: ${REMOTE_IPADDRESS}" 


#----------------
# 3 rsync 実行
# 3.1 リモートサーバ内にある、/data/AAAA/backup/ 配下のファイルとディレクトリをすべて取得する
#   但し、以下3種類のファイル形式は除く
#   ・*/export/*_export.tar.gz
#   ・*/log/event/*_hhhh_event_*.csv.gz
#   ・*/log/*_STATUS_*.log}

# 3.2 上記で除外した3種類の対象履歴ファイル(世代数管理が必要な、3種類のファイル)は、日付を指定した上で別途rsyncにより取得する
#   コピー元指定にワイルドカード指定した場合、コピー先には指定ホストディレクトリは作成されず、指定直下に保存となるため、
#   まずローカルに取得・保存し、そこからmvで移動する処理とする
#----------------
log "[INFO ]" "start rsync
# spawn rsync -avz -e ssh mabu@172.30.0.55:/var/www/html/test_hhhh/AAAA/backup ./  --exclude '*/export/*_export.tar.gz' --exclude '*/log/event/*_hhhh_event_*.csv.gz' --exclude '*/log/*_STATUS_*.log'
# spawn rsync -avz -e ssh ${REMOTE_USER}@${REMOTE_IPADDRESS}:/var/www/html/test_hhhh/AAAA/backup ./output --exclude '*/export/*_export.tar.gz' --exclude '*/log/event/*_hhhh_event_*.csv.gz' --exclude '*/log/*_STATUS_*.log'
# exe_rsync
# 履歴3種類については

mkdir -p ${OUTPUT_TMP_DIR}

ret=`expect -c "
  set timeout 3

  # ディレクトリ内全ファイル(対象履歴3ファイル除く) 
  spawn rsync -avz -e ssh ${REMOTE_USER}@${REMOTE_IPADDRESS}:${REMOTE_DATA_AAAA_BACKUP_DIR} /data/AAAA/ --exclude */export/*_export.tar.gz --exclude */log/event/*_hhhh_event_*.csv.gz --exclude */log/*_STATUS_*.log
  expect \"${REMOTE_USER}@${REMOTE_IPADDRESS}'s pppp:\"
  send \"${REMOTE_PW}\n\"
  interact

  # 対象履歴ファイル1 
  spawn rsync -avz -e ssh ${REMOTE_USER}@${REMOTE_IPADDRESS}:${REMOTE_DATA_AAAA_BACKUP_DIR}/*/export/${TARGET_DATE}_*_export.tar.gz  ${OUTPUT_TMP_DIR} 
  expect \"${REMOTE_USER}@${REMOTE_IPADDRESS}'s pppp:\"
  send \"${REMOTE_PW}\n\"
  interact

  # 対象履歴ファイル2
  spawn rsync -avz -e ssh ${REMOTE_USER}@${REMOTE_IPADDRESS}:${REMOTE_DATA_AAAA_BACKUP_DIR}/*/log/event/*_hhhh_event_${TARGET_DATE}*.csv.gz  ${OUTPUT_TMP_DIR}
  expect \"${REMOTE_USER}@${REMOTE_IPADDRESS}'s pppp:\"
  send \"${REMOTE_PW}\n\"
  interact

  # 対象履歴ファイル3
  spawn rsync -avz -e ssh ${REMOTE_USER}@${REMOTE_IPADDRESS}:${REMOTE_DATA_AAAA_BACKUP_DIR}/*/log/*_STATUS_${TARGET_DATE}*.log  ${OUTPUT_TMP_DIR}
  expect \"${REMOTE_USER}@${REMOTE_IPADDRESS}'s pppp:\"
  send \"${REMOTE_PW}\n\"
  interact

"`
log "[INFO ]" "${ret}"  # rsync理経過をログ出力

# 対象履歴ファイル(世代数管理が必要な、3種類のファイル)について、取得したファイル数をカウント(対象ファイルがない場合ここで終了)
gzlogfile_cnt=`find ${OUTPUT_TMP_DIR}/{*log,*gz} -type f | wc -l`
if [ ${gzlogfile_cnt} -eq 0 ]; then
  log "[WARN ]" "Number of gzlog files retrieved by rsync: ${gzlogfile_cnt}"
  exit 0
else 
  log "[INFO ]" "Number of gzlog files retrieved by rsync: ${gzlogfile_cnt}"
fi


#----------------
# 4 各ホストごとの処理
# tmpディレクトリに保存した、3種類の履歴ファイル(log,gz)をあるべきdirにmvする。
# 同時に、移動先dir内に。一定数以上の世代ファイルが存在する場合、削除する
#----------------

#-------------------------
# 4.1 ファイル名タイプ *_${HOSTNAME}_export.tar.gz の処理
# ホスト名:$2 (_区切りの2列目より崇徳)
# 例) ${OUTPUT_DIR}/DDDDDD01/export/20230118_DDDDDD01_export.tar.gz
#-------------------------
log "[INFO ]" "start mv delete action "

log "[INFO ]" "targetfile pattern: *_*_export.tar.gz"
for file in `ls ${OUTPUT_TMP_DIR}/*_*_export.tar.gz`; do
  HOSTNAME=`basename ${file} | awk ' BEGIN { FS="_" }{  print $2 } '`
  mkdir -p ${OUTPUT_DIR}/${HOSTNAME}/export/
  log "[INFO ]" "hostname:${HOSTNAME} cmd: mv ${file} ${OUTPUT_DIR}/${HOSTNAME}/log/"
  mv ${file} ${OUTPUT_DIR}/${HOSTNAME}/export/
  # 指定世代以上のファイル数が存在する場合、古いファイルを削除
  deletefile '${OUTPUT_DIR}/${HOSTNAME}/export/*_${HOSTNAME}_export.tar.gz' 
done

#-------------------------
# 4.2 ファイル名タイプ ${HOSTNAME}_STATUS_*.log の処理
# ホスト名:$1 (_区切りの1列目より崇徳)
# 例)${OUTPUT_DIR}/DDDDDD01/log/DDDDDD01_STATUS_20230118-010000.log
#-------------------------
log "[INFO ]" "targetfile pattern: *_STATUS_*.log"
for file in `ls ${OUTPUT_TMP_DIR}/*_STATUS_*.log`; do
  HOSTNAME=`basename ${file} | awk ' BEGIN { FS="_" }{  print $1 } '`
  mkdir -p ${OUTPUT_DIR}/${HOSTNAME}/log/
  log "[INFO ]" "hostname:${HOSTNAME} cmd: mv ${file} ${OUTPUT_DIR}/${HOSTNAME}/log/"
  mv ${file} ${OUTPUT_DIR}/${HOSTNAME}/log/
  # 指定世代以上のファイル数が存在する場合、古いファイルを削除
  deletefile '${OUTPUT_DIR}/${HOSTNAME}/log/${HOSTNAME}_STATUS_*.log'
done

#-------------------------
# 4.3 ファイル名タイプ ${HOSTNAME}_hhhh_event_*.csv.gz の処理
# ホスト名:$1 (_区切りの1列目より崇徳)
# 例) ${OUTPUT_DIR}/DDDDDD01/log/event/DDDDDD01_hhhh_event_20230118010000.csv.gz
#-------------------------
log "[INFO ]" "targetfile pattern: *_hhhh_event_*.csv.gz"
for file in `ls ${OUTPUT_TMP_DIR}/*_hhhh_event_*.csv.gz`; do
  HOSTNAME=`basename ${file} | awk ' BEGIN { FS="_" }{  print $1 } '`
  mkdir -p ${OUTPUT_DIR}/${HOSTNAME}/log/event/
  log "[INFO ]" "hostname:${HOSTNAME} cmd: mv ${file} ${OUTPUT_DIR}/${HOSTNAME}/log/"
  mv ${file} ${OUTPUT_DIR}/${HOSTNAME}/log/event/
  # 指定世代以上のファイル数が存在する場合、古いファイルを削除
  deletefile '${OUTPUT_DIR}/${HOSTNAME}/log/event/${HOSTNAME}_hhhh_event_*.csv.gz' 
done

exit 0