O script executado pelo logrotate dá um resultado diferente do executado manualmente

O script executado pelo logrotate dá um resultado diferente do executado manualmente

Quero girar nossos logs de aplicativos usando logrotate. Após cada rotação, ele executa um script que move todos os logs girados para outro diretório. Por exemplo, em /home/dev/logs/frontend, tenho estes arquivos de log:

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

E meu arquivo de configuração do logrotate:

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

E o que script.sh faz écrie um diretório baseado no nome do arquivo de logem seguida, mova o arquivo de log girado para lá. O webapp1-access.logseria girado para webapp1-access.log.1.gzentão o script o moveria para /x/y/webbapp1/renamed.log.gz. E assim por diante para outros logs girados.

Quando testei o logrotate usando logrotate -fv /path/to/config, ele funciona perfeitamente como eu esperava. Então coloquei o arquivo de configuração do logrotate /etc/logrotate.d(como um link simbólico).

No dia seguinte verifiquei /x/ydir e obtive:

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

Os *-access.log/diretórios são criados pelo logrotate. Mas correr logrotate -vf configvárias vezes não produzirá esse resultado inesperado. Isso acontece quando deixo o logrotate fazer sua rotação diária.

Por que isso está acontecendo? Como posso consertar isso?


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



Atualizar

Ainda não sei por que isso acontece, mas finalmente decidi executar o script pelo cron alguns minutos após a rotação.

Suspeito que esta parte do meu "script.sh" newdir_name="${base_name%-*}"não seja bem avaliada pelo logrotate. Mas, novamente, funcionou como esperado se eu executá-lo com força usandologrotate -fv config

Responder1

Acontece que o logrotate executa o script usando she meu script contém bashishms.

Da página de manual:

última ação/endscript

As linhas entreúltima açãoeendscript(ambos devem aparecer nas linhas sozinhos) são executados (usando/bin/sh) ...

No final, executo meu script crontabalguns minutos após o logrotate.

informação relacionada