使用Shell验证日志文件

时间:2019-05-24 14:18:52

标签: shell validation if-statement logging awk

我想基于参考文件来验证日志文件,我使用过脚本,但是它并不美观,也不是最佳选择:

对于每一行,我要检查字段的值,  -字段7等于1我必须检查第16列和第17列     -字段7等于2我必须检查第25列,第27列和第30列     -字段7等于3我必须检查第18列,第24列和第31列     等。

#!/bin/bash

LOG=SMS.log



   awk -F\| ' {s=""}
    $4!=0  {printf "API has wrong value"; s="; " }
    $8=="" { printf "%sApplicationID is empty", s; s="; " }
    $9=="" { printf "%shttp request method is empty", s; s="; " }
    $7=="" { printf "%sOperationID is empty", s; s="; " }
    $13 !~ /0|1|2/ {printf "%sresult(0,1,2) has a wrong value", s; s="; " }

        # 1:create SMS

    $7=="1" && $18=="" {printf "%sSender is missing", s; s="; " }
    $7=="1" && $18 ~ /\/tel\:\+\*\*/ {printf "%sSender is cyphred !", s; s="; " }
    $7=="1" && $20=="" {printf "%sAddress is missing", s; s="; " }
    $7=="1" && $20 ~ /\/tel\:\+[0-9]/ {printf "%sAddress(es) is not cyphred", s; s="; " }
    $7=="1" && $10 ~ /\/tel\:\+\*\*/ {printf "%sSender is cyphred on URI !", s; s="; " }

        ## 2:subscribe 

    $7=="2" && $25=="" {printf "%sdestination is missing", s; s="; " }
    $7=="2" && $16=="201" && $27="" {printf "%sresourceId is missing", s; s="; "}

        #3:unsubscribe 
    $7=="2" && $16=="201" && $25="" {printf "%sresource is missing", s; s="; "}

    s { printf "\n"}
    s
     {printf "\n"}
' $LOG

是否可以将代码更新为更优化,更美观。 输出:

Application is empty; Operation is empty;  Http request method is empty
83ac|EDR|V1|0|V1|2019-05-14|7||||2019-05-14T08:00:42.758Z|8|0|||||XXXXX|||||||||789|||||||||5945548f|||||

2 个答案:

答案 0 :(得分:1)

我会这样:

awk -F'|' '
##### Error Detection
$4 != 0         { prtErr("ApiWrong") }
$8 == ""        { prtErr("AppIdEmpty") }
$9 == ""        { prtErr("HttpEmpty") }
$7 == ""        { prtErr("OpIdEmpty") }
$13 !~ /[012]/  { prtErr("RsltBad") }

$7 == 1 { # 1:create SMS
    if ( $18 == "" )             { prtErr("SndMiss") }
    if ( $18 ~ /\/tel:\+\*\*/ )  { prtErr("SndCyph") }
    if ( $20 == "" )             { prtErr("AddrMiss") }
    if ( $20 ~ /\/tel:\+[0-9]/ ) { prtErr("AddrNotCyph") }
    if ( $10 ~ /\/tel:\+\*\*/ )  { prtErr("SndCyphUri") }
}

$7 == 2 { # 2:subscribe
    if ( $25 == "" )             { prtErr("DestMiss") }
    if ( $16=="201" && $27=="" ) { prtErr("RsrcIdMiss") }
}

$7 == 3 { # 3:unsubscribe
    if ( $16=="201" && $25=="" ) { prtErr("RsrcMiss") }
}

##### Error Reporting
function prtDbg(code,str) { if (doDebug) prtMsg("DEBUG",code,str) }
function prtTrc(code,str) { if (doTrace) prtMsg("TRACE",code,str) }
function prtWrn(code,str) { prtMsg("WARNING",code,str) }
function prtErr(code,str) { prtMsg("ERROR",code,str) }

