Fix Ansible '[Errno 2] No such file or directory' trên Remote Hosts

intermediate🔧 Ansible2026-03-18| Ansible 2.9+, remote Linux hosts (Ubuntu, CentOS, Debian), kết nối SSH

Error Message

Errno 2: No such file or directory on remote host
#ansible#command#path#remote

Tình huống xảy ra2 giờ sáng và playbook của bạn vừa chết với thông báo sau:

fatal: [web01]: FAILED! => {
  'changed': false,
  'cmd': 'some_nonexistent_command',
  'msg': '[Errno 2] No such file or directory: b\'some_nonexistent_command\'',
  'rc': 2
}

Bạn SSH vào host, chạy lệnh thủ công — hoàn toàn bình thường. Vậy tại sao Ansible lại thất bại? PATH. Ansible kết nối qua SSH và khởi tạo một shell không tương tác, không phải login shell. Shell đó bỏ qua hoàn toàn ~/.bashrc/etc/profile. Các công cụ cài qua nvm, pyenv, rbenv, hoặc script tùy chỉnh đặt binary vào các thư mục riêng của từng user — không có thư mục nào trong số đó xuất hiện trong PATH rút gọn của Ansible.

Quy trình Debug### Bước 1: Xác nhận đây là vấn đề PATH, không phải thiếu cài đặtBắt đầu bằng cách kiểm tra xem lệnh có tồn tại trên remote host không và nó nằm ở đâu:

- name: Tìm vị trí của lệnh
  command: which some_command
  register: cmd_path
  ignore_errors: true

- name: Hiển thị PATH trong môi trường shell của Ansible
  command: env
  register: env_output

- debug:
    var: env_output.stdout_lines

Kiểm tra kết quả đầu ra. PATH của Ansible thường là /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin — sáu mục. Phiên SSH tương tác của bạn có thể có 12 mục hoặc hơn. Thư mục bị thiếu thường lộ ra ngay lập tức.

Bước 2: Kiểm tra xem lệnh có được cài đặt không```

ansible web01 -m command -a "which some_command" ansible web01 -m command -a "ls /usr/local/bin/some_command"


Không có kết quả từ `which`? Lệnh chưa được cài đặt — bỏ qua đến Giải pháp 4. Có đường dẫn trả về? Lệnh đã được cài nhưng Ansible không thấy. Đó là vấn đề PATH.
### Bước 3: Xem chính xác PATH mà Ansible nhận được```
ansible web01 -m command -a "echo $PATH"

PATH thông thường của Ansible trông như sau:

/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin

Chạy lệnh echo $PATH tương tự trong phiên SSH tương tác của bạn. Sự chênh lệch giữa hai kết quả cho bạn biết chính xác những gì đang bị thiếu.

Các Giải pháp### Giải pháp 1: Dùng đường dẫn tuyệt đối đầy đủCách sửa nhanh nhất khi bạn biết binary nằm ở đâu:

- name: Chạy lệnh với đường dẫn đầy đủ
  command: /usr/local/bin/some_command --arg value

Không biết đường dẫn? Xác định động trước:

- name: Lấy đường dẫn đầy đủ
  command: which some_command
  register: cmd_path

- name: Dùng đường dẫn đã xác định
  command: "{{ cmd_path.stdout }} --arg value"

Giải pháp 2: Inject PATH cho taskTham số environment cho phép bạn mở rộng PATH cho từng task mà không ảnh hưởng gì khác trên host:

- name: Chạy với PATH tùy chỉnh
  command: some_command --arg value
  environment:
    PATH: "/opt/custom/bin:/usr/local/bin:/usr/bin:/bin:{{ ansible_env.PATH }}"

Cần áp dụng cho toàn bộ play? Đặt một lần ở cấp play:

- hosts: webservers
  environment:
    PATH: "/opt/custom/bin:/usr/local/bin:{{ ansible_env.PATH }}"
  tasks:
    - name: Task này giờ thấy được PATH mở rộng
      command: some_command

Giải pháp 3: Source shell profile trước khi chạyCác công cụ như nvm, pyenvrbenv cần được source script khởi tạo trước khi hoạt động. Chuyển từ module command sang shell và source profile một cách tường minh:

