mikan's technical note

仕事&趣味で実験した小技の備忘録です(Linux,windows,DOS等)

MENU

【shell】毎日指定時間内に動的にSQLを生成して実行する

21:00:00~23:59:59 の間、処理を繰り返したい場合の例

resident_main.sh

#!/bin/bash

############################################################
#
# 毎日指定時間内にSQL実行(常駐)
# (c) 2018 mikan
# ※使用にあたっては利用者の自己責任でお願いします。
#  使い方:
#          例)nohup bash resident_main.sh &
#
#     ログファイル名:yyyymmdd_HHMMSS_sql_main.log
#
############################################################

### ----- 初期処理
LOG_FILE_NAME=`date +%Y%m%d_%H%M%S`_sql_main.log

### ----- 終了フラグ
END_FLG="end.flg"

### ----- スリープ時間(1~60秒程度で設定)
SLEEP_TIME=2

### ----- 進捗表示用(ASCIIコードの16進) debug用
#CODE=0 #debug

SYSTEM_DATE=`date +%Y/%m/%d_%H:%M:%S`
echo "※21:00~17:59の間はスリープします" >> $LOG_FILE_NAME
echo "※中断したい場合は、touch $END_FLG" >> $LOG_FILE_NAME
echo "[$SYSTEM_DATE]: ===== SQL実行メイン(常駐) - 開始 =====" >> $LOG_FILE_NAME

# ----- 終了フラグを削除
if [ -f `pwd`/$END_FLG ]
then
  rm `pwd`/$END_FLG
fi

### ----- 処理完了日
DAY_COMPLETE=00000000

### ----- DAY_COMPLETE を外部ファイルへ出力(グローバル変数として使用)
echo "DAY_COMPLETE=$DAY_COMPLETE;export DAY_COMPLETE" > day_complete.dat

### ----- メインループ
while :
do
  # ----- ※00:00~20:59の間はスリープ
  while :
  do
    # ----- 終了チェック
    if [ -f `pwd`/$END_FLG ]
    then
      SYSTEM_DATE=`date +%Y/%m/%d_%H:%M:%S`
      echo "[$SYSTEM_DATE]: $END_FLG 検出!" >> $LOG_FILE_NAME
      echo
      echo "[$SYSTEM_DATE]: ===== SQL実行メイン(常駐) - 終了 =====" >> $LOG_FILE_NAME
      echo
      exit 0;
    fi

    # ----- 時刻チェック
    S_TIME=`date +%H` # 本番 (時)

    case $S_TIME in
      21 | 22 | 23 ) #21時~23時(21:00:00~23:59:59)の場合はループを抜ける
         break;;
      * ) #実行時間外
         sleep $SLEEP_TIME
         continue;;
    esac

    sleep $SLEEP_TIME
  done

  # ----- DAY_COMPLETE を取得
  . ./day_complete.dat

  # ----- システム日付(yyyymmdd)を取得
  DAY_TODAY=`date +%y%m%d`

  #----- 1日1回だけSQL実行を呼び出す
  if [ $DAY_TODAY != $DAY_COMPLETE ]
  then
    # ----- SQL実行呼び出し
    SYSTEM_DATE=`date +%Y/%m/%d_%H:%M:%S`
    echo "[$SYSTEM_DATE]: SQL実行を呼び出し" >> $LOG_FILE_NAME
    bash ./sqlexe.sh

    # ----- 処理完了日へシステム日付(yyyymmdd)を取得
    DAY_COMPLETE=`date +%y%m%d`

    # ----- DAY_COMPLETE を外部ファイルへ出力(グローバル変数として使用)
    echo "DAY_COMPLETE=$DAY_COMPLETE;export DAY_COMPLETE" > day_complete.dat

    SYSTEM_DATE=`date +%Y/%m/%d_%H:%M:%S`
    echo "[$SYSTEM_DATE]: DAY_COMPLETE(処理完了日)=$DAY_COMPLETE" >> $LOG_FILE_NAME
  fi

  sleep $SLEEP_TIME
done

# ----- 理論上ここを通ることはない
exit 1

resident_sql.sh

#!/bin/bash

############################################################
#
# 動的にSQLを生成して実行
# (c) 2018 mikan
# ※使用にあたっては利用者の自己責任でお願いします。
#
#   ログファイル名:yyyymmdd_HHMMSS_sql_exec.log
#
#   SQL文だけを抽出する例
#     grep -v ": " 20180515_215302_sql_exec.log
#
#   SQL文以外の実行ログを抽出する例
#     grep ": " 20180515_215402_sql_exec.log
#
############################################################

### ----- ログファイル
LOG_FILE_NAME=`date +%Y%m%d_%H%M%S`_sql_exec.log

### ----- SQL実行間隔(1~5秒程度で設定)
SLEEP_TIME=5

### ----- 終了フラグ
END_FLG="end.flg"

### ----- パラメータファイル取込
. ./param.txt

