kakts-log

programming について調べたことを整理していきます

ansible commandとshellモジュールの違い

ansibleで使って対象ノードで特定のコマンドを実行する際、
デフォルトで用意されているcommandモジュールとshellモジュールを使うことができます。
環境変数や、パイプを使ったコマンドを実行させる場合 この2つは挙動が異なるのでまとめてみました。

command モジュール

まずはcommandモジュールについて
command - Executes a command on a remote node — Ansible Documentation

The given command will be executed on all selected nodes. It will not be processed through the shell,
so variables like $HOME and operations like “<”, “>”, “|”, “;” and “&” will not work (use the shell module if you need these features).

commandモジュールはシェルを介して実行されないため、 環境変数($HOMEなど)や、 “<”, “>”, “|”, “;” などのパイプやリダイレクトは使えません。
commandモジュールの意図として、ユーザ環境に依存せずにセキュアにコマンドを実行することがあげられます。
ユーザ環境変数や、パイプ・リダイレクトを使った処理を行いたい場合は shell モジュールを利用するように公式のドキュメントにも書かれています。

If you want to run a command through the shell (say you are using <, >, |, etc), you actually want the shell module instead. The command module is much more secure as it’s not affected by the user’s environment.

shell モジュール

shell - Execute commands in nodes. — Ansible Documentation

commandモジュールの章でも説明したとおり、このshellモジュールは、指定したコマンドをシェル(/bin/sh)を介して実行します。
実行環境に依存した環境変数や、パイプ・リダイレクトを使った処理を実行できます。
これは悪い点もあり、もし実行時に playbookないで変数を使っていて、その変数が意図しない者の場合、そのまま対象ノードに対して実行されてしまうので危険です。
shell moduleで変数を使う場合は、サニタイズのために “{{ var }}” のかわりに “{{ var | quote }}“ を使うべきです。

shell commandモジュール双方のデメリット

qiita.com 上記の記事に、この2つの問題点が書いてあり、読んでみましたが、概ね同意です。
この2つのモジュールをつかってplaybookを書く場合 コマンド実行による冪等性の保証が困難であり、
playbookを読んだだけではシステムの本来あるべき姿(ansbile playbookは本来システムのある「べき」状態を記述するのが正しいはず)がわからなくなること、
そして実行処理は本来シェルスクリプトに任せればよいと思います。
playbookを書く際には他のモジュールを調べた上で、どうしても他のモジュールでは記述できないときにだけ、このshell commandモジュールを使えばよいかと思います。