From DHCP sources:
if (snprintf (backfname, sizeof backfname, "%s~", path_dhcpd_db) >= sizeof backfname)
[...]
if (unlink (backfname) < 0 && errno != ENOENT) {
[...]
if (link(path_dhcpd_db, backfname) < 0) {
The previous backup file is deleted, then the current lease file is hardlinked as backup with a trailing ~.
On Linux, with the inotify(7) event facility, a hardlink is seen as a creation event.
I would suggest to use inotifywait (from inotify-tools package) to signal when such event happened. One should expect the apparition of /var/lib/dhcpd/dhcpd.leases~ which is then directly ready for backup (it's a hardlink to the original). As the file will be a different file (different inode) each time, it's the directory that should be watched for proper detection, and for example the --include option can be used to simplify shell processing (no processing, even the read line is discarded in a dummy variable):
inotifywait -m -e create --include dhcpd.leases~ /var/lib/dhcpd | while read dummy; do
do_backup /var/lib/dhcpd/dhcpd.leases~
done
If the command is not recent enough, it might not understand --include in such case, the test has to be done in the event loop:
inotifywait -m -e create /var/lib/dhcpd | while read -r dir event filename; do
if [ "$filename" = dhcpd.leases~ ]; then
do_backup /var/lib/dhcpd/dhcpd.leases~
fi
done
Alternatively, the incron package (available at least on CentOS 8 Stream), could be used with an entry similar to:
/var/lib/dhcpd IN_CREATE,recursive=false if_correct_file_do_backup $#
with if_correct_file_do_backup being for example a shell checking this was the intended filename:
#!/bin/sh
if [ "$1" = dhcpd.leases~ ]; then
do_backup /var/lib/dhcpd/dhcpd.leases~
fi