배쉬 시차

배쉬 시차

로그 파일이 있는데 두 작업 간의 시간 차이를 찾기 위해 몇 가지 계산을 수행해야 합니다.

내 로그 파일에서는 작업 사이의 시간을 계산해야 합니다 incoming request. candidate list sent for다음 로그의 시간은 2초입니다.

2019-08-23 00:05:27 42303: incoming request: 1dd5.073f.5d5f0397 (156074 bytes)
2019-08-23 00:05:27 42303: store file: /papillon1/vrf/rq/1dd5.073f.5d5f0397.rq, len: 156074
2019-08-23 00:05:27 42303: registering process 42605 left to finish it's work
2019-08-23 00:05:27 42605: making search request for: 1dd5.073f.5d5f0397
2019-08-23 00:05:27 42605: 1dd5.073f.5d5f0397 is request for search by fingers
2019-08-23 00:05:27 42605: portions: 156
2019-08-23 00:05:27 42605: request pattern version 8
2019-08-23 00:05:27 42605: fingers mask: 1111111111; quality mask: 3011031110
2019-08-23 00:05:27 42605: saving request file: /papillon1/vrf/rqm/1dd5.073f.5d5f0397.rqm~
2019-08-23 00:05:27 42605: renaming request file: /papillon1/vrf/rqm/1dd5.073f.5d5f0397.rqm~ -
> /papillon1/vrf/rqm/1dd5.073f.5d5f0397.rqm
2019-08-23 00:05:27 42605: request file saved /papillon1/vrf/rqm/1dd5.073f.5d5f0397.rqm
2019-08-23 00:05:27 42605: request is in queue: 1dd5.073f.5d5f0397
2019-08-23 00:05:27 42605: request 1dd5.073f.5d5f0397 registering time: 663 msec
2019-08-23 00:05:28 42303: waiting for 42605 to be finished
2019-08-23 00:05:28 42303: 42605 finished; waiting time: 0 ms
2019-08-23 00:05:29 43188: candidate list for 1dd5.073f.5d5f0397; 2 records
2019-08-23 00:05:29 43188: candidate list file size: 381
2019-08-23 00:05:29 43188: candidate list sent for: 1dd5.073f.5d5f0397

그래서 로그 파일의 모든 매핑을 읽고 해당 매핑에 대한 두 작업 사이를 계산하는 스크립트를 만들었습니다. 위의 로그는 1dd5.073f.5d5f0397지도를 예로 사용합니다.

이것은 또한 나의 완전한 스크립트입니다.

#!/bin/bash

for i in $(grep 'incoming request:' a8.svrf.ear | sed 's/^.*: //' | awk -F'[ ]' '{print $1}')
do
    var0=$i

    TIME1=$(grep 'incoming request:' a8.svrf.ear | awk -F'[ ]' '{print $2}')

    TIME2=$(grep 'candidate list sent for:' a8.svrf.ear | grep "$var0" | awk -F'[ ]' '{print $2}')

    SEC1=$(date +%s -d "${TIME1}")

    SEC2=$(date +%s -d "${TIME2}")

    DIFFSEC=$(expr "${SEC2}" - "${SEC1}")

    echo Map "${var0}" >> /home/st/anil/test.txt

    echo Start "${TIME1}" >> /home/st/anil/test.txt
    echo Finish "${TIME2}" >> /home/st/anil/test.txt

    echo Took "${DIFFSEC}" seconds >> /home/st/anil/test.txt

    echo Took $(date +%H:%M:%S -ud @"${DIFFSEC}") >>/home/st/anil/test.txt

    echo =========================================================================


done

내 코드에서는 기본적으로 for 루프를 사용하여 모든 맵을 얻으려고 하고 각 맵에 대해 2개의 작업에 대한 시간을 구하고 시차를 찾으려고 시도하지만 결과가 예상치 못한 것입니다.

=========================================================================
...
34\n11:33:42\n11:33:42\n11:33:47’
expr: non-integer argument
date: invalid date ‘@’
=========================================================================
date: invalid date ‘00:01:37\n00:05:27\n00:09:49\n00:11:18\n00:12:02\n00:12:28\n00:12:52\n00:13:24\n00:15:10\n00:16:
...

또한 출력 txt 파일에서 각 지도에 대해 비슷한 상황이 발생합니다.

Map 1dd5.0721.5d5f02b1
Start 00:01:37
00:05:27
00:09:49
00:11:18
00:12:02
00:12:28
00:12:52
00:13:24
00:15:10
00:16:05
00:22:36
00:23:14
00:23:44
00:24:15
00:25:26
00:26:07
00:27:04
00:27:34
...
Finish 
Took  seconds
Took
=========================================================================

내 실수를 지적해 주시면 기쁘겠습니다. 감사해요

답변1

#!/usr/bin/perl

use strict;

use Date::Parse;
use Date::Format;

# hash arrays to keep the start and ending times for each request id.
my %start = ();
my %end = ();

# the @order array is used to preserve the order that we saw request ids,
# so we can print them out in the same order.
my @order;