function prtMsg(level, code, str,       map, msg) {
    map["ApiWrong"]     = "API has wrong value"
    map["AppIdEmpty"]   = "ApplicationID is empty"
    map["HttpEmpty"]    = "http request method is empty"
    map["OpIdEmpty"]    = "OperationID is empty"
    map["RsltBad"]      = "result(0,1,2) has a wrong value"
    map["SndMiss"]      = "Sender is missing"
    map["SndCyph"]      = "Sender is cyphred !"
    map["AddrMiss"]     = "Address is missing"
    map["AddrNotCyph"   = "Address(es) is not cyphred"
    map["SndCyphUri"]   = "Sender is cyphred on URI !"
    map["DestMiss"]     = "destination is missing"
    map["RsrcIdMiss"]   = "resourceId is missing"
    map["RsrcMiss"]     = "resource is missing"
    map["default"]      = "Unknown error code"

    msg = (code in map ? map[code] : map["default"])

    printf "%s: %s[%d]: (%s) %s\n", level, FILENAME, FNR, code, msg | "cat>&2"
    if ( str != "" ) {
        printf "%s: %s[%d]:\t%s\n", $0 | "cat>&2"
    }
}


' "$log"

这可以将要打印的文本与错误指示分离,并集中/显示所有错误消息,以实现共同的外观/感觉,并能够在必要时添加额外的信息并整理检测错误的代码。我还展示了如何将错误与警告等分开(您选择代码中的哪一个),并添加跟踪/调试功能,如果愿意,您可以在代码中遍历所有功能,直到您执行这些操作,它们才会起作用在命令行上设置相关的“ do ...”标志。


更新以仅生成您要求的(未经测试的)特定输出:

BEGIN { FS="|" }

##### General processing including error detection
$4 != 0         { logErr("ApiWrong") }
$8 == ""        { logErr("AppIdEmpty") }
$9 == ""        { logErr("HttpEmpty") }
$7 == ""        { logErr("OpIdEmpty") }
$13 !~ /[012]/  { logErr("RsltBad") }

$7 == 1 { # 1:create SMS
    if ( $18 == "" )             { logErr("SndMiss") }
    if ( $18 ~ /\/tel:\+\*\*/ )  { logErr("SndCyph") }
    if ( $20 == "" )             { logErr("AddrMiss") }
    if ( $20 ~ /\/tel:\+[0-9]/ ) { logErr("AddrNotCyph") }
    if ( $10 ~ /\/tel:\+\*\*/ )  { logErr("SndCyphUri") }
}

$7 == 2 { # 2:subscribe
    if ( $25 == "" )             { logErr("DestMiss") }
    if ( $16=="201" && $27=="" ) { logErr("RsrcIdMiss") }
}

$7 == 3 { # 3:unsubscribe
    if ( $16=="201" && $25=="" ) { logErr("RsrcMiss") }
}

{ prtErrs() }

##### Error reporting primitives
function logErr(code) { _errs[code] }

function prtErrs(       code, map, msg, gotErrs, sep) {
    for (code in _errs) {
        gotErrs = 1
        break
    }

    if (gotErrs) {
        map["ApiWrong"]     = "API has wrong value"
        map["AppIdEmpty"]   = "ApplicationID is empty"
        map["HttpEmpty"]    = "http request method is empty"
        map["OpIdEmpty"]    = "OperationID is empty"
        map["RsltBad"]      = "result(0,1,2) has a wrong value"
        map["SndMiss"]      = "Sender is missing"
        map["SndCyph"]      = "Sender is cyphred !"
        map["AddrMiss"]     = "Address is missing"
        map["AddrNotCyph"]  = "Address(es) is not cyphred"
        map["SndCyphUri"]   = "Sender is cyphred on URI !"
        map["DestMiss"]     = "destination is missing"
        map["RsrcIdMiss"]   = "resourceId is missing"
        map["RsrcMiss"]     = "resource is missing"

        printf "%s: %s[%d]: ", "ERROR", FILENAME, FNR  | "cat>&2"
        for (code in _errs) {
            msg = (code in map ? map[code] : "Unknown error code (" code ")")
            printf "%s%s", sep, msg | "cat>&2"
            sep = "; "
        }
        printf "\n%s\n", $0 | "cat>&2"

        delete _errs
    }
}

如果您有用于数组和length(array)的GNU awk,那么我可以这样做:

BEGIN { FS="|" }

##### General processing including error detection
$4 != 0         { logErr("Wrong","API") }
$8 == ""        { logErr("Empty","AppId") }
$9 == ""        { logErr("Empty","Http request method") }
$7 == ""        { logErr("Empty","OperationID") }
$13 !~ /[012]/  { logErr("Wrong","Result(0,1,2)") }

$7 == 1 { # 1:create SMS
    if ( $18 == "" )             { logErr("Miss","Sender") }
    if ( $18 ~ /\/tel:\+\*\*/ )  { logErr("Cyph","Sender") }
    if ( $20 == "" )             { logErr("Miss","Address") }
    if ( $20 ~ /\/tel:\+[0-9]/ ) { logErr("NotCyph","Address(es)") }
    if ( $10 ~ /\/tel:\+\*\*/ )  { logErr("UriCyph","Sender") }
}

$7 == 2 { # 2:subscribe
    if ( $25 == "" )             { logErr("Miss","Destination") }
    if ( $16=="201" && $27=="" ) { logErr("Miss","ResourceId") }
}

$7 == 3 { # 3:unsubscribe
    if ( $16=="201" && $25=="" ) { logErr("Miss","Resource") }
}

{ prtErrs() }

##### Error reporting primitives
function logErr(type,item) { _errs[type][item] }

function prtErrs(       map, type, msg, item, sep) {
    if ( length(_errs) ) {
        map["Wrong"]   = "has wrong value"
        map["Empty"]   = "is empty"
        map["Miss"]    = "is missing"
        map["Cyph"]    = "is cyphred !"
        map["NotCyph"] = "is not cyphred"
        map["UriCyph"] = "is cyphred on URI !"

        printf "%s: %s[%d]: ", "ERROR", FILENAME, FNR  | "cat>&2"
        for (type in _errs) {
            msg = (type in map ? map[type] : "Unknown error type (" type ")")
            for (item in _errs[type]) {
                printf "%s%s %s", sep, item, msg  | "cat>&2"
                sep = "; "
            }
        }
        printf "\n%s\n", $0 | "cat>&2"

        delete _errs
    }
}

答案 1 :(得分:0)

您可以做的第一件事就是摆脱s变量。

#!/bin/bash

LOG=SMS.log

   awk -F\| '
    function add_error(message){
        error = error OFS message
    }

    $4!=0  {add_error("API has wrong value")}
    $8=="" {add_error("ApplicationID is empty")}
    $9=="" {add_error("http request method is empty")}
    $7=="" {add_error("OperationID is empty")}
    $13 !~ /0|1|2/ {add_error("result(0,1,2) has a wrong value")}

        # 1:create SMS

    $7=="1" && $18=="" {add_error("Sender is missing")}
    $7=="1" && $18 ~ /\/tel\:\+\*\*/ {add_error("Sender is cyphred !")}
    $7=="1" && $20=="" {add_error("Address is missing")}
    $7=="1" && $20 ~ /\/tel\:\+[0-9]/ {add_error("Address(es) is not cyphred")}
    $7=="1" && $10 ~ /\/tel\:\+\*\*/ {add_error("Sender is cyphred on URI !")}

        ## 2:subscribe 

    $7=="2" && $25=="" {add_error("destination is missing")}
    $7=="2" && $16=="201" && $27="" {add_error("resourceId is missing")}

        #3:unsubscribe 
    $7=="2" && $16=="201" && $25="" {add_error("resource is missing")}

    {
        print substr(error, length(OFS)+1); #Works even if error is empty
        error = "";
    }

' OFS="; " $LOG

我认为分析您的日志文件并创建一个新的日志文件有点奇怪。为什么不创建每个错误1列,每行/错误1/0值的csv?您的结果将更容易分析,并且包含您需要的所有信息。