echo
SYSTEM_DATE=`date +%Y/%m/%d_%H:%M:%S`
echo "[$SYSTEM_DATE]: ===== SQL実行 - 開始 ====="

### ----- メインループ
for i in "${dateArray[@]}";
do

  # ----- 終了チェック
  if [ -f `pwd`/$END_FLG ]
  then
    echo "$END_FLG 検出!"
    echo
    SYSTEM_DATE=`date +%Y/%m/%d_%H:%M:%S`
    echo "[$SYSTEM_DATE]: ===== SQL実行 - 終了 =====" >> LOG_FILE_NAME
    echo
    exit 0;
  fi

  # ----- 時刻チェック(18,19,20時以外は終了)
  S_TIME=`date +%H` # 時

  case $S_TIME in
    21 | 22 | 23 ) #21時~23時(21:00:00~23:59:59)の場合は処理
       ;;
    * ) #実行時間外(処理終了)
       break;;
  esac

  # ----- 各項目を取得
  data=(${i[@]})
  EXEC_DAY=${data[0]}
  DATE_STR=${data[1]}
  DATE_END=${data[2]}

  # ----- インクリメント
  COUNT=$(( COUNT + 1 )) #初期値はゼロ(初期化不要)

  # ----- 処理日チェック
  S_TIME=`date +%Y%m%d`
  echo "[$COUNT]: システム日付[$S_TIME] パラメータ[$EXEC_DAY $DATE_STR $DATE_END]" >> $LOG_FILE_NAME
  if [ $S_TIME != $EXEC_DAY ]
  then
    echo "[$COUNT]: 本日対象外の処理日行($EXEC_DAY)はスキップ" >> $LOG_FILE_NAME
    continue
  fi

  # ----- 条件表示
  S_YEAR=${DATE_STR:0:4}
  S_MON=${DATE_STR:4:2}
  S_DAY=${DATE_STR:6:2}
  S_NO=${DATE_STR:8}
  E_YEAR=${DATE_END:0:4}
  E_MON=${DATE_END:4:2}
  E_DAY=${DATE_END:6:2}
  E_NO=${DATE_END:8}

  # ----- SQLファイル削除
  if [ -f `pwd`/tmp.sql ]
  then
    rm `pwd`/tmp.sql
  fi

  # ----- SQLファイル作成ループ ※SQLは目的に合わせて書き換えてください
  for j in "${tableArray[@]}";
  do
    # ----- 各項目を取得
    tableName=(${j[@]})

    # ----- SQL
    echo "DELETE from $tableName" >> tmp.sql
    echo "  WHERE 項目名1 BETWEEN '$DATE_STR' AND '$DATE_END'" >> tmp.sql
    echo "    AND 項目2 IN ('AAA','BBB','CCC');" >> tmp.sql
    echo "commit work;" >> tmp.sql
  done;

  # ----- SQL実行 ※xxDBは環境に合わせて書き換えてください
  SYSTEM_DATE=`date +%Y/%m/%d_%H:%M:%S`
  echo >> $LOG_FILE_NAME
  echo "----- SQL start [$COUNT][$SYSTEM_DATE] -----" >> $LOG_FILE_NAME
  date >> $LOG_FILE_NAME
  rdbexecsql -s xxDB -i `pwd`/tmp.sql >> $LOG_FILE_NAME
  date >> $LOG_FILE_NAME
  SYSTEM_DATE=`date +%Y/%m/%d_%H:%M:%S`
  echo "----- SQL end   [$COUNT][$SYSTEM_DATE] -----" >> $LOG_FILE_NAME
  echo >> $LOG_FILE_NAME

  # ----- 終了チェック
  if [ -f `pwd`/$END_FLG ]
  then
    echo "$END_FLG 検出!" >> $LOG_FILE_NAME
    break;
  fi

  # ----- スリープ
  sleep $SLEEP_TIME
done;

SYSTEM_DATE=`date +%Y/%m/%d_%H:%M:%S`
echo "[$SYSTEM_DATE]: ===== SQL実行 - 終了 =====" >> LOG_FILE_NAME
echo

exit 0

param.txt

### ----- 処理完了日(debug等特殊な場合を除き通常は"00000000"を設定)
DAY_COMPLETE=00000000;export DAY_COMPLETE

### ----- 対象テーブル
tableArray=(
'xxxx.テーブル1'
'xxxx.テーブル2'
'xxxx.テーブル3'
)
export tableArray

### ----- BETWEEN 条件
#
# システム日付と処理日が一致する行だけが
# 実行対象となります
# 一致しない行は、スキップします
#
#-処理日- -----開始------ -----終了------
dateArray=(
'20180516 2008010100000 2008123199999'
'20180516 2009010100000 2009123199999'
'20180517 2010010100000 2010123199999'
'20180517 2011010100000 2011123199999'
'20180518 2012010100000 2012123199999'
'20180518 2013010100000 2013123199999'
)
export dateArray