Our nightly stock export to two marketplaces runs from cron on a pair of integration servers. For years they ran CentOS 7, and an Ansible role installed the job by templating a file into /etc/cron.d. The file was called stock-export.cron, because the template was stock-export.cron.j2 and the task simply dropped the .j2.
In the summer we rebuilt the pair on Debian 12 with the same role. The play was green, the file was there with the right owner, mode and contents, and a reviewer compared it line by line with the old server. For six nights the export did not run. We found out when one marketplace kept showing products as in stock that we had sold out of on the Saturday.
Debian's cron reads /etc/cron.d by the same naming rules as run-parts. A file name may contain letters, digits, underscores and hyphens and nothing else, so a name with a dot in it is skipped, and the manual page says so in as many words. The rule exists so that package manager leftovers such as .dpkg-old copies are never run, and it catches stock-export.cron just the same. cronie, the cron on our CentOS servers, had read the same file every night for four years. Nothing logs a skipped file. The job was simply never scheduled.
Debian's cron also ignores a file in that directory that is writable by group or others. That was the next thing we checked and, this time, not the problem.
The role now names the file stock-export, and a task asserts that every file it places in /etc/cron.d matches the run-parts pattern before the play continues. More usefully, the export no longer relies on anything we put on disk being noticed. Each run records its finish time as a metric, and an alert fires if the last success is more than twenty six hours old, on any operating system. We then looked for other dotted names and found two older jobs on Debian hosts. One had not run since 2023 and turned out not to be needed. The other was a certificate check, and it was.
Ansible reported, correctly, that the file was in place. Whether anything read the file was never part of what it checked.
– Sergey Shinder

