如何用Ansible批量禁用带指定标识的所有Cron任务?
问题:批量禁用带有统一Ansible标识的Cron条目
当前Cron配置
$ 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
现有命令及输出
列出所有启用的Cron
执行命令:
crontab -l | grep -v '#' | tr -d '\n'
输出:
*/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
提取所有Cron的#Ansible:值
执行命令:
crontab -l | awk '/^$/ { next ; } /^#/ { text=$2 ; } /^[^#]/ { print text; }'
输出:
test test
当前Ansible代码及问题
现有handlecron.yml代码:
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 }}"
问题:所有Cron条目共用同一个name: test,导致循环时每个启用的Cron会重复添加到每个#Ansible: test条目下,不符合预期。期望是将每个对应#Ansible: test的启用Cron条目注释(禁用),最终得到如下Cron配置:
$ 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
解决方案建议
方案1:直接编辑crontab文件(推荐,保留原有格式)
通过正则匹配找到#Ansible: test后的启用Cron条目,在其前添加#实现禁用,完全保留原有注释结构:
- name: 批量禁用带有#Ansible: test的Cron条目 hosts: localhost tasks: - name: 读取当前用户的crontab文件 slurp: src: /var/spool/cron/{{ ansible_user_id }} register: crontab_raw ignore_errors: true - name: 处理crontab内容,禁用目标条目 set_fact: modified_crontab: >- {{ crontab_raw.content | b64decode | regex_replace('(^#Ansible: test\\n)([^#].*)', '\\1#\\2', multiline=True) }} when: crontab_raw.content is defined - name: 将修改后的内容写入crontab copy: content: "{{ modified_crontab }}" dest: /var/spool/cron/{{ ansible_user_id }} mode: 0600 when: modified_crontab is defined
原理:利用正则表达式匹配#Ansible: test行后的非注释行,给该行前缀添加#,实现禁用。
方案2:用Ansible cron模块管理(符合Ansible最佳实践)
如果希望用cron模块标准化管理,需要为每个Cron条目设置唯一的name标识(避免重复覆盖),同时保留原有注释:
- name: 用cron模块批量禁用指定标识的Cron条目 hosts: localhost tasks: - name: 解析crontab为结构化数据(注释|||Ansible标识|||Cron命令) raw: | crontab -l | awk ' /^#Cron/ { comment=$0; } /^#Ansible:/ { ansible_tag=$2; } /^[^#]/ { printf "%s|||%s|||%s\n", comment, ansible_tag, $0; } ' ignore_errors: true register: cron_entries - name: 禁用匹配#Ansible: test的条目 cron: name: "{{ item.split('|||')[0] | regex_replace('#Cron to ', '') | replace(' ', '_') }}" # 用注释生成唯一name job: "{{ item.split('|||')[2] }}" state: present disabled: true comment: "{{ item.split('|||')[0] }}" # 保留原注释 when: item.split('|||')[1] == 'test' with_items: "{{ cron_entries.stdout_lines }}"
原理:先把每个启用的Cron条目和关联注释、Ansible标识打包成结构化数据,再循环处理每个条目,用注释生成唯一name避免冲突,同时设置disabled: true禁用条目。
内容的提问来源于stack exchange,提问作者Ashar
相关产品推荐
相关产品推荐

