jq でJSON を整形

本家 Tutorial : https://stedolan.github.io/jq/tutorial/

わかりやすい紹介 : https://qiita.com/takeshinoda@github/items/2dec7a72930ec1f658af

inotify-tools の分かり易い説明 : https://qiita.com/stc1988/items/464410382f8425681c20

アプリケーションのログがJSONテキストで、フィールドを分けて、データベースのテーブルに追加できるスクリプトを作りました。
MySQL 5.7 から、JSON型が提供されたので、整形しないでそのまま追加すれば使えますが、抽出のSQLに慣れてなく、列で分けた方が視認性良いのでそうしてます。

[ 大まかな流れ ]

1) ログは逐次出力されるので、inotify で更新を待ち受け
2) ログの行が追加された時点で、発火
3) 最終行を取得して、sedとかgawkで変換
4) jqで各列値を取得
5) SQL文に整形して、INSERTコマンドを渡しテーブルに追加

[ コード例 ]


#!/bin/bash

### NextCloud log add to my table log ###

# $1 : SiteName (end part of URI) 
# required package: inotify-tools

## --------- const ------------- ##

FIELD_ARRAY=(reqId level time remoteAddr user app method url message userAgent version,)
INSSQL="INSERT INTO log_use (NM_SITE,"

INTERVAL_COMMIT=10         # 一括した時スキップするので
# in order to avoid 
# should write notify result to file. and check row count by wc. and write SQL script file

## ----------------------------- ##

nmsite=$1

watch_file=/home/ncdata/${nmsite}/nextcloud.log
#events=(-e CREATE -e MODIFY -e MOVED_TO)

cnt=0
argsql=""
cmdpost="";
while inotifywait -e MODIFY ${watch_file}; do
  row=`tail -n 1 ${watch_file}`
  echo ${row}
  echo "------------------------------------------------------------"

  # execute jq #
  #echo ${row} | jq
  
  #echo "-- method"
  #echo ${row} | jq -r '.method'
  let cnt++
  echo ${cnt}

  echo "-- SQL"
  cursql=${INSSQL}
  # Field part # 
  for fld in ${FIELD_ARRAY[@]}; do
    cursql=${cursql}${fld}","
  done
  cursql=${cursql}") VALUES ("
  cursql=`echo ${cursql} | sed 's/,,//g'`

  # Value part #
  cursql=${cursql}"'"${nmsite}"',"
  for fld in ${FIELD_ARRAY[@]}; do
    nmfld=`echo ${fld} | sed 's/,//'`
    curval=`echo ${row} | jq ."${nmfld}"`

    if [ ${nmfld} = "time" ]; then
      curval=`echo ${curval} | sed 's/\+[0-9][0-9]:[0-9][0-9]//'`
    fi

    cursql=${cursql}${curval}","
  done
  cursql=${cursql}");"
  cursql=`echo ${cursql} | sed 's/,);/);\n/g'`
  #cursql=`echo -e $cursql"\n"`
  #echo ${cursql}


  argsql=${argsql}${cursql}

  # Execute command #
  if [ ${cnt} -eq ${INTERVAL_COMMIT} ]; then
    #cmdpost=${CMD_SQL}${argsql}"'"
    echo ${argsql} > ${INSSQL_FILENAME}

    ## debug
    tmcur=`date "+%Y%m%d-%H%M%S"`
    #cp ${INSSQL_FILENAME} ${INSSQL_FILENAME}"."${tmcur}

    echo `ls -l ${INSSQL_FILENAME}`
    cmdpost=${CMD_SQL}${INSSQL_FILENAME}
    echo "-- MySQL shell command"
    #echo ${cmdpost}
    #`${cmdpost}`      ???????????? script incorrect

    # Write MySQL database #
    mysql -u???? -p????????? mytable < ${INSSQL_FILENAME}

    argsql=""
    echo "" > ${INSSQL_FILENAME}
    cnt=0
  fi


done

[商品価格に関しましては、リンクが作成された時点と現時点で情報が変更されている場合がございます。]

新しいLinuxの教科書 [ 三宅英明 ]
価格:2970円(税込、送料無料) (2023/1/20時点)

[商品価格に関しましては、リンクが作成された時点と現時点で情報が変更されている場合がございます。]

UNIXという考え方—その設計思想と哲学
価格:2485円(税込、送料無料) (2023/1/29時点)

コメントを残す