Dan Bernstein's multilog can apparently do this - or perhaps most of it, while providing an outlet via file descriptors to !processor to make up the difference as you like - though the 20M/1G size specifications may take some finagling as it seems 16M is its outside limit per log. What follows is, in the majority, a copy+paste selection from the link above, though the link also details other options such as timestamping per line, maintaining [an]other file[s] containing only the most recent line matching pattern and more.
Interface
multilog script
...script consists of any number of arguments. Each argument specifies one action. The actions are carried out in order for each line of input.
Selecting lines
Each line is initially selected. The action...
-pattern
...deselects the line if pattern matches the line. The action...
+pattern
selects the line if pattern matches the line.
...pattern is a string of stars and non-stars. It matches any concatenation of strings matched by all the stars and non-stars in the same order. A non-star matches itself. A star before the end of pattern matches any string that does not include the next character in pattern. A star at the end of pattern matches any string.
Automatically rotated logs
If dir starts with a dot or slash then the action...
dir
...appends each selected line to a log named dir. If dir does not exist, multilog
creates it.
The log format is as follows:
dir is a directory containing some number of old log files, a log file named current, and other files for multilog
to keep track of its actions.
Each old log file has a name beginning with @, continuing with a precise timestamp showing when the file was finished, and ending with one of the following codes:
- .s: This file is completely processed and safely written to disk.
- .u: This file was being created at the moment of an outage. It may have been truncated. It has not been processed.
The action...
ssize
...sets the maximum file size for subsequent dir actions. multilog
will decide that current is big enough if current has size bytes. (multilog
will also decide that current is big enough if it sees a newline within 2000 bytes of the maximum file size; it tries to finish log files at line boundaries.) size must be between 4096 and 16777215. The default maximum file size is 99999.
In versions 0.75 and above: If multilog
receives an ALRM signal, it immediately decides that current is big enough, if current is nonempty.
(Note: I suspect the zsh
schedule
builtin could be easily persuaded to send an ALRM
at specified intervals if necessary.)
The action...
nnum
...sets the number of log files for subsequent dir actions. After renaming current, if multilog
sees num or more old log files, it removes the old log file with the smallest timestamp. num must be at least 2. The default number of log files is 10.
The action...
!processor
...sets a processor for subsequent dir actions. multilog
will feed current through processor and save the output as an old log file instead of current. multilog
will also save any output that processor writes to descriptor 5, and make that output readable on descriptor 4 when it runs processor on the next log file. For reliability, processor must exit nonzero if it has any trouble creating its output; multilog
will then run it again. Note that running processor may block any program feeding input to multilog
.