El script ejecutado por logrotate da un resultado diferente al ejecutado manualmente

El script ejecutado por logrotate da un resultado diferente al ejecutado manualmente

Quiero rotar los registros de nuestra aplicación usando logrotate. Después de cada rotación, ejecuta un script que mueve todos los registros rotados a otro directorio. Por ejemplo /home/dev/logs/frontend, tengo estos archivos de registro:

webapp1-access.log
webapp2-access.log
anotherapp3-access.log
codename-access.log
...

Y mi archivo de configuración logrotate:

$ cat app.daily
/home/dev/logs/frontend/*access.log {
   rotate 1
   daily
   copytruncate
   compress
   notifempty
   missingok
   lastaction
      bash /path/to/script.sh
   endscript
}

Y lo que hace script.sh escrear un directorio basado en el nombre del archivo de registroluego mueva el archivo de registro rotado allí. Se webapp1-access.logrotará y webapp1-access.log.1.gzluego el script lo moverá a /x/y/webbapp1/renamed.log.gz. Y así sucesivamente con otros troncos rotados.

Cuando probé logrotate usando logrotate -fv /path/to/config, funciona perfectamente como esperaba. Luego puse el archivo de configuración de logrotate /etc/logrotate.d(como un enlace simbólico).

Al día siguiente revisé /x/ydir y obtuve:

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

Los *-access.log/directorios son creados por logrotate. Pero ejecutar logrotate -vf configvarias veces no producirá ese resultado inesperado. Eso sucede cuando dejo que logrotate haga su rotación diaria.

¿Por qué está pasando esto? ¿Cómo puedo arreglar esto?


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



Actualizar

Todavía no sé por qué sucede esto, pero finalmente decidí ejecutar el script mediante cron unos minutos después de la rotación.

Sospecho que esta parte de mi "script.sh" newdir_name="${base_name%-*}"no está bien evaluada por logrotate. Pero nuevamente, funcionó como se esperaba si lo ejecuto con fuerza usandologrotate -fv config

Respuesta1

Resulta que logrotate ejecuta el script usando shy mi script contiene bashishms.

Desde la página de manual:

última acción/endscript

Las líneas entreúltima acciónyguión final(ambos deben aparecer en las líneas por sí mismos) se ejecutan (usando/bin/sh) ...

Al final, ejecuto mi script crontabunos minutos después del logrotate.

información relacionada