{"id":5991,"date":"2025-01-26T13:07:10","date_gmt":"2025-01-26T13:07:10","guid":{"rendered":"https:\/\/linuxbuz.com\/?p=5991"},"modified":"2025-07-11T04:48:15","modified_gmt":"2025-07-11T04:48:15","slug":"ansible-loops-example","status":"publish","type":"post","link":"https:\/\/linuxbuz.com\/devops\/ansible-loops-example","title":{"rendered":"Ansible Loops: Simplify Repetitive Tasks in Playbooks"},"content":{"rendered":"<p style=\"text-align: justify;\">Ansible offers a robust feature to iterate over tasks using loops. <a href=\"https:\/\/docs.ansible.com\/ansible\/latest\/playbook_guide\/playbooks_loops.html\" target=\"_blank\" rel=\"noopener\"><strong>Loops in Ansible<\/strong><\/a> simplify repetitive tasks, improve code readability, and reduce redundancy. Loops in Ansible allow you to run the same task multiple times with different inputs. They are useful when:<\/p>\n<ul>\n<li>Installing multiple packages<\/li>\n<li>Creating multiple users<\/li>\n<li>Copying a set of files to a target location<\/li>\n<\/ul>\n<p style=\"text-align: justify;\">Ansible provides two primary ways to define <strong>loops: with_items<\/strong> and the modern <strong>loop<\/strong> keyword.<\/p>\n<p style=\"text-align: justify;\"><em>This guide will cover how to use <strong>with_items, loop, loop control, with_nested,<\/strong> and <strong>block loops<\/strong> in Ansible playbooks with practical examples.<\/em><\/p>\n<div class=\"su-box su-box-style-default\" id=\"\" style=\"border-color:#001a66;border-radius:3px;max-width:none\"><div class=\"su-box-title\" style=\"background-color:#004d99;color:#FFFFFF;border-top-left-radius:1px;border-top-right-radius:1px\">\ud83d\udca1 Recommended Reading<\/div><div class=\"su-box-content su-u-clearfix su-u-trim\" style=\"border-bottom-left-radius:1px;border-bottom-right-radius:1px\">\n\ud83d\udc49 <a href=\"https:\/\/linuxbuz.com\/linuxhowto\/how-to-get-free-cloud-vps-server-step-by-step-guide\" target=\"_blank\" rel=\"noopener\">How to Get a Free Cloud Server for Testing<\/a><br \/>\n<\/div><\/div>\n<div id=\"ez-toc-container\" class=\"ez-toc-v2_0_82_2 counter-hierarchy ez-toc-counter ez-toc-custom ez-toc-container-direction\">\n<div class=\"ez-toc-title-container\">\n<p class=\"ez-toc-title\" style=\"cursor:inherit\">Table of Contents<\/p>\n<span class=\"ez-toc-title-toggle\"><\/span><\/div>\n<nav><ul class='ez-toc-list ez-toc-list-level-1 ' ><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-1\" href=\"https:\/\/linuxbuz.com\/devops\/ansible-loops-example\/#Using_with_items_in_Ansible\" >Using with_items in Ansible<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-2\" href=\"https:\/\/linuxbuz.com\/devops\/ansible-loops-example\/#Using_the_loop_Keyword_in_Ansible\" >Using the loop Keyword in Ansible<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-3\" href=\"https:\/\/linuxbuz.com\/devops\/ansible-loops-example\/#Controlling_Loops_with_loop_control\" >Controlling Loops with loop_control<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-4\" href=\"https:\/\/linuxbuz.com\/devops\/ansible-loops-example\/#Working_with_Ansible_Nested_Loops\" >Working with Ansible Nested Loops<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-5\" href=\"https:\/\/linuxbuz.com\/devops\/ansible-loops-example\/#Using_Block_Loops_in_Ansible\" >Using Block Loops in Ansible<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-6\" href=\"https:\/\/linuxbuz.com\/devops\/ansible-loops-example\/#Error_Handling_in_Loop\" >Error Handling in Loop<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-7\" href=\"https:\/\/linuxbuz.com\/devops\/ansible-loops-example\/#Conclusion\" >Conclusion<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-8\" href=\"https:\/\/linuxbuz.com\/devops\/ansible-loops-example\/#FAQs\" >FAQs<\/a><\/li><\/ul><\/nav><\/div>\n\n<h2><span class=\"ez-toc-section\" id=\"Using_with_items_in_Ansible\"><\/span>Using with_items in Ansible<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p style=\"text-align: justify;\">The <strong>with_items<\/strong> construct is one of the older but widely used methods for creating loops in Ansible. It works by iterating over a list of items and performing the specified task for each item.<\/p>\n<p>Here is an <a href=\"https:\/\/linuxbuz.com\/devops\/ansible-playbooks-examples\" target=\"_blank\" rel=\"noopener\"><strong>example playbook<\/strong><\/a>:<\/p>\n<pre style=\"background-color: #262626; color: white; border-radius: 7px; overflow: auto;\"><code>- name: Install multiple packages\r\n  hosts: webservers\r\n  tasks:\r\n    - name: Install multiple packages\r\n      apt:\r\n        name: \"{{ item }}\"\r\n        state: present\r\n      with_items:\r\n        - nginx\r\n        - curl\r\n        - git<\/code><\/pre>\n<p style=\"text-align: justify;\">In the above example, <strong>with_items<\/strong> loop iterates over a list of packages: <strong>nginx, curl,<\/strong> and <strong>git.<\/strong> These packages will be installed sequentially with <a href=\"https:\/\/linuxbuz.com\/devops\/ansible-apt-module-example\" target=\"_blank\" rel=\"noopener\"><strong>apt module<\/strong><\/a> on the <strong>webservers<\/strong> group.<\/p>\n<h2><span class=\"ez-toc-section\" id=\"Using_the_loop_Keyword_in_Ansible\"><\/span>Using the loop Keyword in Ansible<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p style=\"text-align: justify;\">The <strong>loop<\/strong> keyword is a more modern alternative to <strong>with_items.<\/strong> It provides better readability and supports advanced features like dictionaries and <strong>nested loops.<\/strong><\/p>\n<p>Here is an example playbook to <a href=\"https:\/\/linuxbuz.com\/devops\/ansible-user-module#Add_Multiple_Users_Using_Playbook\" target=\"_blank\" rel=\"noopener\"><strong>add multiple users<\/strong><\/a> on remote hosts.<\/p>\n<pre style=\"background-color: #262626; color: white; border-radius: 7px; overflow: auto;\"><code>- name: Add multiple users\r\n  hosts: webservers\r\n  tasks:\r\n    - name: Create multiple users\r\n      user:\r\n        name: \"{{ item.name }}\"\r\n        shell: \"{{ item.shell }}\"\r\n        state: present\r\n      loop:\r\n        - { name: 'alice', shell: '\/bin\/bash' }\r\n        - { name: 'bob', shell: '\/bin\/zsh' }<\/code><\/pre>\n<p>The above playbook iterates through a list of users and creates them using the <a href=\"https:\/\/linuxbuz.com\/devops\/ansible-user-module\" target=\"_blank\" rel=\"noopener\"><strong>user module<\/strong><\/a>.<\/p>\n<h2><span class=\"ez-toc-section\" id=\"Controlling_Loops_with_loop_control\"><\/span>Controlling Loops with loop_control<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p style=\"text-align: justify;\">Ansible&#8217;s <strong>loop_control<\/strong> allows you to customize how loops behave. You can control variables like index and label formatting for better debugging and reporting.<\/p>\n<p>Here&#8217;s an example:<\/p>\n<pre style=\"background-color: #262626; color: white; border-radius: 7px; overflow: auto;\"><code>- name: Create numbered directories\r\n  hosts: webservers\r\n  tasks:\r\n    - name: Create directories with index\r\n      file:\r\n        path: \"\/tmp\/directory_{{ item }}\"\r\n        state: directory\r\n      loop: \"{{ range(1, 4) | list }}\"\r\n      loop_control:\r\n        index_var: index<\/code><\/pre>\n<p><strong>Explanation:<\/strong><\/p>\n<ul>\n<li><strong>range(1,<\/strong> 4) generates numbers from 1 to 3.<\/li>\n<li><strong>index_var<\/strong> stores the current index for use in tasks.<\/li>\n<\/ul>\n<p style=\"text-align: justify;\">This playbook creates directories <strong>(\/tmp\/directory_1, \/tmp\/directory_2,<\/strong> etc.) and assigns a custom index for each iteration using <strong>loop_control.<\/strong><\/p>\n<h2><span class=\"ez-toc-section\" id=\"Working_with_Ansible_Nested_Loops\"><\/span>Working with Ansible Nested Loops<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p style=\"text-align: justify;\">Nested loops allow tasks to iterate over multiple lists simultaneously. This is useful when dealing with matrix-like configurations.<\/p>\n<p><strong>Configuring services for multiple hosts:<\/strong><\/p>\n<pre style=\"background-color: #262626; color: white; border-radius: 7px; overflow: auto;\"><code>- name: Configure services on hosts\r\n  hosts: webservers\r\n  tasks:\r\n    - name: Configure services with nested loops\r\n      debug:\r\n        msg: \"Configuring {{ item.0 }} on {{ item.1 }}\"\r\n      with_nested:\r\n        - [\"nginx\", \"apache\"]\r\n        - [\"host1\", \"host2\"]<\/code><\/pre>\n<p>This playbook configures services <strong>(nginx, apache)<\/strong> on multiple hosts <strong>(host1, host2)<\/strong> using a <strong>nested loop<\/strong> to iterate over both lists.<\/p>\n<h2><span class=\"ez-toc-section\" id=\"Using_Block_Loops_in_Ansible\"><\/span>Using Block Loops in Ansible<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p style=\"text-align: justify;\">Sometimes, you want to <a href=\"https:\/\/linuxbuz.com\/devops\/ansible-block-module\" target=\"_blank\" rel=\"noopener\"><strong>apply a set of tasks<\/strong><\/a> (a block) repeatedly. <strong>Block loops<\/strong> let you loop over multiple tasks as a group.<\/p>\n<p><strong>Example playbook:<\/strong><\/p>\n<pre style=\"background-color: #262626; color: white; border-radius: 7px; overflow: auto;\"><code>- name: Manage files with a block loop\r\n  hosts: webservers\r\n  tasks:\r\n    - block:\r\n        - name: Create file\r\n          file:\r\n            path: \"\/tmp\/{{ item }}\"\r\n            state: touch\r\n        - name: Add content to file\r\n          lineinfile:\r\n            path: \"\/tmp\/{{ item }}\"\r\n            line: \"Managed by Ansible\"\r\n      loop:\r\n        - file1.txt\r\n        - file2.txt<\/code><\/pre>\n<p><strong>In this example:<\/strong><\/p>\n<ul>\n<li><a href=\"https:\/\/linuxbuz.com\/devops\/ansible-file-module-examples\" target=\"_blank\" rel=\"noopener\"><strong>File module<\/strong><\/a> ensures the specified files <strong>(file1.txt<\/strong> and <strong>file2.txt)<\/strong> are created in the <strong>\/tmp<\/strong> directory.<\/li>\n<li><a href=\"https:\/\/linuxbuz.com\/devops\/ansible-lineinfile-module-example\" target=\"_blank\" rel=\"noopener\"><strong>Lineinfile<\/strong><\/a> module adds the line <strong>&#8220;Managed by Ansible&#8221;<\/strong> to each file, ensuring it exists without duplication.<\/li>\n<li>Loop iterates over the list of file names <strong>(file1.txt<\/strong> and <strong>file2.txt)<\/strong> and applies the tasks in the block to each file.<\/li>\n<\/ul>\n<h2><span class=\"ez-toc-section\" id=\"Error_Handling_in_Loop\"><\/span>Error Handling in Loop<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p style=\"text-align: justify;\">When running loops in Ansible, it&#8217;s important to handle errors gracefully, especially in cases where one failed iteration shouldn\u2019t stop the execution of subsequent tasks.<\/p>\n<p style=\"text-align: justify;\">You can use the <strong>ignore_errors: yes<\/strong> directive to ensure that a failed iteration does not stop the playbook.<\/p>\n<p><strong>Example: installing packages with <a href=\"https:\/\/linuxbuz.com\/devops\/ansible-ignore_errors-example\" target=\"_blank\" rel=\"noopener\">ignored errors<\/a><\/strong><\/p>\n<pre style=\"background-color: #262626; color: white; border-radius: 7px; overflow: auto;\"><code>- name: Install multiple packages ignoring errors\r\n  hosts: webservers\r\n  tasks:\r\n    - name: Install packages\r\n      apt:\r\n        name: \"{{ item }}\"\r\n        state: present\r\n      loop:\r\n        - valid_package\r\n        - invalid_package  # This will cause an error\r\n        - another_valid_package\r\n      ignore_errors: yes<\/code><\/pre>\n<p style=\"text-align: justify;\">If <strong>invalid_package<\/strong> fails to install, Ansible will skip the error and proceed with the next item in the loop.<\/p>\n<h2><span class=\"ez-toc-section\" id=\"Conclusion\"><\/span>Conclusion<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p style=\"text-align: justify;\">Ansible loops are essential for simplifying repetitive tasks and enhancing playbook efficiency. They help automate actions like installing multiple packages, creating users, or configuring services across multiple hosts.<\/p>\n<h2><span class=\"ez-toc-section\" id=\"FAQs\"><\/span>FAQs<span class=\"ez-toc-section-end\"><\/span><\/h2>\n        <section class=\"sc_fs_faq sc_card \">\n            <div>\n\t\t\t\t<h6>1. How is the loop keyword different from with_items?<\/h6>                <div>\n\t\t\t\t\t                    <p>\n\t\t\t\t\t\tThe loop keyword is a modern alternative to with_items, offering better readability and support for advanced features like dictionaries.                    <\/p>\n                <\/div>\n            <\/div>\n        <\/section>\n\t\t        <section class=\"sc_fs_faq sc_card \">\n            <div>\n\t\t\t\t<h6>2. Why should I use loops in Ansible?<\/h6>                <div>\n\t\t\t\t\t                    <p>\n\t\t\t\t\t\tLoops save time, reduce repetitive code, and make your playbooks more efficient and easier to maintain.                    <\/p>\n                <\/div>\n            <\/div>\n        <\/section>\n\t\t        <section class=\"sc_fs_faq sc_card \">\n            <div>\n\t\t\t\t<h6>3. How do I handle errors in loops?<\/h6>                <div>\n\t\t\t\t\t                    <p>\n\t\t\t\t\t\tYou can use ignore_errors: yes or rescue blocks within a task to handle errors during loop iterations without stopping the playbook.                    <\/p>\n                <\/div>\n            <\/div>\n        <\/section>\n\t\t\n<script type=\"application\/ld+json\">\n    {\n\t\t\"@context\": \"https:\/\/schema.org\",\n\t\t\"@type\": \"FAQPage\",\n\t\t\"mainEntity\": [\n\t\t\t\t{\n\t\t\t\t\"@type\": \"Question\",\n\t\t\t\t\"name\": \"1. How is the loop keyword different from with_items?\",\n\t\t\t\t\"acceptedAnswer\": {\n\t\t\t\t\t\"@type\": \"Answer\",\n\t\t\t\t\t\"text\": \"The loop keyword is a modern alternative to with_items, offering better readability and support for advanced features like dictionaries.\"\n\t\t\t\t\t\t\t\t\t}\n\t\t\t}\n\t\t\t,\t\t\t\t{\n\t\t\t\t\"@type\": \"Question\",\n\t\t\t\t\"name\": \"2. Why should I use loops in Ansible?\",\n\t\t\t\t\"acceptedAnswer\": {\n\t\t\t\t\t\"@type\": \"Answer\",\n\t\t\t\t\t\"text\": \"Loops save time, reduce repetitive code, and make your playbooks more efficient and easier to maintain.\"\n\t\t\t\t\t\t\t\t\t}\n\t\t\t}\n\t\t\t,\t\t\t\t{\n\t\t\t\t\"@type\": \"Question\",\n\t\t\t\t\"name\": \"3. How do I handle errors in loops?\",\n\t\t\t\t\"acceptedAnswer\": {\n\t\t\t\t\t\"@type\": \"Answer\",\n\t\t\t\t\t\"text\": \"You can use ignore_errors: yes or rescue blocks within a task to handle errors during loop iterations without stopping the playbook.\"\n\t\t\t\t\t\t\t\t\t}\n\t\t\t}\n\t\t\t\t    ]\n}\n<\/script>\n\n","protected":false},"excerpt":{"rendered":"<p>Ansible offers a robust feature to iterate over tasks using loops. Loops in Ansible simplify repetitive tasks, improve code readability, and reduce redundancy. Loops in Ansible allow you to run &hellip; <\/p>\n","protected":false},"author":1,"featured_media":5992,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"om_disable_all_campaigns":false,"_monsterinsights_skip_tracking":false,"_monsterinsights_sitenote_active":false,"_monsterinsights_sitenote_note":"","_monsterinsights_sitenote_category":0,"two_page_speed":[],"footnotes":""},"categories":[828],"tags":[],"class_list":["post-5991","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-devops"],"aioseo_notices":[],"_links":{"self":[{"href":"https:\/\/linuxbuz.com\/wp-json\/wp\/v2\/posts\/5991","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/linuxbuz.com\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/linuxbuz.com\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/linuxbuz.com\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/linuxbuz.com\/wp-json\/wp\/v2\/comments?post=5991"}],"version-history":[{"count":0,"href":"https:\/\/linuxbuz.com\/wp-json\/wp\/v2\/posts\/5991\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/linuxbuz.com\/wp-json\/wp\/v2\/media\/5992"}],"wp:attachment":[{"href":"https:\/\/linuxbuz.com\/wp-json\/wp\/v2\/media?parent=5991"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/linuxbuz.com\/wp-json\/wp\/v2\/categories?post=5991"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/linuxbuz.com\/wp-json\/wp\/v2\/tags?post=5991"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}