Cách khắc phục lỗi Ansible 'chdir failed: No such file or directory'

beginner🔧 Ansible2026-06-28| Ansible 2.9+, Linux (Ubuntu, CentOS, RHEL), macOS, Mục tiêu từ xa qua SSH

Error Message

fatal: [host]: FAILED! => {"changed": false, "cmd": "make install", "msg": "chdir /opt/app/build failed: [Errno 2] No such file or directory: '/opt/app/build'"}
#ansible#devops#khắc phục sự cố#linux#tự động hóa

Cơn ác mộng triển khai lúc 2 giờ sáng

Tất cả chúng ta đều đã từng trải qua tình huống này. Bạn đang đẩy một bản cập nhật định kỳ, mong đợi một thông báo thành công nhanh chóng, nhưng thay vào đó, terminal của bạn lại hiện ra một loạt chữ đỏ. Bạn đang cố gắng chạy một lệnh make install đơn giản hoặc một script, nhưng Ansible không thể tìm thấy thư mục mà nó cần làm việc. Đó là một trở ngại gây ức chế, đặc biệt là khi bạn chắc chắn rằng thư mục đó phải ở đó.

Lỗi thường trông như thế này:

fatal: [host]: FAILED! => {"changed": false, "cmd": "make install", "msg": "chdir /opt/app/build failed: [Errno 2] No such file or directory: '/opt/app/build'"}

Khi điều này xảy ra, Ansible đang báo cho bạn biết rằng tham số chdir trong module shell hoặc command của bạn trỏ đến một đường dẫn không tồn tại trên remote host. Đây không phải là lỗi trong thiết lập cục bộ của bạn. Đó là một trạng thái bị thiếu trên server đích—có lẽ một thư mục đã không được tạo, hoặc một bước trước đó đã thất bại mà không dừng playbook lại.

Tại sao thư mục lại bị thiếu?

Trước khi bạn bắt đầu can thiệp vào mã nguồn, bạn cần biết tại sao đường dẫn đó biến mất. Trong 90% trường hợp, nó rơi vào một trong ba nguyên nhân sau:

  • Thất bại trong âm thầm: Một tác vụ git clone hoặc unarchive trước đó đã thất bại (có lẽ do lỗi 403 Forbidden hoặc vấn đề dung lượng đĩa) và không tạo ra thư mục.
  • Nhầm lẫn đường dẫn: Bạn đã sử dụng một đường dẫn tương đối như chdir: build, và Ansible đã cố gắng tìm nó so với thư mục home của người dùng SSH (ví dụ: /home/ubuntu/build) thay vì đường dẫn hệ thống dự kiến.
  • Biến trống: Bạn đang sử dụng một biến như chdir: "{{ app_path }}", nhưng biến đó chưa được định nghĩa hoặc vô tình bị đặt thành một chuỗi rỗng.

Debug nhanh: Kiểm tra trạng thái Remote

Đừng đoán mò. Hãy chạy một lệnh ad-hoc nhanh để xem server đang thấy gì:

ansible all -m shell -a "ls -ld /opt/app/build" -i inventory.ini

Nếu server trả về ls: cannot access..., thư mục đó thực sự bị thiếu. Nếu nó trả về chi tiết thư mục, có khả năng bạn đang gặp vấn đề về quyền truy cập hoặc lỗi đánh máy trong biến của playbook.

Các giải pháp

1. Ép buộc thư mục phải tồn tại

Cách khắc phục đáng tin cậy nhất là sử dụng module file ngay trước lệnh của bạn. Điều này đảm bảo thư mục tồn tại bất kể điều gì đã xảy ra trong các bước trước đó. Đây là một nguyên tắc cốt lõi của infrastructure as code: đừng giả định, hãy thực thi.

- name: Đảm bảo thư mục build đã sẵn sàng
  ansible.builtin.file:
    path: /opt/app/build
    state: directory
    mode: '0755'

- name: Chạy quá trình cài đặt
  ansible.builtin.command: make install
  args:
    chdir: /opt/app/build

2. Chuyển sang đường dẫn tuyệt đối

Đường dẫn tương đối là nguồn cơn chính của các lỗi 'No such file'. Nếu playbook của bạn chạy với quyền root, chdir: project sẽ tìm trong /root/project. Nếu chạy với quyền ec2-user, nó sẽ tìm trong /home/ec2-user/project. Luôn sử dụng đường dẫn đầy đủ, như /var/www/my-app/build, để giữ cho playbook của bạn luôn ổn định và dễ đoán.

3. Sử dụng đối số 'Creates' để đảm bảo an toàn

Bạn có thể làm cho các tác vụ của mình thông minh hơn bằng cách sử dụng creates. Điều này nói với Ansible: "Chỉ chạy lệnh này nếu file cụ thể này còn thiếu." Đây là một cách tuyệt vời để ngăn ngừa lỗi và làm cho playbook của bạn có tính idempotent.

- name: Biên dịch ứng dụng
  ansible.builtin.shell: ./configure && make
  args:
    chdir: /opt/app/src
    creates: /opt/app/src/Makefile

4. Xử lý triển khai động

Nếu đường dẫn của bạn thay đổi dựa trên dấu thời gian hoặc mã hash của Git, hãy đảm bảo các biến của bạn được đăng ký chính xác. Ví dụ, nếu bạn đang triển khai vào một thư mục được đặt tên theo ngày hiện tại:

- name: Định nghĩa đường dẫn release
  set_fact:
    rel_path: "/opt/releases/{{ ansible_date_time.date }}"

- name: Tạo thư mục release
  ansible.builtin.file:
    path: "{{ rel_path }}"
    state: directory

- name: Khởi tạo ứng dụng
  ansible.builtin.shell: python3 manage.py migrate
  args:
    chdir: "{{ rel_path }}"

Xác minh việc khắc phục

Sau khi cập nhật playbook, hãy chạy nó với cờ -v (verbose). Hãy tìm đầu ra của module file. Nếu nó báo "changed": true, điều đó có nghĩa là thư mục thực sự đã bị thiếu và Ansible đã sửa nó cho bạn. Bạn cũng có thể chạy lệnh stat /opt/app/build trên remote server để kiểm tra thời gian tạo và quyền sở hữu (ví dụ: drwxr-xr-x).

Những lưu ý quan trọng

  • Hãy rõ ràng: Đừng bao giờ tin rằng một tác vụ trước đó đã tạo ra thư mục. Hãy sử dụng module file để chắc chắn.
  • Kiểm tra quyền hạn: Nếu thư mục tồn tại nhưng bạn vẫn gặp lỗi, become_user có thể không có quyền +x để truy cập vào thư mục cha.
  • Tránh sử dụng dấu ngã (~): Không sử dụng ~/build. Hãy sử dụng /home/username/build để tránh sự mơ hồ giữa các người dùng SSH khác nhau.

Related Error Notes