*/45 * * * * 를 "45분마다"로 읽는 경우가 많은데, 실제로는 45분과 15분이 교대로 나옵니다.
*/45 01:00 01:45 02:00 02:45 03:00 03:45
└45m┘ └15m┘ └45m┘ └15m┘ └45m┘
이유는 단순합니다. cron의 step은 해당 필드의 범위를 나누는 것이고, 분 필드의 범위는 매시간 0으로 되돌아갑니다. */45는 "45분마다"가 아니라 "0~59 중 45로 나누어떨어지는 분", 즉 0분과 45분을 뜻합니다. 매시 정각에 리셋되면서 15분짜리 간격이 끼어듭니다.
한 줄 판별법: 60 % step == 0 이면 간격이 일정하고, 아니면 교대합니다. 그리고 그 나머지가 정확히 짧은 쪽 간격입니다.
60 % 45 = 15 → 45분과 15분 교대
60 % 20 = 0 → 20분 일정
60 % 15 = 0 → 15분 일정
60 % 5 = 0 → 5분 일정
즉 cron은 한 시간을 나누어떨어지게 하는 간격만 정확히 표현할 수 있습니다. 90분, 45분, 7분 같은 건 애초에 표현이 안 됩니다.
한 시간으로 나누어떨어지지 않는 주기가 필요하면 systemd timer의 OnUnitActiveSec=90min처럼 직전 실행 시점부터 재는 방식을 써야 합니다. cron은 시계판을 기준으로 매칭하기 때문에 구조적으로 불가능합니다.
측정 환경과 나머지 케이스는 원문에 정리해뒀습니다.