কীভাবে দুটি টাইম স্ট্যাম্পের মধ্যে লগ বের করা যায়


25

আমি দুটি টাইমস্ট্যাম্পের মধ্যে সমস্ত লগ বের করতে চাই। কিছু লাইনে টাইমস্ট্যাম্প নাও থাকতে পারে তবে আমি সেই লাইনগুলিও চাই। সংক্ষেপে, আমি প্রতিটি লাইন চাই যা দুটি সময়ের স্ট্যাম্পের আওতায় আসে। আমার লগ কাঠামোটি দেখে মনে হচ্ছে:

[2014-04-07 23:59:58] CheckForCallAction [ERROR] Exception caught in +CheckForCallAction :: null
--Checking user--
Post
[2014-04-08 00:00:03] MobileAppRequestFilter [DEBUG] Action requested checkforcall

ধরুন আমি 2014-04-07 23:00এবং এর মধ্যে সমস্ত কিছু বের করতে চাই 2014-04-08 02:00

দয়া করে নোট করুন শুরুর সময় স্ট্যাম্প বা শেষের সময় স্ট্যাম্প লগের মধ্যে নাও থাকতে পারে তবে আমি এই দুটি টাইম স্ট্যাম্পের মধ্যে প্রতিটি লাইন চাই want



আপনার কি কেবলমাত্র একবারে বা প্রোগ্রামগতভাবে বিভিন্ন সময়ে এটি করা দরকার?
ব্র্যাচলে

আমি জিজ্ঞাসা করার কারণটি হ'ল কারণ আপনি যদি আক্ষরিক মানগুলি জানেন তবে আপনি দুটি প্রাসঙ্গিক গ্রেপ করতে পারেন (একটি প্রারম্ভিক ডিলিমিটারের পরে সবকিছু দখল করতে এবং অন্যটি শেষ সীমানারটিতে মুদ্রণ বন্ধ করতে) can যদি তারিখগুলি / সময়গুলি পরিবর্তিত হতে পারে, টু date -dকমান্ডের মাধ্যমে ব্যবহারকারীদের ইনপুট খাওয়ানো এবং অনুসন্ধানের ধরণটি তৈরি করতে এটি ব্যবহার করে সহজেই ফ্লাইতে এগুলি তৈরি করতে পারে ।
ব্র্যাচলে

@ রমেশ, রেফারেন্স করা প্রশ্নটি খুব বিস্তৃত।
ম্যাক্সচলেপজিগ

@ জোয়েলডাভিস: আমি এটি প্রোগ্রামগতভাবে করতে চাই। সুতরাং প্রতিবার আমার / টিএমপি লোকেশন স্থানে স্ট্যাম্পের মধ্যে লগগুলি বের করার জন্য কেবলমাত্র কাঙ্ক্ষিত টাইম স্ট্যাম্প প্রবেশ করতে হবে।
অমিত

উত্তর:


19

আপনি এটির awkজন্য ব্যবহার করতে পারেন :

$ awk -F'[]]|[[]' \
  '$0 ~ /^\[/ && $2 >= "2014-04-07 23:00" { p=1 }
   $0 ~ /^\[/ && $2 >= "2014-04-08 02:00" { p=0 }
                                        p { print $0 }' log

কোথায়:

  • -Fনিয়মিত এক্সপ্রেশন ব্যবহার করে অক্ষর [এবং ]ক্ষেত্র বিভাজক হিসাবে নির্দিষ্ট করে
  • $0 একটি সম্পূর্ণ লাইন রেফারেন্স
  • $2 তারিখের ক্ষেত্র উল্লেখ করে
  • p বুলিয়ান ভেরিয়েবল হিসাবে ব্যবহৃত হয় যা প্রকৃত মুদ্রণ রক্ষা করে
  • $0 ~ /regex/ সত্য যদি সত্যিকারের রেগেক্স ম্যাচ করে $0
  • >= ডিক্সোগ্রাফিকভাবে তুলনা স্ট্রিংয়ের জন্য ব্যবহৃত হয় (যেমন, সমান) strcmp() )

প্রকারভেদ

