Sybase 오류 로그를 확인하려면 sed/awk 명령 쉘 스크립트에 대한 도움이 필요합니다.

Sybase 오류 로그를 확인하려면 sed/awk 명령 쉘 스크립트에 대한 도움이 필요합니다.

저는 Sybase의 위대한 전문가인 Mr. Rob Verschoor가 작성한 쉘 스크립트를 사용해 왔습니다.여기. 이 작업은 cron 작업을 통해 한 시간에 한 번씩 호출되며 키워드가 오류 로그의 사전 정의된 키워드와 일치하면 이메일을 보냅니다. 쉽게 참조할 수 있도록 문제를 일으킬 수 있는 코드를 아래에 게시했습니다.

 LAST_MARKER=$(${AWK} '/'$MARKER'/ { a=NR } END { print a }' $LOGFILE_COPY)
  LAST_MARKER=`echo "$LAST_MARKER+0"|bs`
 if [ ! "$LAST_MARKER" = "" ]
   then
      sed "1,${LAST_MARKER}d" $LOGFILE_COPY > $TMP.x
      cp $TMP.x $LOGFILE_COPY
   fi

이것은 행 1 다음에 행을 추가하는 것을 제외하고는 지난 2년 동안 아무런 문제 없이 잘 작동했습니다. 내 입장에서는 다음과 같습니다.

LAST_MARKER=`echo "$LAST_MARKER+0"|bs`

이는 과학적인 형식으로 제공되는 올바른 숫자 형식으로 반환된 행 수의 형식을 지정하기 위한 것입니다.

거의 매초 추적 메시지로 오류 로그를 채우는 모니터링 도구를 비활성화한 후 지난 며칠 동안 마지막 태그를 찾는 데 문제가 있는 것 같습니다. 따라서 기본적으로 마지막 태그부터 새 태그까지 행 항목이 많았고 아무런 문제도 없었습니다. 이제 이 도구를 비활성화한 후 근무 외 시간에는 활동이 없으므로 마지막 태그와 새 태그가 후속 라인이 됩니다.

이전에는 많은 메시지가 포함된 오류 로그가 다음과 같았습니다.

00:0005:00000:00514:2020/04/17 10:15:59.92 server  _Marker_For_Checking_Errorlog_
00:0005:00000:00514:2020/04/17 10:15:59.92 server  _Marker_End_
...
0:0002:00000:00608:2020/04/16 11:12:40.88 server  DBCC TRACEON 3604, SPID 608
00:0002:00000:00608:2020/04/16 11:12:40.88 server  DBCC TRACEOFF 3604, SPID 608
00:0006:00000:00660:2020/04/16 11:13:40.47 server  DBCC TRACEON 3604, SPID 660
00:0006:00000:00660:2020/04/16 11:13:40.47 server  DBCC TRACEOFF 3604, SPID 660
00:0006:00000:00664:2020/04/16 11:13:40.51 server  DBCC TRACEON 3604, SPID 664
00:0006:00000:00664:2020/04/16 11:13:40.51 server  DBCC TRACEOFF 3604, SPID 664
00:0002:00000:00608:2020/04/16 11:13:40.54 server  DBCC TRACEON 3604, SPID 608
00:0002:00000:00608:2020/04/16 11:13:40.54 server  DBCC TRACEOFF 3604, SPID 608
00:0006:00000:00660:2020/04/16 11:13:40.87 server  DBCC TRACEON 3604, SPID 660
00:0006:00000:00660:2020/04/16 11:13:40.87 server  DBCC TRACEOFF 3604, SPID 660
00:0004:00000:00608:2020/04/16 11:14:40.92 server  DBCC TRACEOFF 3604, SPID 608
...
00:0005:00000:00514:2020/04/17 11:15:59.92 server  _Marker_For_Checking_Errorlog_
00:0005:00000:00514:2020/04/17 11:15:59.92 server  _Marker_End_

이제 오류 로그는 다음과 같습니다.

    00:0004:00000:00974:2020/04/17 09:15:28.80 server  _Marker_For_Checking_Errorlog_
    00:0004:00000:00974:2020/04/17 09:15:38.80 server  _Marker_End_
    00:0005:00000:00514:2020/04/17 10:15:59.92 server  _Marker_For_Checking_Errorlog_
    00:0005:00000:00514:2020/04/17 10:15:59.92 server  _Marker_End_
    00:0003:00000:00030:2020/04/17 11:16:01.51 server  _Marker_For_Checking_Errorlog_
    00:0003:00000:00030:2020/04/17 11:16:01.51 server  _Marker_End_

