-2

Below are my cron entries.

$ crontab -l
#Cron to auto restart app1
#Ansible: test
#*/15 * * * * ansible-playbook  /web/playbooks/automation/va_action.yml


#Cron to auto restart app7

#Ansible: test
*/15 * * * * ansible-playbook  /web/playbooks/automation7/va_action.yml | tee -a /web/playbooks/automation7/cron.out


#Cron to restart Apache services on automation server

#Ansible: test
0 2 * * * /web/apps/prod/apache/http-automation/bin/apachectl -k start

Below is how I list all enabled Cron

crontab -l | grep -v '#' | tr -d '\n'

Output:

*/15 * * * * ansible-playbook  /web/playbooks/automation7/va_action.yml | tee -a /web/playbooks/automation7/cron.out
0 2 * * * /web/apps/prod/apache/http-automation/bin/apachectl -k start

And here is how i list all #Ansible: values for cron

crontab -l | awk '/^$/ { next ; } /^#/ { text=$2 ; } /^[^#]/ { print text; }'

test
test

Here is my Ansible code where I need help.

cat handlecron.yml
- name: "cron"
  hosts: localhost
  tasks:

    - raw: "crontab -l | grep -v '#' | tr -d '\n'"
      ignore_errors: true
      register: cronentry

    - cron:
        name: "test"
        job: "{{ item }}"
        state: present
        disabled: True
      with_items:
        - "{{ cronentry.stdout_lines }}"

I have given #Ansible: test same for all the Cron entries.

I am not sure if I will have to give this as unique entry for the logic to work.

Upon running the automation commented entries for loop cronentry.stdout_lines appears under each #Ansible: test. This is not what I desire but the desired Cron entries should look like below:

$ crontab -l
#Cron to auto restart app1
#Ansible: test
#*/15 * * * * ansible-playbook  /web/playbooks/automation/va_action.yml


#Cron to auto restart app7

#Ansible: test
#*/15 * * * * ansible-playbook  /web/playbooks/automation7/va_action.yml | tee -a /web/playbooks/automation7/cron.out


#Cron to restart apache services on automation server

#Ansible: test
#0 2 * * * /web/apps/prod/apache/http-automation/bin/apachectl -k start

Can you please suggest the logic to use here?

Ashar
  • 2,942
  • 10
  • 58
  • 122

1 Answers1

0

Cron jobs can be found in a file under /var/spool/cron/crontabs/$USERNAME, which is not intended to be edited directly, but they can be read from there.

man crontab

DESCRIPTION crontab is the program used to install, deinstall or list the tables used to drive the cron(8) daemon in Vixie Cron. Each user can have their own crontab, and though these are files in /var/spool/cron/crontabs, they are not intended to be edited directly.

First grep uncommented lines grep -v "^#" /var/spool/cron/crontabs/$USERNAME





*/15 * * * * ansible-playbook  /web/playbooks/automation7/va_action.yml | tee -a /web/playbooks/automation7/cron.out



0 2 * * * /web/apps/prod/apache/http-automation/bin/apachectl -k start

Then grep them without spaces or lines grep -v "^#" /var/spool/cron/crontabs/$USERNAME | grep -v "^[[:space:]]*$"

*/15 * * * * ansible-playbook  /web/playbooks/automation7/va_action.yml | tee -a /web/playbooks/automation7/cron.out
0 2 * * * /web/apps/prod/apache/http-automation/bin/apachectl -k start
- hosts: all
  gather_facts: no
  vars:
    cron_user: root
  tasks:
  - name: Get enabled cron jobs
    shell: grep -v "^#" /var/spool/cron/crontabs/{{ cron_user }} | grep -v "^[[:space:]]*$"
    register: cronentry
    ignore_errors: true

  - debug:
      msg: "{{ cronentry.stdout_lines }}"

  - cron:
      name: "test"
      job: "{{ item }}"
      state: present
      disabled: True
    with_items:
      - "{{ cronentry.stdout_lines }}"

This will do the job, but your mistake is that you gave all the cron jobs the name test, which will lead to overwrite all jobs with the same name.

#Cron to auto restart app1
#Ansible: test
#* * * * * 0 2 * * * /web/apps/prod/apache/http-automation/bin/apachectl -k start


#Cron to auto restart app7

#Ansible: test
#* * * * * 0 2 * * * /web/apps/prod/apache/http-automation/bin/apachectl -k start


#Cron to restart Apache services on automation server

#Ansible: test
#* * * * * 0 2 * * * /web/apps/prod/apache/http-automation/bin/apachectl -k start




