Until now I hadn't fully worked through @spence's script to see exactly what it did and in my mind I conflated two things:
- dnsmasq log file rotation; and
- processing logged queries.
This is because for some time I have been wondering about ways to facilitate adblock-lean processing queries as they are generated.
@spence, now that I've digested your script, which addresses log file rotation, it looks good to me. Nice work and I think you've had fun with this.
When it receives SIGUSR2 and it is logging direct to a file (see --log-facility ) dnsmasq will close and reopen the log file. Note that during this operation, dnsmasq will not be running as root. When it first creates the logfile dnsmasq changes the ownership of the file to the non-root user it will run as. Logrotate should be configured to create a new log file with the ownership which matches the existing one before sending SIGUSR2. If TCP DNS queries are in progress, the old logfile will remain open in child processes which are handling TCP queries and may continue to be written. There is a limit of 150 seconds, after which all existing TCP processes will have expired: for this reason, it is not wise to configure logfile compression for logfiles which have just been rotated. Using logrotate, the required options are create and delaycompress.
@spence I have a suggestion for your script.
At the moment once you've sent SIGUSR2 you then move the old logfile to a different file system, which I think could be problematic given these trailing queries described in the helpful dnsmasq manual excerpt reproduced above that you identified. It seems that ideally dnsmasq is provided with a full 150 seconds for any old queries to get written to the old log file at the new location. It is my understanding that your initial mv within /tmp is perfectly okay - the old queries will still get appended to the same file despite the move. However, the mv to a different file system (e.g. USB stick) is not okay because the writes will not follow through.
Thankfully this would be mostly resolved by simply adding a 150 second sleep after sending the USR2 signal and before archiving the renamed log file in order to give dnsmasq sufficient time to complete its logging of any outstanding queries.
Now I believe ideally you would actually wait 150 seconds from the point of time that dnsmasq actually receives the signal, rather than 150 seconds from sending it. But I don't think there's an easy way to do that except perhaps to send the signal, wait for some kind of log entry in the system log to appear, then wait 150 seconds.
But honestly I think simply waiting 180 seconds would suffice - the signal in reality is not going to take more than 30 seconds to get processed.
Then after the 180 seconds you can safely move the old log file to your external archive on the USB stick.
You could, of course, just use logrotate and its builtin scripting functionality:
prerotate script endscript The script is executed before the log file and its old logs are rotated and only if the log will actually be rotated. These directives may only appear inside a log file definition. Normally, the absolute path to the log file is passed as the first argument to the script. If sharedscripts is specified, the whole pattern is passed to the script. See also postrotate and the SCRIPTS section. See sharedscripts and nosharedscripts for error handling.
But that's obviously way less fun than writing a custom script and as a bonus we lose the package dependency.
By the way, I discovered earlier that it's possible to setup rclone to mount cloud storage on /tmp. One could leverage that to send dnsmasq log files to Google Drive or OneDrive.