이 도구는 이전 태그와 마지막 태그를 구분할 수 없기 때문에 3~4시간 전에 발생한 오류를 계속해서 보냅니다. 지난 시간 내용의 오류 로그에 아무것도 기록되지 않아 오류 메일을 보내서는 안 됩니다.

저는 쉘 스크립팅 전문가가 아니므로 이에 대한 도움을 주시면 감사하겠습니다.

편집: 지난 1시간(3시 15분에서 4시 15분 사이) 내에 미리 정의된 일치 키워드가 있었기 때문에 이 도구의 올바른 동작은 4시 15분(예정된 시간)에 다음 이메일을 보내는 것입니다.

Checking ASE errorlog
Fri Apr 17 04:16:06 WAT 2020
Server=Sybaseprd
Errorlog=/mount/ASE-15_0/install/Sybaseprd.log
00:0006:00000:00061:2020/04/17 04:03:37.15 server  Error: 1621, Severity: 18, State: 1
00:0006:00000:00061:2020/04/17 04:03:37.15 server  Type '16' not allowed before login.
00:0004:00000:00668:2020/04/17 04:03:42.17 server  Error: 1621, Severity: 18, State: 1
00:0004:00000:00668:2020/04/17 04:03:42.17 server  Type '16' not allowed before login.
00:0004:00000:00100:2020/04/17 04:03:42.17 server  Error: 1621, Severity: 18, State: 1
00:0004:00000:00100:2020/04/17 04:03:42.17 server  Type '16' not allowed before login.
00:0012:00000:00000:2020/04/17 04:03:49.30 kernel  ksmask__rpacket: Invalid tdslength value 21536, kpid: 268895208
00:0003:00000:00932:2020/04/17 04:04:59.20 server  Error: 1621, Severity: 18, State: 1
00:0003:00000:00932:2020/04/17 04:04:59.20 server  Type '3' not allowed before login.
9 error lines found in errorlog for ASE server 'SybasePrd'
(end)

잘못된 동작은 다음과 같습니다.

Checking ASE errorlog
Fri Apr 17 05:16:01 WAT 2020
Server=SybasePrd
Errorlog=/mount/ASE-15_0/install/Sybaseprd.log
00:0006:00000:00061:2020/04/17 04:03:37.15 server  Error: 1621, Severity: 18, State: 1
00:0006:00000:00061:2020/04/17 04:03:37.15 server  Type '16' not allowed before login.
00:0004:00000:00668:2020/04/17 04:03:42.17 server  Error: 1621, Severity: 18, State: 1
00:0004:00000:00668:2020/04/17 04:03:42.17 server  Type '16' not allowed before login.
00:0004:00000:00100:2020/04/17 04:03:42.17 server  Error: 1621, Severity: 18, State: 1
00:0004:00000:00100:2020/04/17 04:03:42.17 server  Type '16' not allowed before login.
00:0012:00000:00000:2020/04/17 04:03:49.30 kernel  ksmask__rpacket: Invalid tdslength value 21536, kpid: 268895208
00:0003:00000:00932:2020/04/17 04:04:59.20 server  Error: 1621, Severity: 18, State: 1
00:0003:00000:00932:2020/04/17 04:04:59.20 server  Type '3' not allowed before login.
9 error lines found in errorlog for ASE server 'SybasePRD'
(end)

위 작업은 5시 15분에 실행되며 4시 15분과 5시 15분 사이에 일치하는 행이 없으므로 아무 것도 보고되지 않습니다. 앞서 언급했듯이 프로그램은 다음 5개 일정, 즉 10시 15분까지 이메일을 계속 보내고, 위 오류 이후 오류 로그의 항목 수가 40개 정도를 초과하는 경우에만 중지됩니다.

따라서 원하는 결과는 위의 셸 스크립트에서 오류를 찾아 수정하여 지난 시간을 정확하게 확인하는 것입니다. 즉, 오류 로그의 마지막 표시부터 마지막 ​​줄까지 항목이 없으면 항목이 추가되지 않았음을 의미합니다. 마지막으로 시작을 확인한 후 다음과 같이 아무것도 확인하거나 보고하지 마세요.