while(<>) {
  # skip lines we're not interested in
  next unless (m/incoming request:|candidate list sent for:/);
  chomp;  # strip trailing linefeed

  # split input line into array @F on white-space separated fields.
  my @F = split;
  # and get the timestamp of the log entry
  my $timestamp = join(" ", @F[0..1]);

  if (m/incoming request:/) {
    my $reqid = $F[5];
    if (!defined($start{$reqid})) { push @order, $reqid };

    $start{$reqid} = $timestamp;

  } elsif (m/candidate list sent for:/) {
    my $reqid = $F[7];
    $end{$reqid} = $timestamp;
  };

};

foreach my $reqid (@order) {
    my $seconds = str2time($end{$reqid}) - str2time($start{$reqid});
    my $hms = time2str("%H:%M:%S", $seconds, "0");
    my $s = time2str("%H:%M:%S", str2time($start{$reqid}));
    my $e = time2str("%H:%M:%S", str2time($end{$reqid}));

    print <<__EOF__
Map $reqid
Start $s
Finish $e
Took $seconds seconds
Took $hms
=========================================================================

__EOF__
}

예를 들어 다른 이름으로 저장 anil.pl하고 실행 가능하게 만듭니다 chmod +x anil.pl.

샘플 입력의 출력은 다음과 같습니다.

$ ./anil.pl a8.svrf.ear 
Map 1dd5.073f.5d5f0397
Start 00:05:27
Finish 00:05:29
Took 2 seconds
Took 00:00:02
=========================================================================

동일한 알고리즘을 bash에서 구현할 수 있지만 (IMO) 읽고 이해하기가 더 어렵고 bash 배열 변수는 참조 방법 때문에 사용하기가 어렵습니다. 그리고 훨씬 느리게 실행됩니다.

예를 들어:

#!/bin/bash

declare -A start end
declare -a order

while read -r -a F ; do

  [ "${F[3]} ${F[4]}" != "incoming request:" ] \
    && [ "${F[3]} ${F[6]}" != "candidate for:" ] \
    && continue

  ts="${F[0]} ${F[1]}"

  if [ "${F[3]}" = "incoming" ] ; then
    reqid="${F[5]}"
    [ -v start[$reqid] ] || order+=( "$reqid" )
    start["$reqid"]="$ts"

  elif [ "${F[3]}" = "candidate" ] ; then
    reqid="${F[7]}"
    end["$reqid"]="$ts"
  fi

done <(cat "$@")

for reqid in "${order[@]}"; do
  start=$(date -d "${start[$reqid]}" +%s)
  end=$(date -d "${end[$reqid]}" +%s)
  seconds=$(( $end - $start ))
  hms=$(TZ=UTC date -d "@$seconds" "+%H:%M:%S")
  s=$(date -d "${start[$reqid]}" "+%H:%M:%S")
  e=$(date -d "${end[$reqid]}" "+%H:%M:%S")

cat <<__EOF__
Map $reqid
Start $s
Finish $e
Took $seconds seconds
Took $hms
=========================================================================

__EOF__

done

-v참고: 테스트 운영자가 변수가 존재하는지 확인하려면 bash v4.3 이상이 필요합니다 .

답변2

귀하의 오류를 재현할 수 없습니다. /home/st가 없기 때문에 출력 파일을 매개변수화하기 위해 변경했습니다... 언급한 바와 같이:

#!/bin/bash

for i in $(grep 'incoming request:' a8.svrf.ear | sed 's/^.*: //' | awk -F'[ ]' '{print $1}')
do
    var0=$i

    TIME1=$(grep 'incoming request:' a8.svrf.ear | awk -F'[ ]' '{print $2}')

    TIME2=$(grep 'candidate list sent for:' a8.svrf.ear | grep "$var0" | awk -F'[ ]' '{print $2}')

    SEC1=$(date +%s -d "${TIME1}")

    SEC2=$(date +%s -d "${TIME2}")

    DIFFSEC=$(expr "${SEC2}" - "${SEC1}")

        OUT=/home/st/anil/test.txt
        OUT=t1
        rm -f $OUT
    # echo Map "${var0}" >> /home/st/anil/test.txt
    echo Map "${var0}" >> $OUT

    # echo Start "${TIME1}" >> /home/st/anil/test.txt
    echo Start "${TIME1}" >> $OUT
    # echo Finish "${TIME2}" >> /home/st/anil/test.txt
    echo Finish "${TIME2}" >> $OUT

    # echo Took "${DIFFSEC}" seconds >> /home/st/anil/test.txt
    echo Took "${DIFFSEC}" seconds >> $OUT

    # echo Took $(date +%H:%M:%S -ud @"${DIFFSEC}") >>/home/st/anil/test.txt
    echo Took $(date +%H:%M:%S -ud @"${DIFFSEC}") >> $OUT

    echo =========================================================================


done

출력 파일 t1에는 다음이 포함됩니다.

Map 1dd5.073f.5d5f0397
Start 00:05:27
Finish 00:05:29
Took 2 seconds
Took 00:00:02

이것은 다음과 같은 시스템에 있습니다.

OS, ker|rel, machine: Linux, 3.16.0-7-amd64, x86_64
Distribution        : Debian 8.11 (jessie) 
bash GNU bash 4.3.30
date (GNU coreutils) 8.23

파일을 설정하려면 2개의 OUT 할당을 바꾸면 됩니다.

행운을 빕니다... 건배, drl

관련 정보