Использование awk для извлечения последней временной метки из файла в скрипте Bash

#bash #awk

#bash #awk

Вопрос:

Я долго искал и обнаружил, что вы не можете направлять вывод системного журнала как в буфер, так и в файл через syslog-startup.conf в / etc. Пожалуйста, посмотрите на это: https://unix.stackexchange.com/questions/449156/how-to-set-up-syslog-to-log-to-both-file-buffer

Моим решением было запустить задание cron с bash-скриптом, который будет запускаться каждые пару минут, чтобы извлекать журналы из буфера и сохранять их в файл на моем встроенном устройстве Linux. Подход заключается в том, что я извлекаю первый набор журналов из буфера, выполняя что-то вроде logread >> my_log_file , а затем я извлекаю последнюю запись из my_log_file, получаю из нее временную метку, а затем использую ее для извлечения новых журналов, у которых временная метка больше, чем эта временная метка.

Я столкнулся с проблемой, пытаясь подключить временную метку к команде awk

 if [ -f "${VAR_FILE}" ]; then
    LASTTS=$(tail -n 1 "${VAR_FILE}" | grep -o '^.*swi-')
    LASTTS=$(sed 's/.{5}$//' <<< "$LASTTS")
    echo $LASTTS
fi

awk '$0 > "${LASTTS}"' msgs >> "${VAR_FILE}"
  

Я продолжаю получать все журналы, а не те, которые > моя последняя временная метка. Это сработает, если я изменю команду awk, чтобы в ней была жестко задана фактическая дата как таковая

awk '$0 > "Mar 15 14:20:50"' msgs >> "${VAR_FILE}"

Что я делаю не так?

Комментарии:

1. почему вам нужно входить в буфер, а не напрямую в файл?

2. @jhnc Мне нужно, чтобы журналы поступали как в буфер, так и в файл. Файл будет сохранен на SD-карте, которая подвержена повреждению, и тому подобное, поэтому в случае, если это произойдет, мы хотим иметь журналы в буфере, к которому мы можем получить доступ

3. Возможно, было бы надежнее использовать сетевую опцию для отправки на центральный логхостинг. Каков пример содержимого вашего файла журнала?

4. Имейте в виду, что ваш формат даты не поддается сортировке.

Ответ №1:

Есть три случая:

  1. в файл пока ничего не сохранено
  2. буфер содержит новое содержимое и некоторое старое содержимое
  3. в буфере только новое содержимое (мы что-то пропустили)

Мы хотим добавлять только новое содержимое из буфера.

Предполагая, что busybox awk и shell:

 #!/bin/sh

if [ ! -f "$log" ]; then
    # case 1
    logread > "$log"
else
    prev="$(tail -n 1 "$log")"

    # case 2 or 3
    logread | awk -v prev="$prev" '
        new { print; next }
        $0==prev { new=1 }
        END { exit !new } # "fail" if no old line
    ' >> "$log" 

    # case 3
    [ -n $? ] amp;amp; logread >> "$log"
fi
  

Комментарии:

1. На самом деле я не знаю, какой вывод выдает logread. Если временная метка недостаточно детализирована, с помощью этого кода можно было бы дублировать строки. например. seen: ... / t1a / t1b / t1c / t1a , buffer: t1a / t1b / t1c / t1a / t2d должен быть добавлен t2d , но на самом деле будет добавлен t1b / t1c / t1a / t2d . Однако ничего не должно быть потеряно, если проверки не будут выполнены на таком большом расстоянии друг от друга, что мы попадем в случай 3.

Ответ №2:

ИТАК, ответ, который я искал, это:

 awk -v var="$LASTTS" '$0 > var' msgs >> "${VAR_FILE}"
  

Это, как правило, решает проблему, с которой я столкнулся. Но теперь я столкнулся с тем фактом, что она дублирует всегда, последняя временная метка копируется повторно

Комментарии:

1. Я думаю, что это может привести к сбою, когда ваша последняя строка Mar ... и буфер содержит Apr ...