00:0004:00000:00974:2020/04/17 09:15:28.80 server  _Marker_For_Checking_Errorlog_
    00:0004:00000:00974:2020/04/17 09:15:38.80 server  _Marker_End_
    00:0005:00000:00514:2020/04/17 10:15:59.92 server  _Marker_For_Checking_Errorlog_
    00:0005:00000:00514:2020/04/17 10:15:59.92 server  _Marker_End_
    00:0003:00000:00030:2020/04/17 11:16:01.51 server  _Marker_For_Checking_Errorlog_
    00:0003:00000:00030:2020/04/17 11:16:01.51 server  _Marker_End_

답변1

약간의 문제가 발생했습니다. 다시 문제를 해결할 수 있는지 살펴보겠습니다. 게시한 코드를 가정하면 다음과 같습니다.

 LAST_MARKER=$(${AWK} '/'$MARKER'/ { a=NR } END { print a }' $LOGFILE_COPY)
  LAST_MARKER=`echo "$LAST_MARKER+0"|bs`
 if [ ! "$LAST_MARKER" = "" ]
   then
      sed "1,${LAST_MARKER}d" $LOGFILE_COPY > $TMP.x
      cp $TMP.x $LOGFILE_COPY
   fi

다음과 같은 경우 $LOGFILE_COPY에서 $MARKER(있는 경우)를 포함하는 마지막 줄까지 텍스트를 제거하도록 설계되었습니다 tac.

tac "$LOGFILE_COPY" | awk -v m="$MARKER" '$0~m{exit} 1' | tac > "${TMP}.x" &&
mv "${TMP}.x" "$LOGFILE_COPY"

그렇지 않은 경우 tac다음 2단계 awk 전용 솔루션은 약간 느리게 실행되고 파이프의 입력에서는 작동하지 않지만 모든 크기의 입력 파일에서는 작동하지만 위의 tac 솔루션은 입력이 실패하면 파일이 너무 큽니다.

awk -v m="$MARKER" 'NR==FNR{if ($0~m) a=NR; next} FNR>a' "$LOGFILE_COPY" "$LOGFILE_COPY" > "${TMP}.x" &&
mv "${TMP}.x" "$LOGFILE_COPY"

너무 느린 경우(그렇다면 놀랄 것입니다) 조금 더 빨라질 수 있습니다(시작한 스크립트보다 확실히 더 빠를 것입니다).

start=$(awk -v m="$MARKER" '$0~m{a=NR} END{printf "%d\n", a+1; exit (a?0:1)}' "$LOGFILE_COPY") &&
tail -n +"$start" "$LOGFILE_COPY" > "${TMP}.x" &&
mv "${TMP}.x" "$LOGFILE_COPY"

이것이 당신의 문제를 해결해줄까요?


내레이터: 수정이 시작되는 방식입니다.원래 스크립트이들 중 가장 기본적인 문제를 해결하고 읽기 쉽게 만들려면 다음을 수행하세요.

#!/bin/sh

this_prog=$(basename "$0")

usage()
{
    echo "Usage:"
    echo " $this_prog <servername> <login> <passwd> [<errorlog-pathname> [\"all\"]]"
}

#---------------------------------------------------------------------------

