Ansible Modules – shell vs. command

In the Ansible Core are a lot of Ansible modules included for almost all use cases. On this page
are all modules listed and described with the available options and some examples. Some Ansible modules are on the first view quite similar and can be used for the same purpose, but often are there some crucial differences.

Shell vs. Command

A typical example are the Ansible modules Shell and Command. In the most use cases both modules lead to the same goal. Here are the main differences between these modules.

  • With the Command module the command will be executed without being proceeded through a shell. As a consequence some variables like $HOME are not available. And also stream operations like  <, >, | and & will not work.
  • The Shell module runs a command through a shell, by default /bin/sh. This can be changed with the option executable. Piping and redirection are here therefor available.
  • The command module is more secure, because it will not be affected by the user’s environment.

Conclusion

Before the usage of both modules, you should check, if there isn’t a more specific Ansible module for that task. It’s always better to use a module instead of running a raw command, because the modules are designed to be idempotent and fulfill other standards like exception handling.

If there isn’t a module available, it’s safer to use the command module, because the task will not be affected through the user environment.

If you need the user environment or streaming operations there’s only the shell module, but you should be careful. Keep in mind the following hint from Ansible, if you use the shell module in combination with variables:

To sanitize any variables passed to the shell module, you should use “{{ var | quote }}” instead of just “{{ var }}” to make sure they don’t include evil things like semicolons.)

10 Comments

  • Max Reply

    Maybe include infos about the raw module

    • Dominique Barton Reply

      Good point Max. I think we should add another blog entry for the raw module, as it can execute commands on a remote machine without using Python. Thanks for the hint!

  • Howard Reply

    Very helpful!! I was wondering why ‘mkdir /data && chown user:user /data’ does not work in command, because && is streaming operation!

  • Zex Reply

    Unfortunately, Ansible is incapable of executing some common shell commands. For example when you use shell sequence it won’t work in ansible:

    shell: echo {1..5000}

    When you copy the above command to shell and execute, it will echo 5000 numbers. Of course, echo repeated 5000 times is not that useful, but I have a real-life example with configuring redis cluster where you have to assign slots in a loop. Now, shell is incredibly fast and does it in less than a second.

    If you try to simulate it by using Ansible loops, it’s so slow that our Sun will inflate and scorch the Earth before you see the end of that loop.

    On top of that, yaml imposes some stupid limitations, after that the Ansible parser imposes some idiotic limitations, for example you can write – fail msg=”Error” but not – fail msg = “Now it really failed”, because they forgot to skip whitespace during parsing. However, you can add spaces around the == sign, because I guess that part was written by another programmer.

    If you’re a programmer, Ansible is total crap. It doesn’t simplify things. More like “complexifies”.
    If you’re a non-programmer, and you learn Ansible, you’ll probably never learn how to program because it will screw up your brain.

    Haven’t seen for a long time that many design mistakes like in Ansible. And I’ve been coding in Erlang, so I know how horrible the design mistakes can be.

    • Dominique Barton Reply

      Hi Zex.

      Oh gosh, Erlang – please hit me as hard as you can!
      Just kidding. It seems you’re just here to bash against Ansible which is fine. You don’t like it and that’s your personal preference. I’m happy that you can share your personal experience here in our blog.

      However, I’m a developer too. I used to program PHP, Java, Objectiv-C, a bit of C and C++ and lately a lot of Python. I’m probably not that hardcore developer as you are, but hey that’s OK. So even if I’m a programmer, I don’t think Ansible is “total crap”. Sure there are some things which could be optimised, but hey nothing’s perfect. Some bits of the code are a bit odd, sure. But instead of complaining about Ansible you could make a difference in let’s say, fixing the code and opening a merge request on Github?

      Regarding your “problem”. I’m sure you’re aware of the fact that the {1..5000} syntax is a shell-specific syntax (e.g. bash), which means you can’t really compare Ansible’s shell module with bash (or alike). However, you can pass that syntax via Ansible to bash or create a bash script and execute it. I’m sure both of these methods would work.

      Now as you’re the perfect developer and you’re very well experienced in Erlang, hit us with an alternative solution to Ansible. Do you have built a product by yourself and do you want to share it, probably even open-source? I’m open-minded and I love great products which make my life as a system engineer / developer simpler.

      I’m enthusiastic, passioned and impulsive too. It’s a great gift, but writing whining blog posts doesn’t help you nor the guys who put all that effort into an IMHO great product. So next time, please be more kind. You seem to have a lot of knowledge and it would be great if you can share it with people around you in a nice way.

      You can express yourself in several ways. One way about my opinion of Erlang could be:

      > Erlang is total bullshit and next to assembler the ugliest programming language out there. This will totally fuck up your brain.

      Or I could say:

      > I don’t like Erlang, because in my opinion it doesn’t look very nice. I like nice styled code. However, the performance of Erlang is outstanding and isn’t comparable to Java.

      As you can see, the second one is much nicer and reflects by personal opinion, while the first statement is offending anyone who might like, programm and contribtue to Erlang.

      Cheers & have a nice day
      Domi

    • Alan Sible Reply

      Hilarious.
      So true, I quite like ansible from an operational point of view, yet I entirely agree with your opinion.

      PS: you forgot the blank space before your list items, syntax error: invisible panic mode activated!

  • Santosh Reply

    I’m surprised !! unstable behaviors of shell and command modules:

    Suddenly “rm -rf ” command stop working with command module, even it was working fine in past on same host. when i used same command ( rm -rf ) with shell then it works, But again error, now shell command fails on different host.

    Below are the error :
    failed: [xxxxxxxxxx.com] => {“changed”: true, “cmd”: [“rm”, “-rf”, “/xxx/xxxx/xxxx/xxxx/jenkins”], “delta”: “0:00:00.651038”, “end”: “2016-11-23 03:15:49.552958”, “rc”: 1, “start”: “2016-11-23 03:15:48.901920”, “warnings”: [“Consider using file module with state=absent rather than running rm”]}
    stderr: rm: cannot remove `/xxx/xxxx/xxxx/xxxx/jenkins/jenkins/WEB-INF/lib’: Directory not empty

    Any help ?

    • Paolo Reply

      @santosh both “Consider using file module with state=absent rather than running rm” and “Directory not empty” seem to be more than sufficient hints to me…

      • Santosh

        Hi Paolo, Thanks for your reply, I already checked, even file module is not working for me. my Ansible version is 1.9.4
        same error showing below link:
        https://github.com/ansible/ansible/issues/11087

        currently I’m moving the folder instead of deleting 🙂

    • Lilian Reply

      Very true! Makes a change to see sonmeoe spell it out like that. 🙂

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.