Ansible cron task adds a duplicate job after renaming the task because the cron module matches entries by name

2026-11-14 · 3 min read

Ansible cron task adds a duplicate job after renaming the task because the cron module matches entries by name

A backup that should run once now runs twice. The two jobs may compete for the same lock, send duplicate alerts, or write the same output file. The usual cause of an ansible cron duplicate job rename is not Ansible being noisy: it is the name: option on ansible.builtin.cron. The module uses that value as the identity of the entry. Change it and Ansible adds a new entry; the old one stays. [link needed]

Why an ansible cron duplicate job rename happens

Ansible task labels are documentation. The module does not match on the task’s name:—the YAML key above the module. It matches the cron entry by the module option also called name. [link needed] That value is stored with the entry, commonly as a comment marker, so Ansible can find it on later runs. [link needed]

Before:


- name: Install nightly backup
  ansible.builtin.cron:
    name: "nightly backup"
    minute: "0"
    hour: "2"
    job: "/usr/local/bin/backup.sh"

After tidying:


- name: Install nightly backup
  ansible.builtin.cron:
    name: "nightly-backup"
    minute: "0"
    hour: "2"
    job: "/usr/local/bin/backup.sh"

The first run after the change leaves two cron lines. Both run backup.sh. If you changed only the task label, there is no duplicate. If you changed the module’s name:, there is. Also check user and cron_file: those change which crontab or file is edited. [link needed]

Fix an ansible cron duplicate job rename without downtime

Use a deliberate migration, not a blind rename.

1. List current entries for the target user or file: crontab -l -u app or inspect the managed file under /etc/cron.d/. Find the old name and confirm no unmanaged job already uses the new name.

2. Pick a canonical name: and keep it stable. Prefer a simple slug such as nightly-backup.

3. Install the new entry first, keeping the schedule and command identical:


- name: Install renamed cron job
  ansible.builtin.cron:
    name: "nightly-backup"
    user: app
    minute: "0"
    hour: "2"
    job: "/usr/local/bin/backup.sh"

4. Add a removal task for the old identity, using the same user and cron_file as the old entry:


- name: Remove legacy cron identity
  ansible.builtin.cron:
    name: "nightly backup"
    user: app
    state: absent

5. Run the playbook twice. The second run should change nothing. Check crontab -l -u app and confirm exactly one line remains.

That is the whole ansible cron duplicate job rename trap: create the new identity first, remove the old identity second. Do not rely on job: text matching; two entries with the same command but different name: values are separate entries. [link needed]

When NOT to use the remove-old-name task

Do not add state: absent blindly if the old cron entry is not Ansible-managed. An unmanaged entry with the same name: in the same user or file can be deleted. Check first.

Do not use this pattern when moving the job to a different cron_file. The removal task must point at the old file; state: absent with only the new file leaves the old file untouched. Treat it as a file migration.

Do not rename a name: that other automation or runbooks grep. Keep the old value if the rename has no practical benefit.

Verification checklist