問題の概要これは DevOps における典型的な悩みの一つです。SSH でサーバーにログインして pip3 --version を実行すると完璧に動作するのに、Ansible のプレイブックを実行した瞬間に「Failed to find required executable」エラーでクラッシュしてしまいます。これは、Ansible が通常「非対話型シェル(non-interactive shell)」経由で接続するためです。この環境では、.bashrc や .zshrc ファイルで定義されたカスタム $PATH 設定が無視されることがよくあります。
エラーは通常、次のように表示されます。
Failed to find required executable 'pip3' in paths: /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
Ansible は非常に限定されたシステムディレクトリのセットを検索しています。もしバイナリが /opt/python3.11/bin/pip3 や /home/ubuntu/.local/bin/pip3 に格納されている場合、適切な設定を行わない限り、Ansible はそれを見つけることができません。
バイナリの場所を特定するバイナリがどこにあるか推測するのではなく、アドホックコマンドを使用して、管理対象のすべてのノードにおける正確な絶対パスを確認しましょう。
ansible all -m command -a "which pip3" -i inventory.ini
もし上記でエラーが返される場合は、リモートマシンにログインして手動で検索してください。
whereis pip3
# または find を使用して詳細に検索
find /usr /opt -name pip3 2>/dev/null
パス(例:/usr/local/bin/pip3)が判明したら、以下の解決策のいずれかを実施します。
解決策 1: Python インタープリターを定義する(ベストプラクティス)pip3 に関する問題の多くは、Ansible が誤った Python バージョンを使用していることに起因します。ansible_python_interpreter を明示的に設定することで、Ansible に対し、その Python インストールに紐付いたモジュールやバイナリを検索するように指示できます。これは長期的なメンテナンスにおいて最もクリーンな修正方法です。
インベントリファイルに以下の行を追加します。
[webservers]
10.0.0.5 ansible_python_interpreter=/usr/bin/python3
10.0.0.6 ansible_python_interpreter=/opt/python3.10/bin/python3
あるいは、group_vars/all.yml でグローバルに適用することも可能です。
---
ansible_python_interpreter: /usr/local/bin/python3.9
解決策 2: 'executable' パラメータを使用する失敗しているタスクが1つか2つの場合、グローバルな変更は必要ありません。pip や npm を含む多くのモジュールでは、バイナリを直接指定することができます。この方法では $PATH のルックアップを完全にバイパスします。
- name: 特定の pip バイナリを使用して Flask をインストールする
ansible.builtin.pip:
name: flask
version: "2.2.5"
executable: /usr/local/bin/pip3
解決策 3: 環境変数を介して PATH を注入するexecutable パラメータが用意されていないカスタムシェルスクリプトやモジュールを実行している場合は、environment キーワードを使用して、そのタスク限定で一時的に $PATH を拡張します。
- name: カスタムパスを使用してビルドスクリプトを実行する
ansible.builtin.shell: build_assets.sh
environment:
PATH: "/opt/node-v18/bin:{{ ansible_env.PATH }}"
これにより、既存のパスの先頭にカスタムディレクトリが追加され、スクリプトが依存関係を最初に見つけられるようになります。
解決策 4: シンボリックリンクを作成する(クイックフィックス)急いでいてプレイブックのコードを変更できない場合は、シンボリックリンクを作成する方法があります。これにより、/usr/bin など、Ansible が既に検索対象としているディレクトリ内にバイナリへのリンクを配置します。
sudo ln -s /usr/local/custom/bin/pip3 /usr/bin/pip3
ただし、この方法は控えめに使用してください。リモートホストに対するこのような手動変更は、インフラの再現性を低下させ、「Infrastructure as Code(コードによるインフラ構成)」の原則に反することになります。
結果のテスト修正を確認するために、プレイブックを再実行してください。実行中に Ansible がどの $PATH を使用しているか正確に知りたい場合は、setup モジュールを実行します。
ansible webservers -m setup -a "filter=ansible_env"
JSON 出力の PATH の値を確認してください。ansible_python_interpreter による修正を行った場合は、簡単なデバッグタスクでインストールが成功するか検証します。
- name: pip が動作しているか確認する
ansible.builtin.pip:
name: pyyaml
state: present
register: pip_check
- name: ステータスを表示する
debug:
msg: "Pip が {{ pip_check.path }} に pyyaml を正常にインストールしました"
重要なポイント
- シェルの挙動の違い: Ansible の SSH 接続は、手動ログイン時と同じようにはユーザープロファイルをロードしません。
- 明示的に指定する:
ansible_python_interpreterを設定することで、特に Python 2 と Python 3 が混在するシステムでのバージョン不一致エラーを防げます。 - モジュール固有の設定: 複雑な環境ハックを試みる前に、Ansible モジュールのドキュメントに
executableやbin_pathオプションがないか必ず確認してください。