- name: Chạy sau khi source profile
  shell: "source ~/.bashrc && some_command --arg value"
  args:
    executable: /bin/bash

Để tải /etc/profile~/.bash_profile, gọi bash trực tiếp dưới dạng login shell:

- name: Chạy trong login shell
  shell: bash -l -c 'some_command --arg value'

Lưu ý quan trọng: Cách này chỉ hoạt động với module shell. Module command thực thi binary trực tiếp — không có shell, không có profile, không có mở rộng PATH từ .bashrc.

Giải pháp 4: Cài đặt lệnh còn thiếu trướcKhi lệnh thực sự chưa có trên host, thêm bước cài đặt trước task cần dùng nó:

- name: Đảm bảo công cụ cần thiết đã được cài
  package:
    name: some-package
    state: present
  become: true

- name: Giờ chạy lệnh
  command: some_command --arg value

Với các công cụ dựa trên pip:

- name: Cài đặt công cụ Python
  pip:
    name: some-tool
    state: present
    executable: pip3

- name: Dùng công cụ vừa cài
  command: some-tool --version

Giải pháp 5: Ghim đường dẫn chính xác cho version manager (nvm, pyenv, rbenv)Các version manager cài binary vào thư mục riêng của user như ~/.nvm/versions/node/v20.11.0/bin/. Hardcode đường dẫn version đầy đủ — đây là cách duy nhất hoạt động đáng tin cậy:

- name: Chạy node qua đường dẫn nvm cố định
  command: /home/deploy/.nvm/versions/node/v20.11.0/bin/node -e "console.log('ok')"
  become: true
  become_user: deploy

Lưu đường dẫn version vào biến playbook ở đầu file, không rải rác khắp các task. Khi bạn nâng cấp Node từ v20 lên v22, bạn chỉ cần thay đổi một dòng thay vì mười dòng.

Kiểm tra kết quảChạy với verbose output để xác nhận bản sửa đã ổn định:

ansible-playbook your_playbook.yml --tags your_task_tag -v

Kiểm tra rc: 0 và không có mục FAILED nào. Nếu bạn muốn kiểm tra rõ ràng trước khi chạy task thực, thêm một probe nhanh:

- name: Xác nhận PATH chính xác
  command: which some_command
  register: check

- debug:
    msg: "Tìm thấy lệnh tại: {{ check.stdout }}"

- name: Chạy lệnh thực sự
  command: "{{ check.stdout }} --arg value"

Biến thể với Sudo / becomeMột lỗi liên quan hay khiến nhiều người bất ngờ. Lệnh tồn tại với deploy user nhưng không có với root — hoặc ngược lại:

fatal: [host]: FAILED! => {
  'msg': '[Errno 2] No such file or directory: b\'some_command\'',
  'rc': 2
}

Với become: true, task chạy dưới quyền root. Root thường có PATH ngắn hơn và bị hạn chế hơn so với user thông thường. Truyền PATH tường minh cùng với become:

- name: Chạy với quyền root và PATH đầy đủ
  command: some_command
  become: true
  environment:
    PATH: "/usr/local/bin:/usr/bin:/bin:/sbin:/usr/sbin"

Những điểm cần nhớ- PATH của Ansible không phải PATH của bạn. Chạy ansible host -m command -a "echo $PATH" trước tiên bất cứ khi nào một lệnh thất bại bí ẩn.- Đường dẫn tuyệt đối là lựa chọn tốt nhất trong production. Rõ ràng, dễ chuyển đổi và không bị ảnh hưởng bởi các init script có thể chạy hoặc không trên remote host.- Dùng shell, không phải command, khi cần load profile. Module command bỏ qua shell hoàn toàn — không load profile, không mở rộng PATH.- Ghim đường dẫn version manager vào biến. Hardcode ~/.nvm/versions/node/v20.11.0/bin trong mọi task rất dễ gãy. Đặt vào biến một lần và tham chiếu ở mọi nơi.- Kiểm tra với đúng SSH user thực tế. Sự khác biệt giữa tài khoản dev local, deploy user và root giải thích phần lớn các lỗi kiểu này.

Related Error Notes