Ansibleの「chdir failed: No such file or directory」エラーを解決する方法

beginner🔧 Ansible2026-06-28| Ansible 2.9+, Linux (Ubuntu, CentOS, RHEL), macOS, 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#トラブルシューティング#linux#自動化

深夜2時のデプロイの悩み

誰しも経験があるでしょう。ルーチンのアップデートをプッシュし、すぐに成功メッセージが表示されるのを期待していたのに、代わりにターミナルに赤いテキストの壁が吐き出される。単純な make install やスクリプトを実行しようとしたのに、Ansible が作業すべきディレクトリを見つけられませんでした。フォルダがそこにあるはずだと確信しているとき、これは非常に苛立たしい障害となります。

エラーは通常、以下のようになります。 slums:

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 は shell または command モジュールの chdir パラメータが、リモートホスト上に存在しないパスを指していることを伝えています。これはローカルのセットアップのバグではありません。ターゲットサーバー上の状態が欠落しているのです。おそらく、フォルダが作成されていなかったか、前のステップが Playbook を停止させずに失敗した可能性があります。

なぜディレクトリが欠落しているのか?

コードをいじり始める前に、なぜパスが消えたのかを知る必要があります。90% のケースでは、次の 3 つのいずれかが原因です。

  • サイレントな失敗: 以前の git cloneunarchive タスクが失敗(403 Forbidden やディスク容量の問題など)し、フォルダが作成されなかった。
  • パスの混同: chdir: build のような相対パスを使用しており、Ansible が意図したシステムパスではなく、SSH ユーザーのホームディレクトリ(例:/home/ubuntu/build)からの相対パスで見つけようとした。
  • 空の変数: chdir: "{{ app_path }}" のような変数を使用しているが、その変数が未定義であるか、誤って空の文字列に設定されている。

クイックデバッグ:リモートの状態を確認する

推測しないでください。サーバーがどのように認識しているか、アドホックコマンドを実行して確認しましょう。

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

もしサーバーが ls: cannot access... と返してきた場合、フォルダは物理的に存在しません。ディレクトリの詳細が返される場合は、権限の問題か、Playbook 変数のタイポ(打ち間違い)の可能性があります。

解決策

1. ディレクトリを強制的に作成する

最も確実な修正方法は、コマンドの直前で file モジュールを使用することです。これにより、前のステップで何が起こったかに関係なく、ディレクトリが確実に存在するようにします。これは Infrastructure as Code(IaC)の基本原則です。「想定するのではなく、強制する」ことです。

- name: Ensure the build directory is ready
  ansible.builtin.file:
    path: /opt/app/build
    state: directory
    mode: '0755'

- name: Run the installation
  ansible.builtin.command: make install
  args:
    chdir: /opt/app/build

2. 絶対パスに切り替える

相対パスは、「No such file」エラーの主な原因です。Playbook が root として実行される場合、chdir: project/root/project を探します。ec2-user として実行される場合は、/home/ec2-user/project を探します。Playbook の予測可能性を維持するために、常に /var/www/my-app/build のようなフルパスを使用してください。

3. 安全のために 'creates' 引数を使用する

creates を使用して、タスクをよりスマートにすることができます。これは Ansible に「この特定のファイルが存在しない場合にのみ、このコマンドを実行する」よう伝えます。これはエラーを防ぎ、Playbook のべき等性(idempotency)を確保するための優れた方法です。

- name: Compile the application
  ansible.builtin.shell: ./configure && make
  args:
    chdir: /opt/app/src
    creates: /opt/app/src/Makefile

4. 動的なデプロイの処理

タイムスタンプや Git のハッシュに基づいてパスが変わる場合は、変数が正しく登録されていることを確認してください。例えば、今日の日付にちなんだ名前のフォルダにデプロイする場合:

- name: Define the release path
  set_fact:
    rel_path: "/opt/releases/{{ ansible_date_time.date }}"

- name: Create the release folder
  ansible.builtin.file:
    path: "{{ rel_path }}"
    state: directory

- name: Initialize the app
  ansible.builtin.shell: python3 manage.py migrate
  args:
    chdir: "{{ rel_path }}"

修正の確認

Playbook を更新した後、-v(verbose)フラグを付けて実行します。file モジュールの出力を確認してください。もし "changed": true と表示されれば、ディレクトリが実際に欠落しており、Ansible がそれを修正したことを意味します。また、リモートサーバーで stat /opt/app/build を実行して、作成時間や所有者の権限(例:drwxr-xr-x)を確認することもできます。

重要なポイント

  • 明示的であること: 前のタスクがフォルダを作成したと決して信じないでください。file モジュールを使用して確実性を期しましょう。
  • 権限を確認する: フォルダが存在するのにエラーが出る場合は、become_user が親ディレクトリに移動するための +x 権限を持っていない可能性があります。
  • チルダ(~)を避ける: ~/build は使用しないでください。異なる SSH ユーザー間での曖昧さを避けるため、/home/username/build を使用してください。

Related Error Notes