쉘 스크립트의 연령을 기준으로 파일의 줄 지우기

쉘 스크립트의 연령을 기준으로 파일의 줄 지우기

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 형식은 하나의 숫자로 된 전체 타임스탬프입니다. 이 숫자는 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명령은 콜론을 구분 기호로 사용하여 입력에서 처음 세 개의 열을 제거합니다. 이는 사용 중인 시간 형식에 공백과 콜론이 포함되어 있고 콜론을 열 구분 기호로 재사용하기 때문에 필요합니다. 더 나은 날짜/시간 형식을 사용하면 이는 크게 단순화될 수 있습니다. 이에 대해서는 나중에 자세히 설명하겠습니다.

[ $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 줄만 유지하는 것이 더 쉽고 빠릅니다. 예를 들어 시스템이 하루에 최대 2개의 행을 생성하는 경우 마지막 60개 행만 유지합니다.

tail -n 60 data > newdata

물론 이것은 매일 대략 같은 수의 라인이 있는 경우에만 작동합니다. 이 접근 방식은 하루에 9000개 이상의 회선이 있는 경우도 있고 때로는 회선이 2개만 있는 경우에는 작동하지 않습니다.

관련 정보