かべぎわブログ

技術的なことについてかけたらいいな…

AnsibleのshellモジュールでPATHがとおってないと怒られるときの対処法

概要

Ansibleのshellモジュールでターゲットノードでコマンドを実行しようとしたところ、「コマンドが見つかりません」というエラーが返ってきてしまいました。
のでそれの対処法です。

こんなかんじのplaybookがエラーになった。

- hosts: target
  tasks:
    - shell: ifconfig
$ ansible-playbook -i ./inventory_file ./shell_path.yml -v

PLAY [target] ******************************************************************************************************************************************

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

TASK [command] *****************************************************************************************************************************************
fatal: [192.140.1.62]: FAILED! => {"changed": true, "cmd": "ifconfig", "delta": "0:00:00.003005", "end": "2018-07-24 13:58:14.304449", "msg": "non-zero return code", "rc": 127, "start": "2018-07-24 13:58:14.301444", "stderr": "/bin/sh: ifconfig: コマンドが見つかりません", "stderr_lines": ["/bin/sh: ifconfig: コマンドが見つかりません"], "stdout": "", "stdout_lines": []}
    to retry, use: --limit @/home/ec2-user/shell_path.retry

PLAY RECAP *********************************************************************************************************************************************
192.140.1.62               : ok=1    changed=0    unreachable=0    failed=1   

原因究明

ifconfigコマンドを実行したところ「コマンドが見つかりません」というエラーになった。
PATHがとおっていなさそうなので調べてみる。
こんなかんじのplaybookを用意。

- hosts: target
  tasks:
    - shell: echo ${PATH}

実行してみる。

$ ansible-playbook -i ./inventory_file ./shell_path.yml -v

PLAY [target] ******************************************************************************************************************************************

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

TASK [command] *****************************************************************************************************************************************
changed: [192.140.1.62] => {"changed": true, "cmd": "echo ${PATH}", "delta": "0:00:00.002629", "end": "2018-07-24 13:59:18.802630", "rc": 0, "start": "2018-07-24 13:59:18.800001", "stderr": "", "stderr_lines": [], "stdout": "/usr/local/bin:/usr/bin", "stdout_lines": ["/usr/local/bin:/usr/bin"]}

PLAY RECAP *********************************************************************************************************************************************
192.140.1.62               : ok=2    changed=1    unreachable=0    failed=0   

PATHには/usr/local/bin:/usr/binしか設定されていないことがわかる。
ifconfigコマンドは/usr/sbin/ifconfigに格納されているのでエラーとなっていた。

$ which ifconfig
/usr/sbin/ifconfig

解決方法

shellモジュールに記載するコマンドを絶対PATHで書いてあげる。

- hosts: target
  tasks:
    - shell: /usr/sbin/ifconfig
$ ansible-playbook -i ./inventory_file ./shell_path.yml -v 

PLAY [target] ******************************************************************************************************************************************

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

TASK [command] *****************************************************************************************************************************************
changed: [192.140.1.62] => {"changed": true, "cmd": "/usr/sbin/ifconfig", "delta": "0:00:00.003328", "end": "2018-07-24 14:02:56.630454", "rc": 0, "start": "2018-07-24 14:02:56.627126", "stderr": "", "stderr_lines": [], "stdout": "eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 9001\n        inet 192.140.1.62  netmask 255.255.255.0  broadcast 192.140.1.255\n        inet6 fe80::49c:a8ff:fe3f:24ae  prefixlen 64  scopeid 0x20<link>\n        ether 06:9c:a8:3f:24:ae  txqueuelen 1000  (Ethernet)\n        RX packets 10822  bytes 5943861 (5.6 MiB)\n        RX errors 0  dropped 0  overruns 0  frame 0\n        TX packets 7016  bytes 1080402 (1.0 MiB)\n        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0\n\nlo: flags=73<UP,LOOPBACK,RUNNING>  mtu 65536\n        inet 127.0.0.1  netmask 255.0.0.0\n        inet6 ::1  prefixlen 128  scopeid 0x10<host>\n        loop  txqueuelen 1  (Local Loopback)\n        RX packets 1576  bytes 1885056 (1.7 MiB)\n        RX errors 0  dropped 0  overruns 0  frame 0\n        TX packets 1576  bytes 1885056 (1.7 MiB)\n        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0", "stdout_lines": ["eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 9001", "        inet 192.140.1.62  netmask 255.255.255.0  broadcast 192.140.1.255", "        inet6 fe80::49c:a8ff:fe3f:24ae  prefixlen 64  scopeid 0x20<link>", "        ether 06:9c:a8:3f:24:ae  txqueuelen 1000  (Ethernet)", "        RX packets 10822  bytes 5943861 (5.6 MiB)", "        RX errors 0  dropped 0  overruns 0  frame 0", "        TX packets 7016  bytes 1080402 (1.0 MiB)", "        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0", "", "lo: flags=73<UP,LOOPBACK,RUNNING>  mtu 65536", "        inet 127.0.0.1  netmask 255.0.0.0", "        inet6 ::1  prefixlen 128  scopeid 0x10<host>", "        loop  txqueuelen 1  (Local Loopback)", "        RX packets 1576  bytes 1885056 (1.7 MiB)", "        RX errors 0  dropped 0  overruns 0  frame 0", "        TX packets 1576  bytes 1885056 (1.7 MiB)", "        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0"]}

PLAY RECAP *********************************************************************************************************************************************
192.140.1.62               : ok=2    changed=1    unreachable=0    failed=0   

実行できた。

おわりに

もっとスマートな解決方法はないものか…

Ansible実践ガイド 第2版 (impress top gear)

Ansible実践ガイド 第2版 (impress top gear)