উপরের কমান্ড লাইনটি ডান-ওপেন সময়ের ব্যবধান ম্যাচ প্রয়োগ করে । বন্ধ বিরতি শব্দার্থবিজ্ঞান পেতে কেবল আপনার সঠিক তারিখ বৃদ্ধি করুন, যেমন:

$ awk -F'[]]|[[]' \
  '$0 ~ /^\[/ && $2 >= "2014-04-07 23:00"    { p=1 }
   $0 ~ /^\[/ && $2 >= "2014-04-08 02:00:01" { p=0 }
                                           p { print $0 }' log

আপনি যদি অন্য ফর্ম্যাটে টাইমস্ট্যাম্পগুলি মেলতে চান তবে আপনাকে পরিবর্তন করতে হবে $0 ~ /^\[/ সাব-এক্সপ্রেশনটি । নোট করুন যে এটি লিংকগুলি অফ / অফ লজিক থেকে কোনও টাইমস্ট্যাম্প ছাড়াই উপেক্ষা করবে।

উদাহরণস্বরূপ, টাইমস্ট্যাম্প বিন্যাসের জন্য YYYY-MM-DD HH24:MI:SS( []ধনুবিহীন) আপনি কমান্ডটি এভাবে পরিবর্তন করতে পারেন:

$ awk \
  '$0 ~ /^[0-9]{4}-[0-9]{2}-[0-9]{2} [0-2][0-9]:[0-5][0-9]:[0-5][0-9]/
      {
        if ($1" "$2 >= "2014-04-07 23:00")     p=1;
        if ($1" "$2 >= "2014-04-08 02:00:01")  p=0;
      }
    p { print $0 }' log

(দ্রষ্টব্য যে ক্ষেত্রের বিভাজকটিও পরিবর্তিত হয়েছে - ফাঁকা / খালি ফাঁকা স্থানান্তর, ডিফল্ট)


স্ক্রিপ্ট ভাগ করে নেওয়ার জন্য থ্যাঙ্কস তবে এটি শেষ টাইমস্ট্যাম্প চেক করছে না .. আপনি দয়া করে পরীক্ষা করতে পারেন। 2014-04-07 23:59:58 এর মতো লগগুলি থাকলে আমার কী জানতে দিন। আমি বন্ধনী ছাড়াই বোঝাচ্ছি
অমিত

@ অমিত, উত্তরটি আপডেট করেছেন
ম্যাক্সচলেপজিগ

যদিও আমি মনে করি না এটি একটি স্ট্রিং সমস্যা ( আমার উত্তর দেখুন ), আপনি সমস্ত পরীক্ষার পুনরাবৃত্তি না করে নিজেকে আরও বেশি পঠনযোগ্য এবং সম্ভবত আরও দ্রুত তৈরি করতে পারেন: $1 ~ /^[0-9]{4}-[0-9]{2}-[0-9]{2}/ && $2 ~/[0-2][0-9]:[0-5][0-9]:[0-5][0-9]/ { Time = $1" "$2; if (Time >= "2014-04-07 23:00" ) { p=1 } if (Time >= "2014-04-08 02:00:01" ) { p=0 } } p

হাই ম্যাক্স, আরও একটি ছোট সন্দেহ .. আমার যদি এপ্রিল-07-2014 10:51:17 এর মতো কিছু থাকে। তারপরে আমাকে কী পরিবর্তন করতে হবে .. আমি code$ 0 ~ / ^ [আজ | এজেড] {4} - [0-9] {2} - [0-9] {4} [0-2] [0-9 ]: [0-5] [0-9]: [0-5] [0-9] / && $ 1 "" $ 2> = "এপ্রিল -07-2014 11:00" {পি = 1} $ 0 ~ / ^ [আজ | এজেড] {4} - [0-9] {2} - [0-9] {4} [0-2] [0-9]: [0-5] [0-9]: [0 -5] [0-9] / && $ 1 "" $ 2> = "এপ্রিল -07-2014 12:00:01" {পি = 0} codeতবে এটি কার্যকর নয়
অমিত

@ ওক_এফটিডাব্লু, কোডটি এমনভাবে পরিবর্তন করেছেন যাতে রেজেক্স স্পষ্টভাবে ভাগ করে নেওয়া হয়েছে।
ম্যাক্সচলেপজিগ

12

পরীক্ষা করে দেখুন dategrephttps://github.com/mdom/dategrep

বর্ণনা:

ডেটেগ্রিপ তারিখের সাথে সীমাবদ্ধ মিলগুলির জন্য নামযুক্ত ইনপুট ফাইলগুলি অনুসন্ধান করে এবং স্টাডাউটে প্রিন্ট করে।

যদি ডেটাগ্রাইপ অনুসন্ধানযোগ্য ফাইলে কাজ করে তবে এটি বেশ দক্ষতার সাথে মুদ্রণের জন্য প্রথম এবং শেষ লাইনটি খুঁজে পেতে বাইনারি অনুসন্ধান করতে পারে। ডেটেগ্রেপ স্ট্যান্ডিনের কাছ থেকেও পড়তে পারে যদি একটি ফাইলের নাম আর্গুমেন্ট কেবল একটি হাইফেন হয় তবে এই ক্ষেত্রে এটি প্রতিটি রেখাকে পার্স করতে হবে যা ধীর হবে।

ব্যবহারের উদাহরণ:

dategrep --start "12:00" --end "12:15" --format "%b %d %H:%M:%S" syslog
dategrep --end "12:15" --format "%b %d %H:%M:%S" syslog
dategrep --last-minutes 5 --format "%b %d %H:%M:%S" syslog
dategrep --last-minutes 5 --format rsyslog syslog
cat syslog | dategrep --end "12:15" -

যদিও এই সীমাবদ্ধতাটি আপনার সঠিক প্রশ্নের জন্য এটি অনুপযুক্ত করে তুলতে পারে:

এই মুহুর্তে ডেটেগ্রেপ মারা যাবে কারণ এটি এমন একটি লাইন খুঁজে পেল যা পার্সযোগ্য নয়। ভবিষ্যতের সংস্করণে এটি কনফিগারযোগ্য হবে।


আমি এই কমান্ডটি সম্পর্কে কয়েকদিন আগেই onetingwell.org/post/81991115668/dategrep এর সৌজন্যে শিখেছি , তাই তাকে!
সিপিজিনিউসএমভিভি

3

প্রাসঙ্গিক গ্রেপগুলির জন্য awkGNU ব্যবহার করা বা একটি অ-মানক সরঞ্জামের একটি বিকল্প grep। জিএনইউ grepআপনাকে মুদ্রণের জন্য ইতিবাচক ম্যাচের পরে রেখার সংখ্যা -Aএবং প্রিন্ট করার -Bজন্য পূর্ববর্তী রেখাগুলি নির্দিষ্ট করতে দেবে উদাহরণস্বরূপ:

[davisja5@xxxxxxlp01 ~]$ cat test.txt
Ignore this line, please.
This one too while you're at it...
[2014-04-07 23:59:58] CheckForCallAction [ERROR] Exception caught in +CheckForCallAction :: null
--Checking user--
Post
[2014-04-08 00:00:03] MobileAppRequestFilter [DEBUG] Action requested checkforcall
we don't
want these lines.


[davisja5@xxxxxxlp01 ~]$ egrep "^\[2014-04-07 23:59:58\]" test.txt -A 10000 | egrep "^\[2014-04-08 00:00:03\]" -B 10000
[2014-04-07 23:59:58] CheckForCallAction [ERROR] Exception caught in +CheckForCallAction :: null
--Checking user--
Post
[2014-04-08 00:00:03] MobileAppRequestFilter [DEBUG] Action requested checkforcall

উপরেরটি মূলত grep10,000 টি রেখাগুলি মুদ্রণ করতে বলে যা আপনি যে প্যাটার্নটি শুরু করতে চান তার সাথে মেলে এবং কার্যকরভাবে আপনার আউটপুটটি যেখানে আপনি চান সেখানেই শুরু করে এবং শেষ অবধি যেতে হবে (আশা করি) যেখানে দ্বিতীয়টি egrepরয়েছে পাইপলাইন এটিকে কেবল শেষের ডিলিমিটার এবং এটির আগে 10,000 টি লাইনের সাথে লাইন প্রিন্ট করতে বলে। এই দু'জনের শেষ ফলাফল শুরু হচ্ছে যেখানে আপনি চাইছেন এবং যেখানে আপনি থামতে বলেছেন সেখানে পাস হচ্ছে না।

10,000 হ'ল এমন একটি সংখ্যা যা আমি এনেছি, আপনি যদি মনে করেন যে আপনার আউটপুটটি খুব দীর্ঘ হতে চলেছে a


শুরু এবং শেষের সীমাগুলির জন্য কোনও লগ এন্ট্রি না থাকলে এটি কীভাবে কাজ করবে? যদি ওপি 14:00 থেকে 15:00 এর মধ্যে সমস্ত কিছু চায় তবে 14:00 এর জন্য কোনও লগ প্রবেশ নেই, তাহলে?

এটি এর সাথে সাথে শব্দটিও দেখাবে sedযা আক্ষরিক মিলগুলিও অনুসন্ধান করছে। dategrepসম্ভবত প্রদত্ত সকলের মধ্যে সবচেয়ে সঠিক উত্তর (যেহেতু আপনি যে টাইমস্ট্যাম্পগুলি গ্রহণ করবেন সে সম্পর্কে আপনার "ফাজি" পেতে সক্ষম হওয়া প্রয়োজন) তবে উত্তরের মতো বলা হয়েছে, আমি কেবল এটি বিকল্প হিসাবে উল্লেখ করেছি। এটি বলেছিল, লগটি কাটা পরিকল্পিত পর্যাপ্ত আউটপুট উত্পন্ন করতে যথেষ্ট সক্রিয় থাকলে সম্ভবত প্রদত্ত সময়কালের জন্য কোনও ধরণের প্রবেশও হতে পারে।
ব্র্যাচলে

0

সেড ব্যবহার:

#!/bin/bash

E_BADARGS=23

if [ $# -ne "3" ]
then
  echo "Usage: `basename $0` \"<start_date>\" \"<end_date>\" file"
  echo "NOTE:Make sure to put dates in between double quotes"
  exit $E_BADARGS
fi 

isDatePresent(){
        #check if given date exists in file.
        local date=$1
        local file=$2
        grep -q "$date" "$file"
        return $?

}

convertToEpoch(){
    #converts to epoch time
    local _date=$1
    local epoch_date=`date --date="$_date" +%s`
    echo $epoch_date
}

convertFromEpoch(){
    #converts to date/time format from epoch
    local epoch_date=$1
    local _date=`date  --date="@$epoch_date" +"%F %T"`
    echo $_date

}

getDates(){
        # collects all dates at beginning of lines in a file, converts them to epoch and returns a sequence of numbers
        local file="$1"
        local state="$2"
        local i=0
        local date_array=( )
        if [[ "$state" -eq "S" ]];then
            datelist=`cat "$file" | sed -r -e "s/^\[([^\[]+)\].*/\1/" | egrep  "^[0-9]{4}-[0-9]{2}-[0-9]{2} [0-9]{2}:[0-9]{2}:[0-9]{2}"`
        elif [[ "$state" -eq "E" ]];then
            datelist=`tac "$file" | sed -r -e "s/^\[([^\[]+)\].*/\1/" | egrep  "^[0-9]{4}-[0-9]{2}-[0-9]{2} [0-9]{2}:[0-9]{2}:[0-9]{2}"`

        else
            echo "Something went wrong while getting dates..." 1>&2
            exit 500
        fi

        while read _date
            do
                epoch_date=`convertToEpoch "$_date"`
                date_array[$i]=$epoch_date
                #echo "$_date" "$epoch_date" 1>&2

            (( i++ ))
            done<<<"$datelist"
        echo ${date_array[@]}   


}

findneighbours(){
    # search next best date if date is not in the file using recursivity
    IFS="$old_IFS"
    local elt=$1
    shift
    local state="$1"
    shift
    local -a array=( "$@" ) 

    index_pivot=`expr ${#array[@]} / 2`
    echo "#array="${#array[@]} ";array="${array[@]} ";index_pivot="$index_pivot 1>&2
    if [ "$index_pivot" -eq 1 -a ${#array[@]} -eq 2 ];then

        if [ "$state" == "E" ];then
            echo ${array[0]}
        elif [ "$state" == "S" ];then
            echo ${array[(( ${#array[@]} - 1 ))]} 
        else
            echo "State" $state "undefined" 1>&2
            exit 100
        fi

    else
        echo "elt with index_pivot="$index_pivot":"${array[$index_pivot]} 1>&2
        if [ $elt -lt ${array[$index_pivot]} ];then
            echo "elt is smaller than pivot" 1>&2
            array=( ${array[@]:0:(($index_pivot + 1)) } )
        else
            echo "elt is bigger than pivot" 1>&2
            array=( ${array[@]:$index_pivot:(( ${#array[@]} - 1 ))} ) 
        fi
        findneighbours "$elt" "$state" "${array[@]}"
    fi
}



findFirstDate(){
    local file="$1"
    echo "Looking for first date in file" 1>&2
    while read line
        do 
            echo "$line" | egrep -q "^\[[0-9]{4}-[0-9]{2}-[0-9]{2} [0-9]{2}:[0-9]{2}:[0-9]{2}\]" &>/dev/null
            if [ "$?" -eq "0" ]
            then
                #echo "line=" "$line" 1>&2
                firstdate=`echo "$line" | sed -r -e "s/^\[([^\[]+)\].*/\1/"`
                echo "$firstdate"
                break
            else
                echo $? 1>&2
            fi
        done< <( cat "$file" )



}

findLastDate(){
    local file="$1"
    echo "Looking for last date in file" 1>&2
    while read line
        do 
            echo "$line" | egrep -q "^\[[0-9]{4}-[0-9]{2}-[0-9]{2} [0-9]{2}:[0-9]{2}:[0-9]{2}\]" &>/dev/null
            if [ "$?" -eq "0" ]
            then
                #echo "line=" "$line" 1>&2
                lastdate=`echo "$line" | sed -r -e "s/^\[([^\[]+)\].*/\1/"`
                echo "$lastdate"
                break
            else
                echo $? 1>&2
            fi
        done< <( tac "$file" )


}

findBestDate(){

        IFS="$old_IFS"
        local initdate="$1"
        local file="$2"
        local state="$3"
        local first_elts="$4"
        local last_elts="$5"
        local date_array=( )
        local initdate_epoch=`convertToEpoch "$initdate"`   

        if [[ $initdate_epoch -lt $first_elt ]];then
            echo `convertFromEpoch "$first_elt"`
        elif [[ $initdate_epoch -gt $last_elt ]];then
            echo `convertFromEpoch "$last_elt"` 

        else
            date_array=( `getDates "$file" "$state"` )
            echo "date_array="${date_array[@]} 1>&2
            #first_elt=${date_array[0]}
            #last_elt=${date_array[(( ${#date_array[@]} - 1 ))]}

            echo `convertFromEpoch $(findneighbours "$initdate_epoch" "$state" "${date_array[@]}")`

        fi

}


main(){
    init_date_start="$1"
    init_date_end="$2"
    filename="$3"
    echo "problem start.." 1>&2
    date_array=( "$init_date_start","$init_date_end"  )
    flag_array=( 0 0 )
    i=0
    #echo "$IFS" | cat -vte
    old_IFS="$IFS"
    #changing separator to avoid whitespace issue in date/time format
    IFS=,
    for _date in ${date_array[@]}
    do
        #IFS="$old_IFS"
        #echo "$IFS" | cat -vte
        if isDatePresent "$_date" "$filename";then
            if [ "$i" -eq 0 ];then 
                echo "Starting date exists" 1>&2
                #echo "date_start=""$_date" 1>&2
                date_start="$_date"
            else
                echo "Ending date exists" 1>&2
                #echo "date_end=""$_date" 1>&2
                date_end="$_date"
            fi

        else
            if [ "$i" -eq 0 ];then 
                echo "start date $_date not found" 1>&2
            else
                echo "end date $_date not found" 1>&2
            fi
            flag_array[$i]=1
        fi
        #IFS=,
        (( i++ ))
    done

    IFS="$old_IFS"
    if [ ${flag_array[0]} -eq 1 -o ${flag_array[1]} -eq 1 ];then

        first_elt=`convertToEpoch "$(findFirstDate "$filename")"`
        last_elt=`convertToEpoch "$(findLastDate "$filename")"`
        border_dates_array=( "$first_elt","$last_elt" )

        #echo "first_elt=" $first_elt "last_elt=" $last_elt 1>&2
        i=0
        IFS=,
        for _date in ${date_array[@]}
        do
            if [ $i -eq 0 -a ${flag_array[$i]} -eq 1 ];then
                date_start=`findBestDate "$_date" "$filename" "S" "${border_dates_array[@]}"`
            elif [ $i -eq 1 -a ${flag_array[$i]} -eq 1 ];then
                date_end=`findBestDate "$_date" "$filename" "E" "${border_dates_array[@]}"`
            fi

            (( i++ ))
        done
    fi


    sed -r -n "/^\[${date_start}\]/,/^\[${date_end}\]/p" "$filename"

}


main "$1" "$2" "$3"

এটি একটি ফাইলে কপি করুন। আপনি যদি ডিবাগিং তথ্যটি দেখতে না চান, তবে ডিবাগিং স্ট্ডারকে প্রেরণ করা হয় কেবল "2> / dev / নাল" যুক্ত করুন


1
এই টাইম স্ট্যাম্প না লগ ফাইল প্রদর্শন করবে না।
অমিত

@ আমিত, হ্যাঁ এটা হবে, আপনি চেষ্টা করেছেন?
ইউএনএক্স

@ মিস্টারসো, এটি কাজ করবে না কারণ 22:30 এ লগ এন্ট্রি না থাকলে, পরিসীমাটি শেষ করা হবে না। ওপি যেমন উল্লেখ করেছে, শুরু এবং থামার সময়গুলি লগগুলিতে নাও থাকতে পারে। এটি আপনার কাজ করার জন্য আপনি আপনার রেজেক্সটিকে টুইঙ্ক করতে পারেন, তবে আপনি রেজোলিউশনটি শিথিল করে ফেলবেন এবং কখনই আগে থেকে গ্যারান্টি দেওয়া হবে না যে সঠিক সময়সীমাটি শেষ হয়ে যাবে।

@awk_FTW এটি একটি উদাহরণ, আমি অমিতের দেওয়া টাইমস্ট্যাম্পগুলি ব্যবহার করিনি। আবার রিজেক্স ব্যবহার করা যেতে পারে। আমি সম্মত হয়েছি যে স্পষ্টভাবে সরবরাহ করা বা টাইমস্ট্যাম্প রেজেক্স ম্যাচ না থাকলে টাইমস্ট্যাম্প উপস্থিত না থাকলে এটি কাজ করবে না। আমি শীঘ্রই এটির উন্নতি করব ..
ইউএনএক্স

"ওপি যেমন উল্লেখ করেছে, শুরু এবং থামার সময়গুলি লগগুলিতে নাও থাকতে পারে।" না, আবার ওপি পড়ুন। ওপি বলেছে যে সেই সমস্ত লোক উপস্থিত থাকবেন কিন্তু হস্তক্ষেপের রেখাগুলি অগত্যা কোনও টাইমস্ট্যাম্প দিয়ে শুরু হবে না। এমনকি স্টপ সময়টি উপস্থিত নাও হতে পারে তা বোঝার কোনও অর্থ নেই। আপনি যদি কখনই কোনও সরঞ্জামকে কীভাবে বলতে পারেন যে থামার চিহ্নটি সেখানে থাকার গ্যারান্টিযুক্ত না থাকে তবে কোথায় থামতে হবে? কোথায় প্রক্রিয়াজাতকরণ বন্ধ করবেন তা বলার জন্য সরঞ্জামটি দেওয়ার কোনও মানদণ্ড থাকবে না।
ব্র্যাচলে
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.