catalina.out
should be mostly empty, meaning the application intercepts all errors and handles them itself, possibly logging them elsewhere as configured. But more often than not, nothing such is done and catalina.out
is considered as the application logs. This causes problems because by default Tomcat doesn't rotate this file.
The better approach to truncating the file (and beside fixing the application) is to have rotation in place for catalina.out
. This might already be provided by the specific packaged installation (eg: CentOS7's tomcat 7 is/was shipped with proper catalina.out
log rotation in place), or with a recent enough version of tomcat as described in Bug 64430 whose fix has been integrated in newer Tomcat and backported to Tomcat >= 7.0.105, >= 8.5.56 and >= 9.0.36:
Example (all one line)
CATALINA_OUT_CMD="/usr/bin/rotatelogs -f $CATALINA_BASE/logs/catalina.out.%Y-%m-%d.log 86400"
Rotated files should be further handled with logrotate
or an equivalent specialized tool.
Now to strictly answer the question, or at least the part about handling the single catalina.out
file.
OP writes both:
How to remove everything except last n bytes from the file in Linux?
=> keep the end
deletes [...] the last 5GB from that file
=> keep the start
Keep the start
Thus removing the end. Even if removing the end of a log rather than the start of a log is a bad idea:
POSIX truncate(2)
:
NAME
truncate - truncate a file to a specified length
[...]
DESCRIPTION
The truncate() function shall cause the regular file named by path to
have a size which shall be equal to length bytes.
Which has its truncate(1)
command implementation. For GNU truncate (along GNU stat(1)
) that would be used like this in shell (one has to check the file is greater than 5GiB first or its size would be increased instead). Keeping 5GiB:
if [ $(stat -c %s catalina.out) -gt $((5*1024*1024*1024)) ]; then
truncate -s $((5*1024*1024*1024)) catalina.out
fi
Keep the end
Thus deleting the start of the file. It's possible on Linux and adequate filesystem (eg: Ext4, XFS ...) to do this without involving any copy of data, using fallocate(1)
(with additional Linux-only features):
-p
, --punch-hole
Deallocates space (i.e., creates a hole) in the byte range starting at
offset and continuing for length bytes.
This doesn't involve any copy of data, but requires this to be block-aligned (so usually 4096 bytes-aligned). One can always keep the end of the file, a bit like a ring buffer, without any copy cost. This could be used like this (extra computation is needed to align to a 4096 multiple):
oldsize=$(stat -c %s catalina.out) || exit 1
if [ $oldsize -gt $((5*1024*1024*1024)) ]; then
holesize=$(( (oldsize-5*1024*1024*1024)/4096*4096 ))
fallocate --punch-hole --length "$holesize" catalina.out
fi
--punch-hole
(freeing the disk space by making the file sparse and keeping its apparent size) is used rather than --collapse-range
("moving" remaining data to the start reducing the size) to avoid disruption of the ongoing output appended to catalina.out
by Tomcat, else Tomcat should be stopped before and restarted after.