![Ein von logrotate ausgeführtes Skript führt zu einem anderen Ergebnis als bei manueller Ausführung](https://rvso.com/image/168788/Ein%20von%20logrotate%20ausgef%C3%BChrtes%20Skript%20f%C3%BChrt%20zu%20einem%20anderen%20Ergebnis%20als%20bei%20manueller%20Ausf%C3%BChrung.png)
Ich möchte unsere Anwendungsprotokolle mit rotieren logrotate
. Nach jeder Rotation wird ein Skript ausgeführt, das alle rotierten Protokolle in ein anderes Verzeichnis verschiebt. In habe ich beispielsweise /home/dev/logs/frontend
diese Protokolldateien:
webapp1-access.log
webapp2-access.log
anotherapp3-access.log
codename-access.log
...
Und meine Logrotate-Konfigurationsdatei:
$ cat app.daily
/home/dev/logs/frontend/*access.log {
rotate 1
daily
copytruncate
compress
notifempty
missingok
lastaction
bash /path/to/script.sh
endscript
}
Und was script.sh macht, istErstellen Sie ein Verzeichnis basierend auf dem ProtokolldateinamenVerschieben Sie dann die rotierte Protokolldatei dorthin. Die webapp1-access.log
würde nach rotiert, webapp1-access.log.1.gz
dann verschiebt das Skript sie nach /x/y/webbapp1/renamed.log.gz
. Und so weiter für andere rotierte Protokolle.
Als ich Logrotate mit getestet habe logrotate -fv /path/to/config
, funktionierte es perfekt wie erwartet. Dann habe ich die Logrotate-Konfigurationsdatei /etc/logrotate.d
(als symbolischen Link) eingefügt.
Als ich am nächsten Tag in /x/y
deinem Verzeichnis nachgesehen habe, fand ich:
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
Die *-access.log/
Verzeichnisse werden von logrotate erstellt. Aber das logrotate -vf config
mehrmalige Ausführen führt nicht zu diesem unerwarteten Ergebnis. Das passiert, wenn ich logrotate seine tägliche Rotation durchführen lasse.
Warum passiert das? Wie kann ich das beheben?
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
Aktualisieren
Ich weiß immer noch nicht, warum das passiert, aber schließlich habe ich beschlossen, das Skript einige Minuten nach der Rotation per Cron auszuführen.
Ich vermute, dass dieser Teil meines "script.sh" newdir_name="${base_name%-*}"
nicht gut ausgewertet wird logrotate
. Aber es funktionierte wie erwartet, wenn ich es zwangsweise ausführte mitlogrotate -fv config
Antwort1
Es stellte sich heraus, dass logrotate das Skript ausführt sh
und mein Skript Bashishms enthält.
Aus der Manpage:
letzte Aktion/Endskript
Die Linien zwischenletzte AktionUndEndskript(beide müssen in eigenen Zeilen stehen) werden ausgeführt (mit/bin/sh) ...
Am Ende führe ich mein Skript crontab
einige Minuten nach dem Logrotate aus.