0

I'm looking to extract a list of users from /etc/passwd and then grep their crontab files for disabled (commented: ^#) jobs.

The high level steps would be:

  1. Grab an array of usernames from /etc/passwd ("my_users")
  2. Run grep against the files named in step 1 (/var/spool/cron/{{my_users}})
  3. Use 'Debug' to print out the results.

I'd appreciate any suggestions, here's what I have so far:

 - name: ANSIBLE PLAYBOOK - disabled cronjob check hosts: "{{ variable_host | default('testvm') }}" remote_user: admin gather_facts: no become: yes tasks: - getent: database: passwd - name: set_fact debugger: on_failed ansible.builtin.set_fact: my_users: "{{ getent_passwd|dict2items|json_query('[?contains(value,`/bin/bash`)].key') }}" cacheable: yes - name: set_fact_2 ansible.builtin.set_fact: array_length: "{{ my_users|length }}" - debug: msg: "Debugging 2: {{ my_users|length }}" - name: Get disabled cron jobs debugger: always loop: "{{ my_users }}" ansible.builtin.lineinfile: path: "/var/spool/cron/{{ my_users }}" regexp: "^#" 

Here's the output in question, which isn't quite what I expected:

TASK [Get disabled cron jobs]*********************************************************************************************************************************************************************************** failed: [testvm] (item=n2disk) => {"ansible_loop_var": "item", "changed": false, "item": "n2disk", "msg": "line is required with state=present"} failed: [testvm] (item=cento) => {"ansible_loop_var": "item", "changed": false, "item": "cento", "msg": "line is required with state=present"} failed: [testvm] (item=admin) => {"ansible_loop_var": "item", "changed": false, "item": "admin", "msg": "line is required with state=present"} failed: [testvm] (item=nprobe) => {"ansible_loop_var": "item", "changed": false, "item": "nprobe", "msg": "line is required with state=present"} failed: [testvm] (item=root) => {"ansible_loop_var": "item", "changed": false, "item": "root", "msg": "line is required with state=present"} failed: [testvm] (item=backup) => {"ansible_loop_var": "item", "changed": false, "item": "backup", "msg": "line is required with state=present"}

2
  • 1
    lineinfile is not meant to be used to only check if a line exists. It is meant to make sure that a line exists. This answer uses the check mode to reach your goal. Commented Dec 14, 2022 at 8:57
  • 2
    How are you going to recognize commented jobs from other comments? Commented Dec 14, 2022 at 13:23

1 Answer 1

1

As a hint see below how to create a dictionary comprising all crontab info

  1. Declare the variables
 cron_tabs_path: /var/cron/tabs cron_users: "{{ cron_user.files|map(attribute='path')| map('basename')|list }}" cron_tabs: "{{ cron_tab.results|map(attribute='stdout')| map('community.general.jc', 'crontab')|list }}" cron_tabs_dict_all: "{{ dict(ansible_play_hosts| zip(ansible_play_hosts| map('extract', hostvars, ['cron_tabs_dict']))) }}" 
  1. Find all crontab files (cron_users)
 - find: paths: "{{ cron_tabs_path }}" register: cron_user 
  1. Read all crontabs
 - command: "crontab -u {{ item }} -l" register: cron_tab loop: "{{ cron_users }}" 
  1. Create a dictionary of users and their crontabs
 - set_fact: cron_tabs_dict: "{{ dict(cron_users|zip(cron_tabs)) }}" 

For example, given the crontabs on remote hosts test_11 and test_13

shell> ssh admin@test_11 sudo crontab -u admin -l #Ansible: test_1 5 12 * * * echo test 1 #Ansible: test_5 5 14 * * * echo test 5 #Ansible: test_4 5 13 * * * echo test 4 shell> ssh admin@test_11 sudo crontab -u alice -l #Ansible: test_2 5 13 * * * echo test 2 shell> ssh admin@test_11 sudo crontab -u bob -l #Ansible: test_3 5 14 * * * echo test 3 
shell> ssh admin@test_13 sudo crontab -u admin -l #Ansible: test_1 5 12 * * * echo test 1 #Ansible: test_4 5 13 * * * echo test 4 #Ansible: test_5 5 14 * * * echo test 5 

The playbook

shell> cat pb.yml - hosts: test_11,test_13 vars: cron_tabs_path: /var/cron/tabs cron_tabs: "{{ cron_tab.results|map(attribute='stdout')| map('community.general.jc', 'crontab')|list }}" cron_users: "{{ cron_user.files|map(attribute='path')| map('basename')|list }}" cron_tabs_dict_all: "{{ dict(ansible_play_hosts| zip(ansible_play_hosts| map('extract', hostvars, ['cron_tabs_dict']))) }}" tasks: - find: paths: "{{ cron_tabs_path }}" register: cron_user - debug: var: cron_users - command: "crontab -u {{ item }} -l" register: cron_tab loop: "{{ cron_users }}" - debug: var: cron_tabs - set_fact: cron_tabs_dict: "{{ dict(cron_users|zip(cron_tabs)) }}" - debug: var: cron_tabs_dict|to_yaml - debug: var: cron_tabs_dict_all|to_yaml run_once: true 

gives

 cron_tabs_dict_all: test_11: admin: schedule: - command: echo test 1 day_of_month: ['*'] day_of_week: ['*'] hour: ['12'] minute: ['5'] month: ['*'] - command: echo test 5 day_of_month: ['*'] day_of_week: ['*'] hour: ['14'] minute: ['5'] month: ['*'] - command: echo test 4 day_of_month: ['*'] day_of_week: ['*'] hour: ['13'] minute: ['5'] month: ['*'] variables: [] alice: schedule: - command: echo test 2 day_of_month: ['*'] day_of_week: ['*'] hour: ['13'] minute: ['5'] month: ['*'] variables: [] bob: schedule: - command: echo test 3 day_of_month: ['*'] day_of_week: ['*'] hour: ['14'] minute: ['5'] month: ['*'] variables: [] test_13: admin: schedule: - command: echo test 1 day_of_month: ['*'] day_of_week: ['*'] hour: ['12'] minute: ['5'] month: ['*'] - command: echo test 4 day_of_month: ['*'] day_of_week: ['*'] hour: ['13'] minute: ['5'] month: ['*'] - command: echo test 5 day_of_month: ['*'] day_of_week: ['*'] hour: ['14'] minute: ['5'] month: ['*'] variables: [] 

Use getent to read /etc/passwd

 - getent: database: passwd 

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.