Add a path to the global $PATH with Ansible

When building certain roles or playbooks, I often need to add a new directory to the global system-wide $PATH so automation tools, users, or scripts will be able to find other scripts or binaries they need to run. Just today I did this yet again for my geerlingguy.ruby Ansible role, and I thought I should document how I do it here—mostly so I have an easy searchable reference for it the next time I have to do this and want a copy-paste example!

    - name: Add another bin dir to system-wide $PATH.
      copy:
        dest: /etc/profile.d/custom-path.sh
        content: 'PATH=$PATH:{{ my_custom_path_var }}'

In this case, my_custom_path_var would refer to the path you want added to the system-wide $PATH. Now, on next login, you should see your custom path when you echo $PATH!

Comments

Appreciate you documenting this, might want to include a mode: '0644' in the copy portion to enable other users to use the path.
Thanks again,
Greg

I think you’re missing the “export” command in the script content.

This method is okay for the first run, but it's not idempotent. Every time you run it, it will add it again. You can end up with a lot of duplicates. This lineinfile method will check to make sure the path does not already exist (in what ever file your modifying, the PATH in '/etc/environment' is used for non-interactive logins). If it's missing, it will append it to the PATH. One caveat, if it does exist and it's the first directory, it will move it to the end. It took me about 25 hours to fine tune this regex.

In this example, create a var named 'new_path' with the directory you want to add to PATH.

  lineinfile:
    dest:           "/etc/environment"
    state:          present
    regexp:         '^(PATH=\")({{ new_path }}:)?((?(2).*?(?!(?:.\"))|.*?(?!(?:{{ new_path }}))))(:{{ new_path }})?((?(4).*|\"))'
    line:           '\1\3:{{ new_path }}\5'
    backrefs:       yes

Much simpified idempotent solution:
- name: Add another bin dir to system-wide $PATH.
# Make sure its idempotent otherwise PATH grows on every run.
when: ansible_env.PATH is not search(my_custom_path_var)
copy:
dest: /etc/profile.d/custom-path.sh
content: 'PATH=$PATH:{{ my_custom_path_var }}'