Bash-скрипт для ротации логов

Хорошо, обо всем по порядку:

Да, мне известен инструмент logrotate, который обычно используется для чего-то вроде этого. Однако, поскольку файл журнала, который я хочу повернуть, уже содержит отметку времени в имени файла, logrotate никогда не удалит старые журналы.

Этот сценарий должен:

  1. скажите приложению создать новый файл журнала (через SIGHUP)
  2. найти все существующие необработанные файлы журналов приложения
  3. сжать все файлы журнала, кроме того, который в настоящее время используется приложением
  4. сохранить 7 последних журналов и удалить остальные.

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

#!/usr/bin/bash

procname="foo"
srcpath="/var/log"
srcname="*${procname}.log"  # example: 2021-02-05_1200_foo.log
count=7

echo "rotate $procname logs: ${srcpath}/${srcname} ($count rotations)"

pid="$(pidof $procname)"
if [[ ! $? == 0 ]]
then
    # don't rotate anything if the application is not running
    echo "$procname process not running"
    exit 1
fi

# ask the application to create a new logfile
kill -HUP "$pid"

sleep 1 #probably not necessary?

# get array of all logfiles (should be exactly 2 in most cases)
mapfile -t list <  <(find "$srcpath" -maxdepth 1 -name "$srcname" | sort)
size=${#list[@]}

# don't do anything unless there are at least 2 files
if [[ $size -lt 2 ]]
then
    echo "nothing to do"
    exit 0
fi

# find the active logfile (should be the last one) and delete it from the array
for ((i=size-1; i>=0; i--));
do
    if [[ $(find -L /proc/"$pid"/fd -inum "$(stat -c '%i' "${list[i]}")") ]]
    then
        unset "list[i]"
        break
    fi
done

# compress all remaining files (usually just one)
gzip "${list[@]}"

unset list
unset size

# get array of all compressed logfiles
mapfile -t list <  <(find "$srcpath" -maxdepth 1 -name "$srcname.gz" | sort)
size=${#list[@]}

if [[ $size -gt $count ]]
then
    idx=("${!list[@]}")
    # remove $count most recent files from $list
    for i in "${idx[@]: -$count:$count}"
    do
        unset "list[$i]"
    done

    # delete the remaining old files
    rm -f "${list[@]}"
fi

exit 0

1 ответ
1

Shellcheck указывает на это:

pid="$(pidof $procname)"
if [[ ! $? == 0 ]]
then

Мы можем написать это более четко

if ! pid="$(pidof $procname)"
then

Вскоре после этого:

# don't rotate anything if the application is not running
echo "$procname process not running"

Это похоже на сообщение об ошибке — перенаправьте это на &2.

Я немного обеспокоен

# find the active logfile (should be the last one) and delete it from the array

Если демон не успел открыть новый файл к тому времени, как мы дойдем до этого места, то синхронизация будет нарушена. Тем не менее, это, вероятно, не имеет значения — у нас будет еще один невращенный файл до следующего запуска, что не вызывает большого беспокойства.

Будьте осторожны с такими командами:

gzip "${list[@]}"

Это хорошая идея использовать -- поэтому мы можем быть уверены, что имена файлов, начинающиеся с - не интерпретируются как варианты.

Также такие команды, как gzip может потерпеть неудачу — действительно ли мы хотим продолжать, если они это сделают? (На этот вопрос не так просто ответить, поскольку одна из вероятных причин — «нет места на устройстве», и в этом случае мы действительно хотим удалить некоторые файлы!)

  • Спасибо! Я не знал, что у вас может быть назначение внутри предложения if, это намного лучше, чем $? версия. Что касается проблемы рассинхронизации, поэтому я добавил sleep 1, что, конечно, тоже не является гарантией, но, надеюсь, лучше, чем ничего. Не думал о --, я добавлю это в gzip и rm на всякий случай (даже если имена файлов не должны начинаться с -). Мне нужно подумать об обработке ошибок … честно говоря, я не совсем уверен, что я хочу делать, если gzip не работает

    — Феликс Джи

  • Да, я видел сон с его комментарием, поэтому знал, что вы о нем знаете. Извините, я не могу предложить ничего лучше.

    — Тоби Спейт

  • я мысль списки аргументов не начинались бы с -, но часто проще просто уронить -- в команду, чтобы спасти драгоценный ум, рассуждая об этом!

    — Тоби Спейт

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *