![Скрипт, выполняемый logrotate, дает другой результат, чем при его запуске вручную](https://rvso.com/image/168788/%D0%A1%D0%BA%D1%80%D0%B8%D0%BF%D1%82%2C%20%D0%B2%D1%8B%D0%BF%D0%BE%D0%BB%D0%BD%D1%8F%D0%B5%D0%BC%D1%8B%D0%B9%20logrotate%2C%20%D0%B4%D0%B0%D0%B5%D1%82%20%D0%B4%D1%80%D1%83%D0%B3%D0%BE%D0%B9%20%D1%80%D0%B5%D0%B7%D1%83%D0%BB%D1%8C%D1%82%D0%B0%D1%82%2C%20%D1%87%D0%B5%D0%BC%20%D0%BF%D1%80%D0%B8%20%D0%B5%D0%B3%D0%BE%20%D0%B7%D0%B0%D0%BF%D1%83%D1%81%D0%BA%D0%B5%20%D0%B2%D1%80%D1%83%D1%87%D0%BD%D1%83%D1%8E.png)
Я хочу ротировать наши журналы приложений с помощью logrotate
. После каждой ротации он выполняет скрипт, который перемещает все ротированные журналы в другой каталог. Например, в /home/dev/logs/frontend
, у меня есть эти файлы журналов:
webapp1-access.log
webapp2-access.log
anotherapp3-access.log
codename-access.log
...
И мой файл конфигурации logrotate:
$ cat app.daily
/home/dev/logs/frontend/*access.log {
rotate 1
daily
copytruncate
compress
notifempty
missingok
lastaction
bash /path/to/script.sh
endscript
}
И то, что делает script.sh, этосоздать каталог на основе имени файла журналазатем переместите туда повернутый файл журнала. webapp1-access.log
Будет повернуто в , webapp1-access.log.1.gz
затем скрипт переместит его в /x/y/webbapp1/renamed.log.gz
. И так далее для других повернутых журналов.
Когда я протестировал logrotate с помощью logrotate -fv /path/to/config
, и он отлично работает, как я и ожидал. Затем я поместил файл конфигурации logrotate в /etc/logrotate.d
(как символическую ссылку).
На следующий день я проверил /x/y
dir и получил:
webbapp1/ <---- created from initial logrotate -fv
webbapp1-access.log/ <---- Unexpected
anotherapp3/ <---- created from initial logrotate -fv
anotherapp3-access.log/ <---- Unexpected
codename/ <---- created from initial logrotate -fv
codename-access.log/ <---- Unexpected
Каталоги *-access.log/
создаются logrotate. Но запуск logrotate -vf config
нескольких раз не даст такого неожиданного результата. Это происходит, когда я оставляю logrotate выполнять ежедневную ротацию.
Почему это происходит? Как это исправить?
script.sh
#! /usr/bin/bash
exec 3>> /var/log/archived-log.log
[ "${1:-}" = "-d" ] && debug=1
environment="frontend"
rotateddir="/home/dev/logs/$environment"
destdir="/x/y"
[ "${debug:-}" ] && echo "DEST DIR: $destdir"
log() {
timestamp=$(date +"%Y-%m-%d %H:%M:%S")
echo "$timestamp: $1" >&3
}
for archive in $rotateddir/*.gz; do
[ "${debug:-}" ] && echo "ARCHIVE: $archive"
[ "${archive##*/}" = "*.gz" ] && continue
base_name=$(basename "$archive")
[ "${debug:-}" ] && echo "BASENAME: $base_name"
extension="${base_name##*.}"
[ "${debug:-}" ] && echo "EXT: $extension"
newdir_name="${base_name%-*}"
[ "${debug:-}" ] && echo "NEWDIR_NAME: $newdir_name"
tanggal=$(stat -c %y "$archive" | cut -d" " -f1 | { read dat; date -d $dat +%Y%m%d; })
#jam=$(stat -c %y "$archive" | cut -d" " -f2 | { read dat; date -d $dat +%H%M; })
newdir_path="$destdir/$newdir_name"
[ "${debug:-}" ] && echo "NEWDIR_PATH: $newdir_path"
#dest_archive="$newdir_path/$tanggal-$jam.log.$extension"
dest_archive="$newdir_path/$tanggal.log.$extension"
[ "${debug:-}" ] && echo "DEST_ARCHIVE: $dest_archive"
[ ! -d "$newdir_path" ] && {
if [ "${debug:-}" ]; then
echo "Would create $newdir_path"
else
mkdir -p "$newdir_path"
log "Created directory: $newdir_path"
fi
}
[ ! -f "$dest_archive" ] && {
if [ "${debug:-}" ]; then
echo "Would move $archive to $dest_archive"
else
rsync -a --no-owner --no-group --remove-source-files "$archive" "$dest_archive"
#cp -u --no-preserve=mode,ownership "$archive" "$dest_archive" && rm -f "$archive"
log "Relocated $archive to $dest_archive"
fi
}
rotates=$(ls -1 "$newdir_path" | wc -l )
[ "$rotates" -ge 7 ] && {
oldest=$(ls -t "$newdir_path" | tail -1)
if [ "${debug:-}" ]; then
echo "Would delete the oldest archive: $oldest"
else
rm -f "$newdir_path/$oldest"
log "Deleted oldest archive of $base_name : $oldest"
fi
}
done
exit 0
Обновлять
Я до сих пор не знаю, почему это происходит, но в конце концов я решил запустить скрипт через cron через несколько минут после ротации.
Я подозреваю, что эта часть моего "script.sh" newdir_name="${base_name%-*}"
не оценивается должным образом logrotate
. Но опять же, он работал как и ожидалось, если я запускал его принудительно с помощьюlogrotate -fv config
решение1
Оказывается, logrotate выполняет скрипт, используя sh
, а мой скрипт содержит bashishms.
Из страницы руководства:
последнее действие/конечный скрипт
Линии междупоследнее действиеиконец скрипта(оба из которых должны появляться в отдельных строках) выполняются (с использованием/bin/ш) ...
В конце концов, я запускаю свой скрипт через crontab
несколько минут после logrotate.