When automating RabbitMQ administration with Ansible, many developers encounter a puzzling scenario where commands work locally but fail remotely with:
fatal: [IP]: FAILED! => {"changed": false, "cmd": "rabbitmqctl list_vhosts",
"failed": true, "msg": "[Errno 2] No such file or directory", "rc": 2}
The root cause typically stems from environment and PATH differences between local and remote execution. When Ansible connects remotely via SSH, it doesn't load the same shell environment as an interactive login session.
Key factors contributing to this behavior:
- The full path to
rabbitmqctl
isn't specified - Environment variables (like ERLANG_HOME) aren't loaded
- The SSH session doesn't source the same profile scripts
1. Absolute Path Specification
The most reliable approach is using the full path to rabbitmqctl:
- name: get vhosts
command: /usr/sbin/rabbitmqctl list_vhosts
register: vhosts
changed_when: false
2. Environment-Aware Execution
For complex setups where environment variables matter:
- name: get vhosts
shell: |
source /etc/profile
/usr/sbin/rabbitmqctl list_vhosts
args:
executable: /bin/bash
register: vhosts
changed_when: false
3. Become User Context
When RabbitMQ runs under specific user permissions:
- name: get vhosts
become: yes
become_user: rabbitmq
command: /usr/sbin/rabbitmqctl list_vhosts
register: vhosts
changed_when: false
For production environments, consider these robust patterns:
Custom Facts for Path Discovery
- name: find rabbitmqctl path
shell: which rabbitmqctl
register: rabbitmqctl_path
changed_when: false
- name: use discovered path
command: "{{ rabbitmqctl_path.stdout }} list_vhosts"
register: vhosts
changed_when: false
Using RabbitMQ Module (Ansible 2.8+)
- name: get vhosts
rabbitmq_vhost:
list: yes
register: vhosts
When issues persist, add these debugging steps:
- name: debug environment
shell: env
register: env_output
- debug: var=env_output.stdout_lines
This reveals exactly what environment variables are available during remote execution.
Remember that RabbitMQ commands often require:
- Proper Erlang environment setup
- Correct cookie file permissions
- SELinux context considerations
Always test your playbook with -vvv
flag for detailed execution tracing.
When running Ansible playbooks that execute rabbitmqctl
commands remotely, you might encounter this frustrating error:
fatal: [IP]: FAILED! => {"changed": false, "cmd": "rabbitmqctl list_vhosts",
"failed": true, "msg": "[Errno 2] No such file or directory", "rc": 2}
The puzzling aspect is that the same playbook works fine when run locally on the target machine. This suggests the issue relates to how Ansible executes commands remotely versus locally.
The fundamental reason this fails remotely stems from how Ansible handles command execution:
- Environment variables: Remote execution doesn't inherit the same environment as a local shell session
- Path resolution: The full path to rabbitmqctl isn't available in the restricted remote execution environment
- User context: The command may run under a different user than expected
After testing multiple approaches, here are the most reliable solutions:
1. Using Absolute Paths
The most straightforward fix is specifying the full path to rabbitmqctl:
- name: get vhosts
command: /usr/sbin/rabbitmqctl list_vhosts
register: vhosts
changed_when: false
You may need to verify the exact path on your system with:
which rabbitmqctl
2. Setting the Correct Environment
RabbitMQ commands often require specific environment variables. This approach ensures they're available:
- name: get vhosts
shell: |
. /etc/profile
. ~/.bashrc
rabbitmqctl list_vhosts
args:
executable: /bin/bash
register: vhosts
changed_when: false
3. Using the RabbitMQ Ansible Module
For better reliability, consider using the dedicated rabbitmq_* modules:
- name: get vhosts
rabbitmq_vhost:
list: yes
register: vhosts
The common suggestion to switch from command
to shell
often fails because:
- It still doesn't address the missing PATH issue
- Environment variables needed by rabbitmqctl aren't automatically loaded
- The execution context may lack necessary permissions
To better understand the remote execution context, add this debug task:
- name: debug environment
shell: |
echo "PATH: $PATH"
echo "USER: $(whoami)"
echo "HOME: $HOME"
register: env_debug
- debug: var=env_debug.stdout_lines
For production environments, combining absolute paths with environment setup provides the most reliable solution:
- name: get vhosts reliably
shell: |
. /etc/profile
/usr/sbin/rabbitmqctl list_vhosts
args:
executable: /bin/bash
register: vhosts
changed_when: false