Наложение лечится в одну строку, переезжать ради него не нужно:
0 2 * * * /usr/bin/flock -n /tmp/nochnoy.lock /opt/progon/start.sh
Флаг -n означает «занято, значит уходим молча». Хотите, чтобы второй дождался первого, уберите -n.
С пропуском после перезагрузки хуже, cron про пропущенные запуски не помнит вовсе. Вот тут таймер выигрывает:
[Unit]
Description=Ночной сбор
[Timer]
OnCalendar=*-*-* 02:00:00
Persistent=true
RandomizedDelaySec=900
[Install]
WantedBy=timers.target
```
Persistent=true догоняет пропущенный запуск сразу после старта машины. RandomizedDelaySec растаскивает пять прогонов по времени, чтобы они не стартовали в одну секунду. И весь вывод сам ложится в журнал, journalctl -u nochnoy.service показывает прошлые запуски с кодами выхода, никаких перенаправлений в файл руками.