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.