Ansible スクリプトモジュールで発生する「Permission denied」エラーの解決方法

AnsibleAnsibleBeginner
オンラインで実践に進む

💡 このチュートリアルは英語版からAIによって翻訳されています。原文を確認するには、 ここをクリックしてください

はじめに

Ansible は、インフラストラクチャ管理と設定を簡素化する強力な自動化ツールです。Ansible の script モジュールを使用すると、playbook 内でカスタムスクリプトを実行でき、Ansible の機能を組み込みモジュールを超えて拡張できます。しかし、ユーザーは、このモジュールを使用する際に「Permission denied(アクセス拒否)」エラーに遭遇することが多く、これが自動化ワークフローを妨げる可能性があります。

この実験(Lab)では、Ansible の script モジュールにおける権限関連の問題を理解し、解決するためのガイドを提供します。権限エラーの原因を特定し、Ansible スクリプトが正常に実行されるようにするためのさまざまな解決策を実装する方法を学びます。

Ansible のインストールと環境設定

Ansible スクリプトに関する権限の問題を調査する前に、環境をセットアップする必要があります。Ansible をインストールし、テスト環境の基本的な構造を作成しましょう。

Ansible のインストール

まず、パッケージインデックスを更新し、Ansible をインストールします。

sudo apt update
sudo apt install -y ansible

インストールが完了したら、Ansible が正しくインストールされていることを確認します。

ansible --version

Ansible のバージョンと設定の詳細を示す、次のような出力が表示されるはずです。

