Sam Hooke

Append to .bashrc using Ansible

You can append to .bashrc using the Ansible blockinfile module.

Since Ansible is intended to be idempotent, by default it will add # BEGIN and # END comments around the block. This enables Ansible to detect whether the block has already been added, and so avoids making the change if the block already matches.

Following is a simple example of appending some code to .bashrc that shows our current Git branch in bash.

The code for appending §

This is the code we want to append to .bashrc:1

bashrc_extra.sh §
function parse_git_branch () {
  git branch 2> /dev/null | sed -e '/^[^*]/d' -e 's/* \(.*\)/\ \(\1)/'
}

RED="\[\033[01;31m\]"
YELLOW="\[\033[01;33m\]"
GREEN="\[\033[01;32m\]"
BLUE="\[\033[01;34m\]"
NO_COLOR="\[\033[00m\]"

PS1="$GREEN\u@\h$NO_COLOR:$BLUE\w$YELLOW\$(parse_git_branch)$NO_COLOR\$ "

Nothing particularly special here. Just make sure the bashrc_extra.sh file has unix line endings (LF), not Windows (CR LF), else when you run the playbook each line will have ^M at the end when viewed in less.

Playbook task §

We add this task to our playbook:

playbook.yml §
- name: Ensure .bashrc contains Git config
  ansible.builtin.blockinfile:
    path: "{{ ansible_env.HOME }}/.bashrc"
    block: "{{ lookup('ansible.builtin.file', 'bashrc_extra.sh') }}"
    state: present

It does the following:

  • Uses ansible_env.HOME to look up the HOME environment variable, which gives us the path to the home directory on the target machine.
  • The block uses ansible.builtin.file to read the contents of bashrc_extra.sh from the local machine.

We have this structure on our local machine:

.
├── playbook.yml
└── bashrc_extra.sh

Structure §

A quick aside…

You might prefer to put the bashrc_extra.sh in a config directory, especially as the project grows.

To do so, just specify 'config/bashrc_extra.sh' in the block:2

.
├── playbook.yml
└── config/
    └── bashrc_extra.sh

Running the playbook §

That’s it, now we can run the playbook.

$ ansible-playbook playbook.yml

After running the playbook, this is what ~/.bashrc on the target machine contains:

$ less ~/.bashrc
# ...snip...

# BEGIN ANSIBLE MANAGED BLOCK
function parse_git_branch () {
  git branch 2> /dev/null | sed -e '/^[^*]/d' -e 's/* \(.*\)/\ \(\1)/'
}

RED="\[\033[01;31m\]"
YELLOW="\[\033[01;33m\]"
GREEN="\[\033[01;32m\]"
BLUE="\[\033[01;34m\]"
NO_COLOR="\[\033[00m\]"

PS1="$GREEN\u@\h$NO_COLOR:$BLUE\w$YELLOW\$(parse_git_branch)$NO_COLOR\$ "
# END ANSIBLE MANAGED BLOCK

And if you run the playbook again, the task will make no changes, because the block is already applied.


  1. Taken from here. Thanks danielalvarenga and abdobouna↩︎

  2. Made with this fun tool↩︎

These are rough notes that vary greatly in quality and length, but prove useful to me, and hopefully to you too!

← Previous: Using Kerberos from an Ansible playbook
Next: Sphinx: Link to HTML from MyST Markdown →