{"id":1369,"date":"2024-06-12T07:14:17","date_gmt":"2024-06-12T07:14:17","guid":{"rendered":"http:\/\/shijuvarghese.com\/?p=1369"},"modified":"2025-05-24T04:06:22","modified_gmt":"2025-05-24T04:06:22","slug":"ansible-scheduling-jobs-using-at-and-cron","status":"publish","type":"post","link":"http:\/\/shijuvarghese.com\/?p=1369","title":{"rendered":"Ansible: Scheduling jobs using AT and CRON"},"content":{"rendered":"<p>Ansible provides a means to schedule jobs to be executed on a future time, weather it is a one time job or ones to be repeated at regular interval. This is done using the modules &#8220;<strong>ansible.builtin.cron<\/strong>&#8221; OR &#8220;<strong>ansible.posix.at<\/strong>&#8221; based on the requirement.<\/p>\n<p>Below is a playbook that will execute a command &#8220;touch \/root\/test1.txt&#8221; 2 minutes after ansible executes the playbook on the managed node 192.168.48.129 (centosMYOBvm)<\/p>\n<p>Let us check the status of the managed node<\/p>\n<p><strong>[root@centosMYOBvm ~]#<\/strong> systemctl status atd<br \/>\nUnit atd.service could not be found.<br \/>\n<strong>[root@centosMYOBvm ~]#<\/strong> ls -l \/root\/test1.txt<br \/>\nls: cannot access &#8216;\/root\/test1.txt&#8217;: No such file or directory<\/p>\n<p>Now let us create and run a playbook to install &#8220;at&#8221; package and add a file in root directory<\/p>\n<p><strong>[root@centos9vm ~]#<\/strong> cat schedule.yml<\/p>\n<p>===== ==<br \/>\n<em>&#8211; &#8211; &#8211;<\/em><br \/>\n<em>&#8211; name: Playbook to install and run AT commands<\/em><br \/>\n<em> \u00a0 \u00a0 hosts: 192.168.48.129<\/em><br \/>\n<em> \u00a0 \u00a0 tasks:<\/em><br \/>\n<em> \u00a0 \u00a0 \u00a0 \u00a0 &#8211; name: Task to install at module in destination node<\/em><br \/>\n<em> \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 ansible.builtin.dnf:<\/em><br \/>\n<em> \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 name: at<\/em><br \/>\n<em> \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 state: present<\/em><\/p>\n<p><em> \u00a0 \u00a0 \u00a0 \u00a0 &#8211; name: Tast to start atd service<\/em><br \/>\n<em> \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 ansible.builtin.service:<\/em><br \/>\n<em> \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 name: atd<\/em><br \/>\n<em> \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 state: started<\/em><br \/>\n<em> \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 enabled: yes<\/em><\/p>\n<p><em> \u00a0 \u00a0 \u00a0 \u00a0 &#8211; name: Task to run the AT command<\/em><br \/>\n<em> \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 ansible.builtin.at:<\/em><br \/>\n<em> \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 command: touch \/root\/test1.txt<\/em><br \/>\n<em> \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 count: 2<\/em><br \/>\n<em> \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 units: minutes<\/em><\/p>\n<p>===== ==<\/p>\n<p><strong>[root@centos9vm ~]#<\/strong> ansible-navigator run -m stdout schedule.yml<\/p>\n<p>==== ===<\/p>\n<p>PLAY [Playbook to install and run AT commands] *********************************<\/p>\n<p>TASK [Gathering Facts] *********************************************************<br \/>\nok: [192.168.48.129]<\/p>\n<p>TASK [Task to install at module in destination node] ***************************<br \/>\nchanged: [192.168.48.129]<\/p>\n<p>TASK [Tast to start atd service] ***********************************************<br \/>\nchanged: [192.168.48.129]<\/p>\n<p>TASK [Task to run the AT command] **********************************************<br \/>\nchanged: [192.168.48.129]<\/p>\n<p>PLAY RECAP *********************************************************************<br \/>\n192.168.48.129 : ok=4 changed=3 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0<\/p>\n<p>==== ==<\/p>\n<p>Let us verify the result in the managed node.<\/p>\n<p><strong>[root@centosMYOBvm ~]#<\/strong> systemctl status atd<\/p>\n<p>=== ===<br \/>\n\u25cf atd.service &#8211; Deferred execution scheduler<br \/>\nLoaded: loaded (\/usr\/lib\/systemd\/system\/atd.service; enabled; preset: enabled)<br \/>\nActive: active (running) since Wed 2024-06-12 12:38:24 IST; 4s ago<br \/>\n=== ==<\/p>\n<p><strong>[root@centosMYOBvm ~]#<\/strong> atq<br \/>\n1 Wed Jun 12 12:40:00 2024 a root<br \/>\n<strong>[root@centosMYOBvm ~]#<\/strong> date<br \/>\nWed Jun 12 12:38:35 PM IST 2024<br \/>\n<strong>[root@centosMYOBvm ~]#<\/strong> ls -l \/root\/test1.txt<br \/>\nls: cannot access &#8216;\/root\/test1.txt&#8217;: No such file or directory<br \/>\n<strong>[root@centosMYOBvm ~]#<\/strong> ls -l \/root\/test1.txt<br \/>\n-rw-r&#8211;r&#8211;. 1 root root 0 Jun 12 12:40 \/root\/test1.txt<\/p>\n<p style=\"text-align: center;\">&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-******&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-<\/p>\n<p style=\"text-align: left;\">Now let us move to scheduling repetitive jobs using CRON. In the below example we will use ansible to install crontabs and add an entry in crontab<\/p>\n<p><strong>[root@centos9vm ~]#<\/strong> cat cron_schedule.yml<\/p>\n<p>== ===<br \/>\n<em>&#8211; &#8211; &#8211;<\/em><br \/>\n<em>&#8211; name: Playbook to install and add cron jobs<\/em><br \/>\n<em> \u00a0 \u00a0 hosts: 192.168.48.129<\/em><br \/>\n<em> \u00a0 \u00a0 tasks:<\/em><br \/>\n<em> \u00a0 \u00a0 \u00a0 \u00a0 &#8211; name: Task to install cron and start the service<\/em><br \/>\n<em> \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 ansible.builtin.dnf:<\/em><br \/>\n<em> \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 name: crontabs<\/em><br \/>\n<em> \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 state: present<\/em><\/p>\n<p><em> \u00a0 \u00a0 \u00a0 \u00a0 &#8211; name: Task to start cron service<\/em><br \/>\n<em> \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 ansible.builtin.service:<\/em><br \/>\n<em> \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 name: crond<\/em><br \/>\n<em> \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 state: started<\/em><br \/>\n<em> \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 enabled: yes<\/em><\/p>\n<p><em> \u00a0 \u00a0 \u00a0 \u00a0 &#8211; name: Add a cron job to wtire Hi to \/root\/test1.txt<\/em><br \/>\n<em> \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 ansible.builtin.cron:<\/em><br \/>\n<em> \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 name: Write to test1<\/em><br \/>\n<em> \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 minute: &#8220;10&#8221;<\/em><br \/>\n<em> \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 hour: &#8220;19&#8221;<\/em><br \/>\n<em> \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 job: echo &#8220;Hi&#8221; &gt; \/root\/test1.txt<\/em><\/p>\n<p>=== ===<\/p>\n<p>Let us verify if cron is already installed in the managed node.<\/p>\n<p><strong>[root@centosMYOBvm ~]#<\/strong> systemctl status crond<br \/>\nUnit crond.service could not be found.<\/p>\n<p>==== ===<\/p>\n<p>Now let us run the playbook<\/p>\n<p><strong>[root@centos9vm ~]#<\/strong> ansible-navigator run -m stdout cron_schedule.yml<\/p>\n<p>==== ===<\/p>\n<p>PLAY [Playbook to install and add cron jobs] ***********************************<\/p>\n<p>TASK [Gathering Facts] *********************************************************<br \/>\nok: [192.168.48.129]<\/p>\n<p>TASK [Task to install cron and start the service] ******************************<br \/>\nchanged: [192.168.48.129]<\/p>\n<p>TASK [Task to start cron service] **********************************************<br \/>\nchanged: [192.168.48.129]<\/p>\n<p>TASK [Add a cron job to wtire Hi to \/root\/test1.txt] ***************************<br \/>\nok: [192.168.48.129]<\/p>\n<p>PLAY RECAP *********************************************************************<br \/>\n192.168.48.129 : ok=4 changed=2 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0<\/p>\n<p>==== ===<\/p>\n<p>Now let us verify back in the managed node:<\/p>\n<p><strong>[root@centosMYOBvm ~]#<\/strong> systemctl status crond<\/p>\n<p>===== ==<br \/>\n\u25cf crond.service &#8211; Command Scheduler<br \/>\nLoaded: loaded (\/usr\/lib\/systemd\/system\/crond.service; enabled; preset: enabled)<br \/>\nActive: active (running) since Wed 2024-06-12 19:24:58 IST; 38s ago<\/p>\n<p>====== ==<\/p>\n<p><strong>[root@centosMYOBvm ~]#<\/strong> crontab -l<\/p>\n<p>===== ===<br \/>\n#Ansible: Write to test1<br \/>\n10 19 * * * echo &#8220;Hi&#8221; &gt; \/root\/test1.txt<\/p>\n<p>===== ===<\/p>\n","protected":false},"excerpt":{"rendered":"<div class=\"mh-excerpt\"><p>Ansible provides a means to schedule jobs to be executed on a future time, weather it is a one time job or ones to be <a class=\"mh-excerpt-more\" href=\"http:\/\/shijuvarghese.com\/?p=1369\" title=\"Ansible: Scheduling jobs using AT and CRON\">[&#8230;]<\/a><\/p>\n<\/div>","protected":false},"author":1,"featured_media":1792,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[32,21,3],"tags":[],"class_list":["post-1369","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-ansible","category-devops","category-linux"],"_links":{"self":[{"href":"http:\/\/shijuvarghese.com\/index.php?rest_route=\/wp\/v2\/posts\/1369","targetHints":{"allow":["GET"]}}],"collection":[{"href":"http:\/\/shijuvarghese.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/shijuvarghese.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/shijuvarghese.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"http:\/\/shijuvarghese.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=1369"}],"version-history":[{"count":12,"href":"http:\/\/shijuvarghese.com\/index.php?rest_route=\/wp\/v2\/posts\/1369\/revisions"}],"predecessor-version":[{"id":1594,"href":"http:\/\/shijuvarghese.com\/index.php?rest_route=\/wp\/v2\/posts\/1369\/revisions\/1594"}],"wp:featuredmedia":[{"embeddable":true,"href":"http:\/\/shijuvarghese.com\/index.php?rest_route=\/wp\/v2\/media\/1792"}],"wp:attachment":[{"href":"http:\/\/shijuvarghese.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=1369"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/shijuvarghese.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=1369"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/shijuvarghese.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=1369"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}