ansible [core 2.12.x]
  config file = /etc/ansible/ansible.cfg
  configured module search path = ['/home/labex/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
  ansible python module location = /usr/lib/python3/dist-packages/ansible
  ansible collection location = /home/labex/.ansible/collections:/usr/share/ansible/collections
  executable location = /usr/bin/ansible
  python version = 3.10.x (default, Mar 01 2023, 12:34:56) [GCC 11.2.0]
  jinja version = 3.0.3
  libyaml = True

プロジェクト構造の設定

次に、Ansible playbook とスクリプト用のプロジェクトディレクトリ構造を作成しましょう。

mkdir -p ~/project/ansible-lab/{playbooks,scripts}
cd ~/project/ansible-lab

この構造では、

  • playbooks/ に Ansible playbook が含まれます。
  • scripts/ に Ansible によって実行されるシェルスクリプトが含まれます。

簡単なスクリプトの作成

Ansible で使用する簡単なシェルスクリプトを作成しましょう。scripts ディレクトリに hello.sh という名前のファイルを作成します。

cd ~/project/ansible-lab/scripts
touch hello.sh

エディタで hello.sh ファイルを開き、次の内容を追加します。

#!/bin/bash
echo "Hello from $(hostname)!"
echo "Current time: $(date)"
echo "Current user: $(whoami)"

このスクリプトは、ホスト名、現在の時刻、およびスクリプトを実行したユーザーを出力します。

インベントリファイルの作成

次に、Ansible 用の簡単なインベントリファイルを作成しましょう。Ansible では、インベントリファイルは、Ansible が管理するホストとグループを定義します。

cd ~/project/ansible-lab
touch inventory.ini

inventory.ini ファイルを開き、以下を追加します。

[local]
localhost ansible_connection=local

このインベントリファイルは、Ansible にローカルマシンでコマンドを実行するように指示します。

基本的な Playbook の作成

次に、script モジュールを使用する基本的な Ansible playbook を作成しましょう。

cd ~/project/ansible-lab/playbooks
touch run_script.yml

run_script.yml ファイルを開き、次の内容を追加します。

---
- name: Run a script
  hosts: local
  tasks:
    - name: Execute the hello script
      script: ../scripts/hello.sh

この playbook は、ローカルマシンで hello.sh スクリプトを実行しようとします。

この基本的な設定により、次のステップで Ansible スクリプトに関する権限の問題を調査する準備ができました。

Permission denied(アクセス拒否)エラーの発生

環境をセットアップしたので、Ansible playbook を実行し、permission denied(アクセス拒否)エラーが発生した場合に何が起こるかを理解しましょう。

Playbook の実行

Playbook を実行してみましょう。

cd ~/project/ansible-lab
ansible-playbook -i inventory.ini playbooks/run_script.yml

次のようなエラーメッセージが表示される可能性があります。

TASK [Execute the hello script] *******************************
fatal: [localhost]: FAILED! => {"changed": false, "msg": "failed to execute the script: /bin/sh: 1: /home/labex/.ansible/tmp/ansible-tmp-1234567890.12-123456789012345/AnsiballZ_script.py: Permission denied"}

これは、Ansible script モジュールを使用する際に発生する一般的な permission denied(アクセス拒否)エラーです。このエラーは、スクリプトに実行権限がないために発生します。スクリプトを実行するには、実行権限が必要です。

Linux におけるファイル権限の理解

Linux では、すべてのファイルに、誰が読み取り、書き込み、または実行できるかを決定する権限があります。権限には次の 3 つのタイプがあります。

  1. Read (r): ファイルの内容を読み取ることができます。
  2. Write (w): ファイルを変更できます。
  3. Execute (x): ファイルをプログラムとして実行できます。

これらの権限は、次の 3 つの異なるユーザーカテゴリに割り当てられます。

  1. User (owner): ファイルの所有者
  2. Group: ファイルのグループのメンバーであるユーザー
  3. Others: その他のすべてのユーザー

ls -l コマンドを使用して、ファイルの権限を表示できます。

ls -l ~/project/ansible-lab/scripts/hello.sh

次のような出力が表示される場合があります。

-rw-rw-r-- 1 labex labex 95 Jun 10 12:34 /home/labex/project/ansible-lab/scripts/hello.sh

この出力では、最初の文字のセット(-rw-rw-r--)がファイルの権限を表しています。

  • 最初の文字(-)は、これが通常のファイルであることを示します。
  • 次の 3 文字(rw-)は、所有者の権限(読み取り、書き込み、実行なし)です。
  • 次の 3 文字(rw-)は、グループの権限です。
  • 最後の 3 文字(r--)は、その他のユーザーの権限です。

すべてのユーザーカテゴリで実行権限(x)がないことに注意してください。これが、permission denied(アクセス拒否)エラーが発生する理由です。

現在の権限の確認

スクリプトの現在の権限を調べてみましょう。

ls -l ~/project/ansible-lab/scripts/hello.sh

Ansible が実行するために必要な実行権限がスクリプトにないことがわかります。

次のステップでは、この権限の問題を修正し、Ansible playbook を正常に実行する方法を学びます。

chmod を使用した権限の問題の修正

"Permission denied(アクセス拒否)" エラーを修正する最も一般的な方法は、スクリプトファイルに実行権限を追加することです。これは、chmod コマンドを使用して行うことができます。

chmod コマンドの理解

chmod コマンドは、Linux でファイルまたはディレクトリの権限を変更するために使用されます。このコマンドには、権限を指定するためのいくつかの方法があります。

  1. Symbolic mode(記号モード): 文字(r、w、x)を使用して権限を表します。
  2. Numeric mode(数値モード): 数字(4、2、1)を使用して権限を表します。

ここでは、実行権限を追加するために、記号モードを使用します。

スクリプトへの実行権限の追加

スクリプトに実行権限を追加しましょう。

chmod +x ~/project/ansible-lab/scripts/hello.sh

+x オプションは、すべてのユーザーカテゴリ(ユーザー、グループ、その他)に実行権限を追加します。

権限が更新されたことを確認しましょう。

ls -l ~/project/ansible-lab/scripts/hello.sh

次のような出力が表示されるはずです。

-rwxrwxr-x 1 labex labex 95 Jun 10 12:34 /home/labex/project/ansible-lab/scripts/hello.sh

権限文字列の x に注目してください。これは、実行権限が追加されたことを示しています。

Playbook の再実行

スクリプトに実行権限を追加したので、Ansible playbook をもう一度実行してみましょう。

cd ~/project/ansible-lab
ansible-playbook -i inventory.ini playbooks/run_script.yml

今回は、playbook が正常に実行されるはずです。

PLAY [Run a script] ******************************************

TASK [Gathering Facts] ***************************************
ok: [localhost]

TASK [Execute the hello script] *****************************
changed: [localhost]

PLAY RECAP *************************************************
localhost                  : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

スクリプト出力の表示

スクリプトの出力を確認しましょう。Ansible はスクリプトの出力をキャプチャし、タスクの結果に含めます。詳細な出力を確認するために、playbook を変更して出力を登録し、表示してみましょう。

cd ~/project/ansible-lab/playbooks

run_script.yml ファイルを編集して、register(登録)タスクと debug(デバッグ)タスクを含めます。

---
- name: Run a script
  hosts: local
  tasks:
    - name: Execute the hello script
      script: ../scripts/hello.sh
      register: script_output

    - name: Display script output
      debug:
        var: script_output.stdout_lines

次に、playbook をもう一度実行しましょう。

cd ~/project/ansible-lab
ansible-playbook -i inventory.ini playbooks/run_script.yml

次のような出力が表示されるはずです。

PLAY [Run a script] ******************************************

TASK [Gathering Facts] ***************************************
ok: [localhost]

TASK [Execute the hello script] *****************************
changed: [localhost]

TASK [Display script output] ********************************
ok: [localhost] => {
    "script_output.stdout_lines": [
        "Hello from localhost!",
        "Current time: Wed Jun 10 12:34:56 UTC 2023",
        "Current user: labex"
    ]
}

PLAY RECAP *************************************************
localhost                  : ok=3    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

これで、スクリプトの完全な出力を確認できます。スクリプトは、現在のユーザーである labex ユーザーとして実行されました。

chmod +x で実行権限を追加することにより、"Permission denied(アクセス拒否)" エラーを正常に修正し、Ansible を介してスクリプトを実行できるようになりました。

特権昇格のための Become の使用

root アクセスを必要とするコマンドの実行など、特権を昇格させてスクリプトを実行する必要がある場合があります。このような場合、スクリプトに実行権限を追加するだけでは不十分な場合があります。Ansible は、特権昇格でタスクを実行するための become ディレクティブを提供しています。

Become ディレクティブの理解

Ansible の become ディレクティブを使用すると、別のユーザーとして、通常は特権を昇格させてタスクを実行できます。これは、コマンドラインで sudo を使用することに似ています。

become ディレクティブの主なオプションは次のとおりです。

  • become: yes: 特権昇格を有効にします。
  • become_user: <username>: どのユーザーになるかを指定します(デフォルトは root)。
  • become_method: <method>: ユーザーになる方法を指定します(デフォルトは sudo)。

Root 特権を必要とするスクリプトの作成

正常に実行するために root 特権を必要とするスクリプトを作成しましょう。

cd ~/project/ansible-lab/scripts
touch system_info.sh

system_info.sh ファイルに次の内容を追加します。

#!/bin/bash
echo "System information - requires root privileges"
echo "Hostname: $(hostname)"
echo "Kernel version: $(uname -r)"
echo "Available disk space:"
df -h /
echo "User executing the script: $(whoami)"

スクリプトを実行可能にします。

chmod +x ~/project/ansible-lab/scripts/system_info.sh

Become を使用した Playbook の作成

次に、become ディレクティブを使用する playbook を作成しましょう。

cd ~/project/ansible-lab/playbooks
touch root_script.yml

root_script.yml ファイルに次の内容を追加します。

---
- name: Run a script as root
  hosts: local
  tasks:
    - name: Execute the system info script
      script: ../scripts/system_info.sh
      become: yes
      register: script_output

    - name: Display script output
      debug:
        var: script_output.stdout_lines

become: yes ディレクティブは、Ansible に特権を昇格させてスクリプトを実行するように指示します。

Become を使用した Playbook の実行

新しい playbook を実行しましょう。

cd ~/project/ansible-lab
ansible-playbook -i inventory.ini playbooks/root_script.yml

playbook は正常に実行され、次のような出力が表示されるはずです。

PLAY [Run a script as root] *********************************

TASK [Gathering Facts] **************************************
ok: [localhost]

TASK [Execute the system info script] **********************
changed: [localhost]

TASK [Display script output] *******************************
ok: [localhost] => {
    "script_output.stdout_lines": [
        "System information - requires root privileges",
        "Hostname: localhost",
        "Kernel version: 5.15.0-1015-aws",
        "Available disk space:",
        "Filesystem      Size  Used Avail Use% Mounted on",
        "/dev/root        59G   17G   42G  29% /",
        "User executing the script: root"
    ]
}

PLAY RECAP ************************************************
localhost                  : ok=3    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

スクリプトの出力では、「User executing the script」が labex ではなく、root になっていることに注目してください。これは、become: yes ディレクティブにより、スクリプトが特権を昇格させて実行されたことを示しています。

Become を使用するタイミングの理解

次のような状況で、become ディレクティブを使用する必要があります。

  1. スクリプトが root 特権を必要とするシステムファイルまたはディレクトリにアクセスする必要がある場合。
  2. スクリプトがパッケージをインストールしたり、システム設定を変更したりする必要がある場合。
  3. スクリプトが、通常はコマンドラインで sudo が必要なコマンドを実行する必要がある場合。

become ディレクティブを適切に使用することで、スクリプトが正常に実行するために必要な権限を持っていることを確認し、permission denied(アクセス拒否)エラーを回避できます。

権限の問題を回避するためのベストプラクティス

chmodbecome を使用して権限の問題を修正する方法を理解したので、まず権限の問題が発生しないようにするためのベストプラクティスをいくつか見ていきましょう。

1. スクリプトを使用する前に必ず実行可能にする

Ansible でスクリプトを使用する前に、常に実行権限があることを確認してください。

chmod +x path/to/script.sh

これは、スクリプト作成プロセスの一環として行うのが良い習慣です。

2. 適切なファイルモードでバージョン管理を使用する

Git などのバージョン管理システムを使用している場合は、ファイルモード(権限)が保持されていることを確認してください。Git では、次のように設定できます。

git config core.fileMode true

既存のリポジトリの場合は、ファイルモードを更新する必要がある場合があります。

git update-index --chmod=+x path/to/script.sh

3. 権限を確認して修正するスクリプトを作成する

プロジェクト内のすべてのスクリプトの権限を確認して修正するユーティリティスクリプトを作成しましょう。

cd ~/project/ansible-lab
touch fix_permissions.sh

fix_permissions.sh ファイルに次の内容を追加します。

#!/bin/bash
echo "Fixing permissions for scripts in ansible-lab"

## Find all .sh files and make them executable
find ~/project/ansible-lab -name "*.sh" -type f -exec chmod +x {} \;

echo "Done. All script files now have execute permissions."

スクリプトを実行可能にします。

chmod +x ~/project/ansible-lab/fix_permissions.sh

プロジェクト内のすべてのスクリプトに実行権限があることを確認するために、スクリプトを実行します。

./fix_permissions.sh

4. Ansible の File モジュールを使用して権限を設定する

Ansible の file モジュールを使用して、スクリプトファイルに正しい権限があることを確認することもできます。これを行う playbook を作成しましょう。

cd ~/project/ansible-lab/playbooks
touch set_permissions.yml

set_permissions.yml ファイルに次の内容を追加します。

---
- name: Set correct permissions for scripts
  hosts: local
  tasks:
    - name: Find all script files
      find:
        paths: /home/labex/project/ansible-lab
        patterns: "*.sh"
        recurse: yes
      register: script_files

    - name: Make script files executable
      file:
        path: "{{ item.path }}"
        mode: "0755"
      loop: "{{ script_files.files }}"

この playbook を実行して、すべてのスクリプトに正しい権限があることを確認します。

cd ~/project/ansible-lab
ansible-playbook -i inventory.ini playbooks/set_permissions.yml

5. 事前チェック Playbook を作成する

最後に、メインの playbook を実行する前に、すべてが正しく設定されていることを確認する事前チェック playbook を作成しましょう。

cd ~/project/ansible-lab/playbooks
touch preflight_check.yml

preflight_check.yml ファイルに次の内容を追加します。

---
- name: Pre-flight checks
  hosts: local
  tasks:
    - name: Check if scripts are executable
      find:
        paths: /home/labex/project/ansible-lab
        patterns: "*.sh"
        recurse: yes
      register: script_files

    - name: Verify script permissions
      stat:
        path: "{{ item.path }}"
      register: stat_results
      loop: "{{ script_files.files }}"
      failed_when: not stat_results.stat.executable
      ignore_errors: yes

この playbook は、すべての .sh ファイルが実行可能かどうかを確認し、実行可能でないものを報告します。

事前チェックを実行しましょう。

cd ~/project/ansible-lab
ansible-playbook -i inventory.ini playbooks/preflight_check.yml

すべてのスクリプトに正しい権限がある場合、playbook はエラーなしで完了します。実行権限が不足しているスクリプトがある場合は、通知が表示されます。

これらのベストプラクティスに従うことで、Ansible スクリプトで permission denied(アクセス拒否)エラーを回避し、自動化がスムーズに実行されるようにすることができます。

まとめ

この実験(Lab)では、Ansible のスクリプトモジュールを使用する際に、「Permission denied(アクセス拒否)」エラーを特定し、解決する方法を学びました。

この実験(Lab)からの主なポイントは次のとおりです。

  1. Linux におけるファイル権限の重要性と、それが Ansible でのスクリプト実行にどのように影響するかを理解する。
  2. chmod コマンドを使用して、スクリプトファイルに実行権限を追加する。
  3. root アクセスを必要とするスクリプトを実行する際に、特権昇格のために Ansible の become ディレクティブを利用する。
  4. 権限の問題を防止するためのベストプラクティスの実装。これには以下が含まれます。
    • スクリプトを使用する前に実行可能にする。
    • バージョン管理で適切なファイルモードを維持する。
    • 権限を確認して修正するユーティリティスクリプトを作成する。
    • Ansible の file モジュールを使用して権限を設定する。
    • 環境を確認するための事前チェックを実装する。

これらのテクニックを適用することで、Ansible スクリプトが権限エラーなしでスムーズに実行されるようにし、自動化ワークフローの信頼性を高めることができます。

この実験(Lab)で学んだスキルは、Ansible を効果的に使用するための基本であり、幅広い自動化シナリオに適用できます。