web-dev-qa-db-ja.com

「ansible -a "env"」がユーザーとは異なる環境パスを返すのはなぜですか?

リモートサーバーに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

想像できるように、sbinserviceなどの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ファイルに追加できるパス変数はありますか?

5
Pretzel

私がansibleを使用したときはいつでも、別のシェルの下で別のユーザーとして実行されました。次のようにして、ユーザーを確認できます。

ansible -a "id"

次に、以下で定義されたユーザーシェルを確認できます:cat /etc/passwd

パスに追加するベストプラクティスは、次の行を追加することです:/home/<username>/.profileor~/.bash_profile

2
cormpadre

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
10
Tom H

つまり、あなたの質問が最終的に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"
2
Tom H