シェルスクリプトの年齢に基づいてファイルの行を消去する

シェルスクリプトの年齢に基づいてファイルの行を消去する

mysqlサーバーのスレーブディレイを1分ごとに記録したいので、簡単なスクリプトを用意しました。

#!/bin/bash
echo "`date` : `mysql -uroot -pXXXXXX -e"show slave status\G" | grep -i seconds_behind_master | awk '{$1=$1};1'`"

サンプル出力は次のとおりです。

Wed Jul  1 11:40:17 +0530 2020 : Seconds_Behind_Master: NULL
Wed Jul  1 11:41:17 +0530 2020 : Seconds_Behind_Master: NULL
Thu Jul  2 11:42:17 +0530 2020 : Seconds_Behind_Master: 0
Fri Jul  3 11:40:17 +0530 2020 : Seconds_Behind_Master: 1
.
.
.
Fri Jul  31 4:40:17 +0530 2020 : Seconds_Behind_Master: 10

同じスクリプトに、日付フィールドに基づいて30日より古いレコードを削除する削除ロジックを含める方法があります。セントース8を使っています。

よろしくお願いします。

答え1

cutoff=$( date -d "30 days ago" "+%s" )

while read -r line ; do
  timestamp=$( date -d"$( echo $line | cut -d: -f1,2,3 )" "+%s" )
  if [ $timestamp -gt $cutoff ] ; then
    printf -- '%s\n' "$line"
  fi
done

このようにしてください

$ purge.sh < data > newdata

説明する:

まず、30日前にepoch形式のタイムスタンプを取得します。次に、入力のタイムスタンプを解析し、エポック形式で印刷します。次に、解析されたタイムスタンプを30日前のタイムスタンプと比較して、最新の行のみを印刷します。

Epoch形式は、1つの数字で完全なタイムスタンプです。この数字は、1970年1月1日以降に経過した秒数を表します。この日には特別なことはなく、誰もが同意する合意にすぎません。通常は整数ですが、秒よりも高い精度が必要な場合は、小数部を持つことができます。実は数字だけなので時間比較が簡単です。

時代の詳細については、こちらをご覧ください。https://en.wikipedia.org/wiki/Unix_time

いくつかの詳細

date -d "30 days ago" "+%s"

date人間が読める表現を解析できるので、これは良い方法です。

the は、"+%s"epoch 形式を出力する日付の引数です。

cut -d: -f1,2,3

このcutコマンドは、コロンを区切り文字として使用して、入力から最初の3つの列を削除します。これは、使用中の時間形式にスペースとコロンが含まれており、コロンを列区切り文字として再利用するために必要です。より良い日付/時刻形式を使用すると、これは大幅に簡素化される可能性があります。これについては後で詳しく説明します。

[ $timestamp -gt $cutoff ]

タイムスタンプがカットオフ値より大きいときにbashが言う内容です。

printf -- '%s\n' "$line"

複雑だが強力な表現方法です。echo $line


より良い時間形式情報

あなたの人生(そして同僚の人生)をより簡単にするには、タイムスタンプをiso形式で書くことをお勧めします。

date -Iseconds

seconds必要なだけ精度を持つ方法ですseconds。一般的にこれだけで十分です。

比較する

$ date -Iseconds
2022-05-04T21:30:23+02:00

$ date
Mi 4. Mai 21:30:24 CEST 2022

簡単に言えば、利点は次のとおりです。スペースがないため、ほとんどのテキスト解析ツールでは「単語」です。並べ替えが簡単です。それでも人が読むことができます。ロケール依存文字列(日と月の名前)はありません。

iso形式を使用してタイムスタンプを作成すると、削除コードは次のように単純化できます。

while read -r isotimestamp rest ; do
  timestamp=$( date -d"$isotimestamp" "+%s" )
  if [ $timestamp -gt $cutoff ] ; then
    printf -- '%s %s\n' "$isotimestamp" "$rest"
  fi
done

cutこれで、 extra の代わりに、最初のread「単語」を行の残りの部分から分離する方法を使用できます。


別の方法

ファイルの最後のX行だけを維持する方が簡単で高速です。たとえば、システムが1日に最大2行を生成する場合は、最後の60行だけを保持します。

tail -n 60 data > newdata

もちろん、これは毎日ほぼ同じ数の行がある場合にのみ機能します。このアプローチは、1日に9000を超える回線がある場合があり、時には2つの回線しかない場合は機能しません。

関連情報