How to delete a cron job with Ansible?
Asked Answered
P

3

17

I have about 50 Debian Linux servers with a bad cron job:

0 * * * * ntpdate 10.20.0.1

I want to configure ntp sync with ntpd and so I need to delete this cron job. For configuring I use Ansible. I have tried to delete the cron entry with this play:

tasks:
   - cron: name="ntpdate" minute="0" job="ntpdate 10.20.0.1" state=absent user="root"

Nothing happened.

Then I run this play:

tasks:
   - cron: name="ntpdate" minute="0" job="ntpdate pool.ntp.org" state=present

I see new cron job in output of "crontab -l":

...
# m h  dom mon dow   command
  0 *  *   *   *     ntpdate 10.20.0.1
#Ansible: ntpdate
0 * * * * ntpdate pool.ntp.org

but /etc/cron.d is empty! I don't understand how the Ansible cron module works.

How can I delete my manually configured cron job with Ansible's cron module?

Peonage answered 21/10, 2015 at 9:11 Comment(0)
M
27

User's crontab entries are held under /var/spool/cron/crontab/$USER, as mentioned in the crontab man page:

Crontab is the program used to install, remove or list the tables used to drive the cron(8) daemon. Each user can have their own crontab, and though these are files in /var/spool/ , they are not intended to be edited directly. For SELinux in mls mode can be even more crontabs - for each range. For more see selinux(8).

As mentioned in the man page, and the above quote, you should not be editing/using these files directly and instead should use the available crontab commands such as crontab -l to list the user's crontab entries, crontab -r to remove the user's crontab or crontab -e to edit the user's crontab entries.

To remove a crontab entry by hand you can either use crontab -r to remove all the user's crontab entries or crontab -e to edit the crontab directly.

With Ansible this can be done by using the cron module's state: absent like so:

hosts : all
tasks :
  - name : remove ntpdate cron entry
    cron :
      name  : ntpdate
      state : absent

However, this relies on the comment that Ansible puts above the crontab entry that can be seen from this simple task:

hosts : all
tasks :
  - name : add crontab test entry
    cron :
      name  : crontab test
      job   : echo 'Testing!' > /var/log/crontest.log
      state : present

Which then sets up a crontab entry that looks like:

#Ansible: crontab test
* * * * * echo Testing > /var/log/crontest.log

Unfortunately if you have crontab entries that have been set up outside of Ansible's cron module then you are going to have to take a less clean approach to tidying up your crontab entries.

For this we will simply have to throw away our user's crontab using crontab -r and we can invoke this via the shell with a play that looks something like following:

hosts : all
tasks :
  - name  : remove user's crontab
    shell : crontab -r

We can then use further tasks to set the tasks that you wanted to keep or add that properly use Ansible's cron module.

Madewell answered 21/10, 2015 at 9:54 Comment(2)
Worth noting that crontab -r returns exit code 1 if there is no crontab for a user. ignore_errors: yes might be useful.Organo
Oneway to get a better diff, is to add the header comment into cron above existing entry and then apply ansible.Skald
M
0

If you have very complicated crontab entries so you can also delete it by shell module of ansible as shown in below example.

---
- name: Deleting contab entry
  hosts: ecx
  become: true
  tasks:
   - name: "decroning entry"
     shell:
           "crontab -l -u root |grep -v mybot  |crontab -u root -"
     register: cronout
   - debug: msg="{{cronout.stdout_lines}}" 

Explanation:- You have to just replace "mybot" string on line 8 with your unique identity of crontab entry. that's it. for "how to delete multiple crontab entries by ansible" you can use multiple strings in grep as shown below

"crontab -l -u root |grep -v 'strin1\|string2\|string3\|string4'  |crontab -u root -"
Molluscoid answered 14/8, 2022 at 15:11 Comment(0)
Q
0

If you want to remove just Ansible-cronjobs and leave the rest, this will remove the "#Ansible:"-comment and the following line from a crontab.

- name: "Removes Ansible cron entries"
  shell: |
    crontab -l -u USERNAME | \
    awk 'BEGIN {skip=0} /^#Ansible:/ {skip=1; next} skip {skip=0; next} {print}' | \
    crontab -u USERNAME  -

Explanation:

  1. List all cron-jobs for USERNAME
  2. awk read input from 1) and search lines starting with '#Ansible:'
  • If found: Skip line + next line
  • Else: Print line
  1. crontab for USERNAME receives output from 2) and overwrites everything
Quintuplet answered 24/7, 2024 at 11:12 Comment(2)
Why not just awk '/#Ansible:/ {next;next} 1' ? Assuming every pertinent cron job is preceded by the comment, of course. The OP didn't say that. I would think that crontab -l | grep -v ntpdate | crontab - would be close to what he's looking for.Proctor
I tried your suggestion, but it didn't work. I believe awk will not process the second 'next' in your script - thus it just printed all cronjobs without any "#Ansible"-comments. I am not very good at awk, there could be smarter ways than my suggestion - very open to that. However, I did try the "grep -v" approach, but that doesn't work because you need to remove 2 lines. I also tried grep "#Ansible" -A1, but then it you cannot invert it with -v. Hence my suggestion is still the best so far :)Quintuplet

© 2022 - 2025 — McMap. All rights reserved.