Skip to content
Search Rocky Linux

    Browse this documentation

    logrotate in practice: copytruncate and -f, tested on Rocky 9

    An application writing its own log file will fill the partition within days. logrotate ships with EL and rotates by time or size, compresses, and keeps N copies. This page walks the full flow on a self-managed app log.

    Terminal window
    sudo dnf install -y logrotate
    head -20 /etc/logrotate.conf
    ls /etc/logrotate.d/ | head -5
    btmp
    dnf
    wtmp

    Every file under /etc/logrotate.d/ is a snippet; the system’s own btmp and wtmp live there. Do not stuff app configuration into logrotate.conf — a file in /etc/logrotate.d/ is cleaner.

    Terminal window
    cat | sudo tee /etc/logrotate.d/myapp <<'EOF'
    /var/log/myapp/*.log {
    daily
    rotate 3
    compress
    missingok
    notifempty
    copytruncate
    }
    EOF

    What the six directives do:

    DirectiveEffect
    dailyRotate once a day (or use size 50M, weekly)
    rotate 3Keep 3 older files; delete from the 4th on
    compressgzip the rotated file
    missingokNo error when the log is absent
    notifemptyDo not rotate an empty file
    copytruncateCopy then truncate the original — the app does not need to reopen its file handle
    Terminal window
    sudo logrotate -d /etc/logrotate.d/myapp
    rotating pattern: /var/log/myapp/*.log after 1 days (3 rotations)
    empty log files are not rotated, old logs are removed
    considering log /var/log/myapp/app.log
    ...
    log does not need rotating (log has already been rotated)

    -d is a dry-run: it prints but changes nothing. When the configuration looks right, force one run:

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

    app.log is truncated to 0 bytes and the content moved into app.log.1.gz — that is copytruncate in action.

    Tested on EL10: the same stanza on Alma/Rocky 10.2

    Section titled “Tested on EL10: the same stanza on Alma/Rocky 10.2”

    In PVE VMs running AlmaLinux 10.2 and Rocky Linux 10.2, with the same stanza:

    /var/log/lab/app.log {
    daily
    rotate 3
    copytruncate
    notifempty
    missingok
    su root root
    }

    logrotate -d dry run (the state file says it already rotated today):

    log does not need rotating (log has already been rotated)

    After logrotate -f:

    -rw-r--r--. 1 root root 0 ... app.log
    -rw-r--r--. 1 root root 21 ... app.log.1

    Write one more line, force again:

    -rw-r--r--. 1 root root 0 ... app.log
    -rw-r--r--. 1 root root 5 ... app.log.1
    -rw-r--r--. 1 root root 21 ... app.log.2

    copytruncate behaves exactly as advertised: the active file becomes 0 bytes, the old content moves to .1, and the next rotation shifts .1 to .2. Writers do not reopen the file; the cost is a tiny window between copy and truncate where a few lines can be lost.

    • copytruncate loses lines: anything written between the copy and the truncate is lost; applications that can reopen their handle should use create plus a postrotate signal instead;
    • size without daily: size triggers regardless of time; do not mix it with daily and expect once-a-day;
    • Ownership: if /var/log/myapp is not owned by root, the file created after copytruncate may have the wrong owner; add su myapp myapp when needed.

    Prerequisite: Rocky 9 with logrotate installed.

    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 # run 1
    sudo logrotate -f /etc/logrotate.d/lab # run 2
    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 (rotate 3 works)