# Check parameters
if [ $# -lt 3 ] || [ $# -gt 5 ]
then
    usage
    exit 1
fi

srv=$1
login=$2
psswd=$3
logfile=$4
opt=$5

#---------------------------------------------------------------------------

# Temp directory
tmp=$(mktemp -d) || exit 1
trap 'rm -f "$tmp"/*; rmdir "$tmp"; exit' 0

logfile_copy="${tmp}/errlog"

#---------------------------------------------------------------------------

# Some contants; do NOT change these !
dft_mailprog="your_mail_program" #DO NOT CHANGE -- go to the next section
dft_dba_mail="[email protected] [email protected]" #DO NOT CHANGE
#                                                   -- go to the next section

#---------------------------------------------------------------------------

# Some definitions
#
# mailprog must be set to your command-line mail program, like 'mail', 'mailx',
# etc. Later in this script, it is assumed that this mail program supports
# specifying the mail subject on the command line with the "-s" option.
# Should you use 'sendmail', you'll have to modify the script, or do without
# the mail subject, as 'sendmail' does not have this "-s" option.
# NT users may want to use 'ssmtp' (part of CygWin) as their mail
# program (also see comment below).
mailprog="$dft_mailprog"  # define your own setting here

# Define a list of people receiving results by email:
dba_mail="$dft_dba_mail"  # define your own setting here

skip_when_empty=NO # if YES, will not send mail when no errors were found

#---------------------------------------------------------------------------

# The marker strings below can be set to any arbitrary string, as long
# as this is unique and does not appear in the errorlog as part of any
# error message.
# These strings should not be changed anymore once you've started using
# this script.
marker="_Marker_For_Checking_Errorlog_"        #do not change this !
marker2="_Marker_End_"                #do not change this !

#--------------------------------------------------------------------------

# Change the below to 'gawk' (or 'nawk') if desired... This may be needed
# when hitting built-in max. string length limits in 'awk'. 'gawk' etc.
# tend to be more flexible.
AWK='awk'   # awk|gawk

#---------------------------------------------------------------------

# Check the mail program and email adresses have been defined
if [ "$mailprog" = "$dft_mailprog" ]
then
    echo ""
    echo "You must first define the variable 'mailprog' in this script;"
    echo "please set it to the name of your command-line mail program,"
    echo "like 'mail', 'mailx', etc."
    echo ""
    exit 1
fi

if [ "$dba_mail" = "$dft_dba_mail" ]
then
    echo ""
    echo "You must first define the variable 'dba_mail' in this script;"
    echo "please set it to a list of recipients."
    echo ""
    exit 1
fi

#--------------------------------------------------------------------------

# First locate the server errorlog
rm -f "$logfile_copy"

if [ "$logfile" = "" ]
then
    # Pick up the server errorlog pathname; first check if this is 12.0
    # or later to determine the method for doing this
    #
    cat << --EOF-- > "${tmp}/vchk.sql"
select name from sysobjects  -- used for ASE version check
where name = "sysqueryplans"
go
dbcc traceon(3604)
go
dbcc resource -- contains errorlog pathname
go
--EOF--

    # The below isql session also doubles as an ASE access and
    # privilege check.
    # Using 'cat' and piping the SQL to isql is done to make it run on
    # Windows NT as well ('cos the NT version of 'isql' won't understand
    # Unix-style pathnames)
    #
    < "${tmp}/vchk.sql" isql -S"$srv" -U"$login" -P"$psswd" -w500 > "${tmp}/vchk"

    if grep -q "CT-LIBRARY error" "${tmp}/vchk"
    then
        cat "${tmp}/vchk"
        echo ""
        echo "*** Note: in case you cannot connect because the ASE server is down,"
        echo "*** you can also specify the errorlog pathname explicitly."
        echo ""
        usage
        exit 1
    fi

    if grep "You must have the following role(s) to" "${tmp}/vchk"
    then
        exit 1
    fi

    # 18-Sep-2001 Corrected the test below: it said "-ne 1" instead of "-eq 1",
    # causing it to not to identify version pre-12.0 correctly
    # (thanks to Jean Loesch)
    #
    if [ "$(grep -c "sysqueryplans" "${tmp}/vchk")" -eq 1 ]
    then
        #--------------------------------------------------------------------------

        # This is ASE 12.0+, so locate the errorlog through @@errorlog (this isn't
        # really necessary, as dbcc resource would still work fine), but let's do
        # it anyway for educational purposes ...

        cat << --EOF-- > "${tmp}/ataterrlog.sql"
print @@errorlog
go
--EOF--

        < "${tmp}/ataterrlog.sql" isql -S"$srv" -U"$login" -P"$psswd" > "${tmp}/ataterrlog"

        logfile=$( "$AWK" '{print $1}' "${tmp}/ataterrlog" )

        #--------------------------------------------------------------------------

    else # not 12.0+

        # This is ASE pre-12.0, so locate the errorlog through dbcc resource (already
        # executed above)

        logfile=$( "$AWK" 'sub(/.*rerrfile=/,""){print $1}' "${tmp}/vchl" )

    fi

fi # if $logfile = ""

#--------------------------------------------------------------------------

# Errorlog file name known now, check if it's there
if [ ! -f "$logfile" ]
then
    echo "Error accessing server errorlog file [$logfile] - file not found"
    echo "Note: this script must be run on the same host where the "
    echo "ASE errorlog file is located."
    exit 1
fi

cp "$logfile" "$logfile_copy"

#--------------------------------------------------------------------------
# Check option parameter
#
if [ "$opt" = "" ]
then
    scan_all=N
else
    scan_all=Y
    echo "Scanning the entire ASE errorlog."
fi

#--------------------------------------------------------------------------

if [ "$scan_all" = "N" ]
then

    # Skip the part of the errorlog until the last marker

    # Note: if the next line gives an error message, use a different shell

    last_marker=$("$AWK" -v marker="$marker" '$0 ~ marker { a=NR } END { print a+0 }' "$logfile_copy")
    if [ ! "$last_marker" = "" ]
    then
        sed "1,${last_marker}d" "$logfile_copy" > "${tmp}/x" &&
        cp "${tmp}/x" "$logfile_copy"
    fi

fi

#--------------------------------------------------------------------------

# Create output file
{
    echo "Checking ASE errorlog"
    date
    echo "Server=$srv"
    echo "Errorlog=$logfile"
    echo ""
} > "${tmp}/out"

#--------------------------------------------------------------------------

# Finally... search for errors in the log file. The below set of search
# strings catches pretty much everything, but you can add any string here
# which you would also like to search for...
#
# Note that these strings indicate the presence of messages that should
# be investigated. Still, this may require further inspection of the
# errorlog, as more messages may be present which contain additional
# information.

grep -Ei '(warning|severity|fail|unmirror|mirror exit|not enough|error|suspect|corrupt|correct|deadlock|critical|allow|infect|error|full|problem|unable|not found|threshold|couldn|not valid|invalid|NO_LOG|logsegment|syslogs|stacktrace)' "$logfile_copy" |
grep -Evi '(successfull|_Marker_|(Suspect Granularity))' > "${tmp}/out2"

nrlines=$(wc -l "${tmp}/out2" | "$AWK" '{print $1}')

cat "${tmp}/out2" >> "${tmp}/out"

#--------------------------------------------------------------------------
#
echo "$nrlines error lines found in errorlog for ASE server '$srv'"

{
    echo ""
    echo "$nrlines error lines found in errorlog for ASE server '$srv'"
    echo ""
    echo "(end)"
} >> "${tmp}/out"

if [ "$skip_when_empty" = "NO" ] && [ "$nrlines" -eq 0 ]
then
    nrlines=1  # to force it into mailing anyway
fi

if [ "$nrlines" -gt 0 ]
then
    # Mail any error messages found to the list of recipients
    # (note: assumption is that the -s "subject" option is available for
    # your email program. Should you use "sendmail", it may not be
    # available, and you'd have to remove this option; when you're familiar
    # with 'sendmail', you can add the subject line yourself by inserting
    # header lines into the message file)
    #
    # Note for NT users: if you need a command-line mail program on NT,
    # consider 'ssmtp'. This is part of the CygWin package, which you need
    # anyway to run this script on NT. The download location for CygWin
    # is in the file header above.

    subj="Results of ASE errorlog check for '$srv'"
    "$mailprog" -s "$subj" "$dba_mail" < "${tmp}/out"
fi

#--------------------------------------------------------------------------

if [ "$scan_all" = "N" ]
then
    # Write a new marker to the server errorlog to indicate we got till here
    # Only do this when (i) no explicit errorlog pathname was specified and
    # (ii) only the last part of the log was scanned.

    cat << --EOF-- > "${tmp}/logprint.sql"
dbcc logprint ("$marker")
dbcc logprint ("$marker2") -- need a second line to avoid missing the last line
if @@error = 0 print "Writing marker to ASE errorlog."
-- note: in ASE 12.0, we could the more tidy "dbcc printolog(string)" instead
go
--EOF--

    < "${tmp}/logprint.sql" isql -S"$srv" -U"$login" -P"$psswd" | grep -Ev '(DBCC execution compl|(SA))'
fi

#--------------------------------------------------------------------------
# end
#

그 밖에도 개선할 수 있는 부분이 있고 아직 테스트되지 않았기 때문에 버그가 있을 수 있지만 원본과 비교하여 원본이 어떤 방식으로 변경되어야 하는지 아이디어를 얻을 수 있기를 바랍니다.

관련 정보