リモートサーバーにsshしてenv
を実行すると、次のPATHが返されます。
PATH=/usr/lib64/qt-3.3/bin:/usr/local/bin:/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/sbin:/home/myusername/bin
対照的に、ansibleコマンドansible -a "env"
を実行すると、次のPATHが取得されます。
PATH=/usr/lib64/qt-3.3/bin:/usr/local/bin:/bin:/usr/bin
想像できるように、sbin
、service
などのntpdate
コマンドを実行しようとすると、sbinコマンドへの完全なパスを入力する必要があるため、これにより問題が発生します。 (はい、これを実行できるansibleモジュールがあることを知っていますが、PATHが短縮/切り捨てられている理由を解決しようとしています。)
なぜこれが起こっているのか誰でも知っていますか?
編集:これについて私が尋ねている理由は、私が本Ansible for DevOps
の例に従っているため、この理由のために一部の例が機能しないためです。
私が仕事に取り掛かろうとしている例は、本の28ページからです:
$ ansible multi -s -a "service ntpd stop"
$ ansible multi -s -a "ntpdate -q 0.rhel.pool.ntp.org"
$ ansible multi -s -a "service ntpd start"
これらのコマンドは常にエラーを発生させます。しかし、フルパスを含めるように変更すると、機能します。
$ ansible multi -s -a "/sbin/service ntpd stop"
$ ansible multi -s -a "/usr/sbin/ntpdate -q 0.rhel.pool.ntp.org"
$ ansible multi -s -a "/sbin/service ntpd start"
当然のことながら、発行するアドホックコマンドごとに完全なパスを入力する必要はありません。 (私はすべてのコマンドのパスを知りません。)
シェルに含まれている通常のパスをansibleに含めて取得する方法はありますか?これを可能にするインベントリファイルまたはansible.cfgファイルに追加できるパス変数はありますか?
私がansibleを使用したときはいつでも、別のシェルの下で別のユーザーとして実行されました。次のようにして、ユーザーを確認できます。
ansible -a "id"
次に、以下で定義されたユーザーシェルを確認できます:cat /etc/passwd
パスに追加するベストプラクティスは、次の行を追加することです:/home/<username>/.profile
or~/.bash_profile
ansible -a
は コマンドモジュール を使用しており、コマンドの実行にシェルを使用していません。
http://docs.ansible.com/ansible/intro_adhoc.html
通常、コマンドもモジュール名に-mを使用しますが、デフォルトのモジュール名は「コマンド」です。
/usr/sbin
などのパスのコンポーネントは、シェルが/etc/profile
ファイルをソーシングすることによってパスに追加され、コマンドモジュールは login Shellを作成しないため、そのファイルを読みません。
http://linux.die.net/man/1/bash
bashが対話型ログインシェルとして、または--loginオプションを使用して非対話型シェルとして呼び出されると、ファイル/ etc/profileが存在する場合、そのファイルからコマンドを最初に読み取り、実行します。そのファイルを読み取った後、〜/ .bash_profile、〜/ .bash_login、および〜/ .profileをこの順序で検索し、存在していて読み取り可能な最初のコマンドからコマンドを読み取って実行します。シェルの起動時に--noprofileオプションを使用して、この動作を禁止できます。
Ansibleのドキュメントでは、シェルが必要な場合は Shell モジュールを使用するとしています。ただし、シェルモジュールから(--loginオプションを渡すことによって)ログインシェルを開始するオプションがあるとは思われません。
実際、さまざまな場所で、ansibleポリシーは環境を信頼せず、タスクの定義時にVARSを明示的に設定することが言及されています。
ただし、アドホックモードでansibleを使用しているときにパスを設定することは可能です。これらは、インタラクティブ/bin/bash
シェルで表示されるPATHを複製するために私が実行できる最も近いものです。
$ ansible raspberrypi -m Shell \
-a 'PATH=$PATH:/usr/local/sbin:/usr/sbin:$HOME/bin env' \
| grep PATH
PATH=/usr/local/bin:/usr/bin:/bin:/usr/games:/usr/local/sbin:
/usr/sbin:/home/pi/bin
または、/etc/profile
ファイルをソースにすることもできます。
$ ansible raspberrypi -m Shell \
-a 'executable=/bin/bash source /etc/profile ; env | grep PATH'
PATH=/opt/consul/bin:/usr/local/sbin:/usr/local/bin:
/usr/sbin:/usr/bin:/sbin:/bin
これも機能するようです。
$ ansible raspberrypi -a '/bin/bash -l -c "env"'
PATH=/opt/consul/bin:/usr/local/sbin:/usr/local/bin:
/usr/sbin:/usr/bin:/sbin:/bin
つまり、あなたの質問が最終的にSudoの下でansibleを使用してコマンドを実行することに関するものであるとすれば、ansible -s -a env
を使用するときにPATHがどのように設定されるかをもう一度見ました。 Sudo -s
フラグをansibleで使用する場合、$ PATHはansible -a env
のみを使用する場合とは異なるメカニズムによって設定されることに注意することが重要だと思います。
Sudo command
またはansible -s
を使用すると、ユーザー環境がリセットされ、$ PATHはDefault secure_path
の/etc/sudoers
設定によって制御されます。これは man sudoers ドキュメント;
デフォルトでは、env_resetオプションは有効になっています。これにより、新しい最小限の環境でコマンドが実行されます。新しい環境には、env_checkおよびenv_keepオプションで許可された呼び出しプロセスからの変数に加えて、TERM、PATH、HOME、MAIL、Shell、LOGNAME、USER、USERNAME、およびSudo_ *変数が含まれます。
Default secure_path
の値を設定しない場合、これらの値はsshdバイナリにハードコード化されます。詳細は this answer を参照してください。
ただし、Fedora/centros/ubuntuのデフォルトでは、$ PATHの値は/etc/sudoers
に設定されたsecure_pathから取得されます。
secure_path-Sudoから実行されるすべてのコマンドに使用されるパス。
たとえば、私のFedoraローカルホストでは、/etc/sudoers
に次の行があります。
Defaults secure_path = /sbin:/bin:/usr/sbin:/usr/bin
sshとSudoを使用してenv
コマンドをリモートで実行すると、その正確なパスが返されます。
$ ssh localhost "Sudo env" | grep PATH
PATH=/sbin:/bin:/usr/sbin:/usr/bin
そして、私はansibleを使用して同じことを取得します。
$ ansible localhost -s -a 'env' | grep PATH
PATH=/sbin:/bin:/usr/sbin:/usr/bin
そして、私はraspbian(debian)インスタンスで同じことを試しましたが、同様の動作が得られます。
$ ansible raspberrypi -s -a 'cat /etc/sudoers' | grep secure
Defaults secure_path="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
そして、それはansibleが-s -a
オプションで見るパスです。
$ ansible raspberrypi -s -a env | grep PATH
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
元の質問に関しては、/etc/sudoers
ファイルを見て、Defaults secure_path="/some/path/here"
の値を確認します。
適切なsbin/
ディレクトリを含む値がそこにない場合、次のansibleのコマンドは、フルパスを指定しないと機能しません。
ansible multi -s -a "service ntpd stop"