Сценарий оболочки НЕТ строк добавляются из входного файла с использованием отметки времени - PullRequest
0 голосов
/ 09 апреля 2020

INPUT-файл имеет значение /var/log/error.log

 Apr 7 05:58:05 ip-172-31-19-169 kernel: BIOS-provided physical RAM map: critical     
 Apr 7 09:21:12 ip-172-31-19-169 kernel: BIOS-provided physical RAM map: critical     
 Apr 7 13:05:57 ip-172-31-19-169 kernel: BIOS-provided physical RAM map: critical

Мой сценарий

#!/bin/ksh

d1=$(date --date="-50 min" "+%b %_d %H:%M")

d2=$(date "+%b %_d %H:%M")

while read line; do

    [[ $line > $d1 && $line < $d2 || $line =~ $d2 ]] && echo $line | egrep -wi '[Cc]ritical' >> /mnt/dinesh/ksh-scripts/draft/text.txt

done < /var/log/error.log

Во время выполнения моего сценария системное время составляет около 13:06:05

Так что в соответствии со сценарием /mnt/dinesh/ksh-scripts/draft/text.txt ФАЙЛ должен иметь последнюю запись моего error.log Но в mnt/dinesh/ksh-scripts/draft/text.txt.

не добавляются никакие строки. Может кто-нибудь помочь мне решить эту проблему.

1 Ответ

0 голосов
/ 21 апреля 2020

Существенная проблема с логикой c кода заключается в том, что для сравнения дат используется сравнение строк. В сравнении строк Apr 17 меньше Apr 2 и Feb 1 меньше Jan 1.

Вместо этого шаблон в оболочках POSIX должен преобразовывать дату в секунды, начиная с 1970-01-01 00:00:00 UT C, также известный как «эпоха».

Для команды date укажите время в формате секунд, чтобы установить FORMAT в +%s, например, date +%s.

В ksh есть спецификатор формата printf, T, для преобразования строки, такой как строка, считываемая из файла журнала, в число секунд с начала эпохи. См. https://www.unix.com/302701867-post4.html?s=860f6c21431fa69ef9e083161f93739d

Вот ваш сценарий, переписанный для устранения ошибки logi c путем преобразования сравнений в секунды:

#!/bin/ksh
ERROR_LOG=/tmp/error.log
FILTERED_ERROR_LOG=/tmp/text

now_secs=$(date "+%s")
start_secs=$(date --date="-30000 min" +%s)

while read line; do
    # Below stderr is redirected since I can't figure out how to get just the first part
    # of the date parsed skipping the other stuff after that.
    # Even though there is warning printed, the time comes out parsed correctly
    line_secs=$(printf "%(%#)T" "$line" 2>/dev/null)

    if (( $line_secs > $start_secs && line_secs < now_secs || line_secs == now_secs )); then
        echo $line | egrep -wi '[Cc]ritical' >> $FILTERED_ERROR_LOG
    fi
done < $ERROR_LOG

Некоторые дополнительные примечания.

Похоже, вы более широко можете понять, что такое отладка таких проблем. Как вы можете видеть, если задать в StackOverflow такую ​​специфическую проблему, c, то, вероятно, не будет представлять большого интереса для других, поэтому может потребоваться некоторое время, чтобы получить какой-либо значимый ответ.

Опция трассировки basi c равна -x. Давайте запустим это на приведенном выше скрипте:

ksh -x /tmp/bug.ksh
+ ERROR_LOG=/tmp/error.log
+ FILTERED_ERROR_LOG=/tmp/text
+ date +%s
+ now_secs=1587473181
+ date '--date=-30000 min' +%s
+ start_secs=1585673181
+ 0< /tmp/error.log
+ read line
+ printf '%(%#)T' 'Apr 7 05:58:05 ip-172-31-19-169 kernel: BIOS-provided physical RAM map: critical'
+ 2> /dev/null
+ line_secs=1586253485
+ (( 1586253485 > 1585673181 && line_secs < now_secs || line_secs == now_secs ))
+ egrep -wi '[Cc]ritical'
+ echo Apr 7 05:58:05 ip-172-31-19-169 kernel: BIOS-provided physical RAM map: critical
+ 1>> /tmp/text
+ read line
+ printf '%(%#)T' 'Apr 7 09:21:12 ip-172-31-19-169 kernel: BIOS-provided physical RAM map: critical'
+ 2> /dev/null
+ line_secs=1586265672
+ (( 1586265672 > 1585673181 && line_secs < now_secs || line_secs == now_secs ))
+ egrep -wi '[Cc]ritical'
+ echo Apr 7 09:21:12 ip-172-31-19-169 kernel: BIOS-provided physical RAM map: critical
+ 1>> /tmp/text
+ read line
+ printf '%(%#)T' 'Apr 7 13:05:57 ip-172-31-19-169 kernel: BIOS-provided physical RAM map: critical'
+ 2> /dev/null
+ line_secs=1586279157
+ (( 1586279157 > 1585673181 && line_secs < now_secs || line_secs == now_secs ))
+ egrep -wi '[Cc]ritical'
+ echo Apr 7 13:05:57 ip-172-31-19-169 kernel: BIOS-provided physical RAM map: critical
+ 1>> /tmp/text
+ read line

Я изменил ваш код несколькими способами, чтобы упростить отладку и увидеть проблему. Поместив то, что вы хотите сделать, добавьте к файлу журнала, как отдельный оператор в if, а не как часть условия &&, в трассировку, подобную приведенной выше, вы увидите, что это отображается как отдельный линия. В частности, когда вы видите:

+ egrep -wi '[Cc]ritical'
+ echo Apr 7 05:58:05 ip-172-31-19-169 kernel: BIOS-provided physical RAM map: critical

, мы знаем, что тест прошел успешно. Если вам интересно, был ли временной тест неудачным из-за первой части (время недостаточно новое) или второй части (время слишком новое) или не совпадает с третьей частью (время сейчас), поместите их в их собственные if или else позволили бы трассировке показать это.

Однако я сделал еще кое-что, чтобы упростить отладку. Хотя с такой конструкцией, как (( $line_secs > $start_secs )) k sh, появится предупреждение:

/tmp/bug.ksh: warning: line 14: variable expansion makes arithmetic evaluation less efficient

, потому что вместо этого предпочтительнее будет более эффективный (( line_secs > start_secs )), добавив дополнительную подстановку с помощью $, которую вы увидите значения сравниваются в след. И это может помочь вам выяснить, какая часть выходит из строя.

Если вы уже знали об этом и попробовали это, то я думаю, что вы получите больше ответов, если перейдете в StackOverflow с трассировкой, как показано выше, а затем вопрос немного сузился до «почему это сравнение не удается?» и вы можете получить больше ответов быстрее.

Наконец, я упомяну, что я написал отладчики для современных ksh93 новее, чем 2014-12-24, zsh и bash. Однако, когда я попробовал приведенный выше пример на kshdb, это не удалось, и я не уверен, почему.

...