################### Solution with unique cron jobs names ###################

- hosts: all
  gather_facts: no
  vars:
    cron_user: root
  tasks:
  - name: Get enabled cron jobs
    shell: grep -v "^#" /var/spool/cron/crontabs/{{ cron_user }} | grep -v "^[[:space:]]*$"
    register: cronentry
    ignore_errors: true

  - name: get cron job name #Get the line before the line found in the previous task
    shell: fgrep -B1 "{{ item }}" /var/spool/cron/crontabs/{{ cron_user }}
    with_items: "{{ cronentry.stdout_lines }}"
    register: cronjob_name

  - cron:
      # Get the job name without '#Ansible: '
      name: "{{ item.stdout_lines[0] | regex_search('(?:#Ansible: )(.*)$', '\\1') | first }}"
      job: "{{ item.stdout_lines[1] }}"
      state: present
      disabled: True
    with_items:
      - "{{ cronjob_name.results }}"

Result:

TASK [cron] *********************************
changed: [test-001] => (item={'changed': True, 'stdout': '#Ansible: execute playbook\n15 * * * * ansible-playbook  /web/playbooks/automation7/va_action.yml | tee -a /web/playbooks/automation7/cron.out', 'stderr': '', 'rc': 0, 'cmd': 'fgrep -B1 "15 * * * * ansible-playbook  /web/playbooks/automation7/va_action.yml | tee -a /web/playbooks/automation7/cron.out" /var/spool/cron/crontabs/root', 'start': '2022-08-30 15:03:07.266264', 'end': '2022-08-30 15:03:07.281987', 'delta': '0:00:00.015723', 'msg': '', 'invocation': {'module_args': {'_raw_params': 'fgrep -B1 "15 * * * * ansible-playbook  /web/playbooks/automation7/va_action.yml | tee -a /web/playbooks/automation7/cron.out" /var/spool/cron/crontabs/root', '_uses_shell': True, 'warn': False, 'stdin_add_newline': True, 'strip_empty_ends': True, 'argv': None, 'chdir': None, 'executable': None, 'creates': None, 'removes': None, 'stdin': None}}, 'stdout_lines': ['#Ansible: execute playbook', '15 * * * * ansible-playbook  /web/playbooks/automation7/va_action.yml | tee -a /web/playbooks/automation7/cron.out'], 'stderr_lines': [], 'failed': False, 'item': '15 * * * * ansible-playbook  /web/playbooks/automation7/va_action.yml | tee -a /web/playbooks/automation7/cron.out', 'ansible_loop_var': 'item'})

changed: [test-001] => (item={'changed': True, 'stdout': '#Ansible: start apache ctl\n0 2 * * * /web/apps/prod/apache/http-automation/bin/apachectl -k start', 'stderr': '', 'rc': 0, 'cmd': 'fgrep -B1 "0 2 * * * /web/apps/prod/apache/http-automation/bin/apachectl -k start" /var/spool/cron/crontabs/root', 'start': '2022-08-30 15:03:08.149322', 'end': '2022-08-30 15:03:08.165943', 'delta': '0:00:00.016621', 'msg': '', 'invocation': {'module_args': {'_raw_params': 'fgrep -B1 "0 2 * * * /web/apps/prod/apache/http-automation/bin/apachectl -k start" /var/spool/cron/crontabs/root', '_uses_shell': True, 'warn': False, 'stdin_add_newline': True, 'strip_empty_ends': True, 'argv': None, 'chdir': None, 'executable': None, 'creates': None, 'removes': None, 'stdin': None}}, 'stdout_lines': ['#Ansible: start apache ctl', '0 2 * * * /web/apps/prod/apache/http-automation/bin/apachectl -k start'], 'stderr_lines': [], 'failed': False, 'item': '0 2 * * * /web/apps/prod/apache/http-automation/bin/apachectl -k start', 'ansible_loop_var': 'item'})
Khaled
  • 775
  • 1
  • 5
  • 19
  • What is the solution with names being unique and not the same? – Ashar Aug 28 '22 at 12:39
  • @Ashar The answer is updated. – Khaled Aug 30 '22 at 13:19
  • will enabling the cron have similar logic / approach? if you could add it to your answer – Ashar Aug 30 '22 at 14:01
  • @Ashar It's possible, but that would be over-engineered. Search for specific words in commented lines, uncomment the line, remove the first four asterisks, get the name from the line above and enable the cron. – Khaled Aug 30 '22 at 14:14