Skip to content
Search AlmaLinux

    Browse this documentation

    AlmaLinux 9: rotate your application logs

    Executed in an almalinux:9 container (AlmaLinux 9.8): installing logrotate, writing /etc/logrotate.d/myapp, logrotate -d, logrotate -f, ls -l. Log: plans/content-expansion/evidence/logs/alma-log-rotation.log.

    Automatic cron.daily invocation, multi-day behaviour and SELinux-related failures were not tested here.

    Terminal window
    ls /etc/logrotate.d/ | head -5
    head -20 /etc/logrotate.conf

    AlmaLinux 9 ships snippets such as btmp, wtmp and dnf under /etc/logrotate.d/; the main /etc/logrotate.conf only carries global defaults. Put application configuration in /etc/logrotate.d/, not in the main file.

    /var/log/myapp/*.log {
    daily
    rotate 3
    compress
    missingok
    notifempty
    copytruncate
    }
    DirectiveEffect
    dailyRotate daily (or weekly, size 50M)
    rotate 3Keep 3 older files
    compressgzip the rotated file
    missingok / notifemptyNo error when absent; skip empty files
    copytruncateCopy then truncate, so the app need not reopen its handle
    Terminal window
    sudo logrotate -d /etc/logrotate.d/myapp
    considering log /var/log/myapp/app.log
    Creating new state
    Now: 2026-10-18 17:54
    Last rotated at 2026-10-18 17:00
    log does not need rotating (log has already been rotated)

    -d prints only and changes nothing.

    Terminal window
    sudo logrotate -f /etc/logrotate.d/myapp
    ls -l /var/log/myapp/
    -rw-r--r-- 1 root root 0 Oct 18 17:54 app.log
    -rw-r--r-- 1 root root 4023 Oct 18 17:54 app.log.1.gz

    The original is truncated and the content moved into .1.gz — that is copytruncate.

    • copytruncate loses lines written between copy and truncate; prefer create plus a postrotate signal when the app can reopen its file;
    • size without a time directive triggers regardless of the clock; do not mix and expect once a day;
    • Wrong directory ownership: the file created after copytruncate may end up owned by root; add su myapp myapp.
    Terminal window
    sudo mkdir -p /var/log/lab && sudo sh -c 'head -c 200000 /dev/urandom > /var/log/lab/a.log'
    sudo tee /etc/logrotate.d/lab >/dev/null <<'EOF'
    /var/log/lab/*.log { daily rotate 3 compress copytruncate }
    EOF
    sudo logrotate -f /etc/logrotate.d/lab
    sudo logrotate -f /etc/logrotate.d/lab
    ls /var/log/lab/

    Checks:

    1. a.log.1.gz and a.log.2.gz exist
    2. a.log is 0 bytes
    3. After five forced runs, no more than 3 *.gz files remain

    常见问题

    Why does `logrotate -d` say "already been rotated"?

    It reads the state file and decides no rotation is due; `-d` is a dry-run and does not update state. Use `-f` to force one run when you want to validate the configuration now.

    copytruncate or create?

    If the application can reopen its log file (after a signal), use create with postrotate. Use copytruncate only when it cannot reopen (some Java apps), accepting that lines written between copy and truncate are lost.

    Why did the rotated file end up owned by root?

    copytruncate runs as root and creates the new file as root. Add `su <user> <group>` so logrotate acts as the app user, or chown in postrotate.