# Writing ansible module in shell/bash script

**URL:** <https://forum.ansible.com/t/writing-ansible-module-in-shell-bash-script/12145>\
**Category:** Ansible Project\
**Created:** [December 18, 2012, 2:04am UTC](https://forum.ansible.com/t/writing-ansible-module-in-shell-bash-script/12145 "2012-12-18T02:04:13Z")\
**Posts on this page:** 16\
**Page:** 1

<div class="post-metadata">

**Author:** ![Ser\_Heang\_Tan](https://avatars.discourse-cdn.com/v4/letter/s/ebca7d/32.png) [@Ser\_Heang\_Tan](https://forum.ansible.com/u/Ser_Heang_Tan)\
**Post date:** [December 18, 2012, 2:04am UTC](https://forum.ansible.com/t/writing-ansible-module-in-shell-bash-script/12145/1 "2012-12-18T02:04:13Z")

</div>

Hi,  
I am not sure whether there is any document on writing BASH/SH module in ansible, but I did found a few example. But I would like to know what is return value for JSON as indicated in this post here [https://groups.google.com/forum/?fromgroups=&pli=1#!searchin/ansible-project/shell$20script$20module/ansible-project/pb6\_YyZWJs0/l-KZKNjs\_t4J](https://groups.google.com/forum/?fromgroups=&pli=1#!searchin/ansible-project/shell$20script$20module/ansible-project/pb6_YyZWJs0/l-KZKNjs_t4J). Also, is there some function header like the initscript “functions” that I can reuse for the BASH/SH module?

I understand writing the module in Python and using Python \> 2.6 is the best way forward, but I have a lot of older Linux/Unix servers and have restriction on installing any new packages on them. In addition, the environment also have a few network devices that only support SSH and basic shell. I had been using the “raw” module, but I would like to write/reuse some of my current shell script (in BASH), and convert them into ansible module. Is that possible?

Thank you.  
Regards,  
SHTan

---

<div class="post-metadata">

**Author:** ![Chris\_Berkhout](https://avatars.discourse-cdn.com/v4/letter/c/e95f7d/32.png) [@Chris\_Berkhout](https://forum.ansible.com/u/Chris_Berkhout)\
**Post date:** [December 18, 2012, 3:51am UTC](https://forum.ansible.com/t/writing-ansible-module-in-shell-bash-script/12145/2 "2012-12-18T03:51:34Z")

</div>

Hi SHTan,

Here's a version of my site\_facts module, written in plain bash:  
[https://gist.github.com/4324790](https://gist.github.com/4324790)

To help with more fancy JSON operations in bash, the most impressive  
thing I've found is this:  
[https://github.com/kristopolous/TickTick](https://github.com/kristopolous/TickTick)  
However, it does some kind of on-the-fly rewriting of the script as it  
is run, so you need to use it from a script file. It won't work in an  
interactive shell, and it might not work for Ansible.

Cheers,  
Chris

---

<div class="post-metadata">

**Author:** ![jpmens1](https://avatars.discourse-cdn.com/v4/letter/j/e9c0ed/32.png) [@jpmens1](https://forum.ansible.com/u/jpmens1)\
**Post date:** [December 18, 2012, 6:24am UTC](https://forum.ansible.com/t/writing-ansible-module-in-shell-bash-script/12145/3 "2012-12-18T06:24:01Z")

</div>

> I am not sure whether there is any document on writing BASH/SH module in  
> ansible, but I did found a few example. But I would like to know what is  
> return value for JSON

You should be able to get by, either by printing JSON to stdout, or  
doing something like this:

----8\<-------8\<-------8\<-------8\<-------8\<-------8\<-------8\<---  
#!/bin/sh

# do something clever

echo "ok=true changed=true name='John Doe'"  
----8\<-------8\<-------8\<-------8\<-------8\<-------8\<-------8\<---

ansible server -m jp1  
server | success \>\> {  
&nbsp;&nbsp;&nbsp;&nbsp;"changed": true,  
&nbsp;&nbsp;&nbsp;&nbsp;"name": "John Doe",  
&nbsp;&nbsp;&nbsp;&nbsp;"ok": true  
}

> Also, is there some function header like the initscript "functions" that I  
> can reuse for the BASH/SH module?

I don't think that exists.

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;-JP

---

<div class="post-metadata">

**Author:** ![Andreas\_Davour](https://avatars.discourse-cdn.com/v4/letter/a/bcef8e/32.png) [@Andreas\_Davour](https://forum.ansible.com/u/Andreas_Davour)\
**Post date:** [December 18, 2012, 8:28am UTC](https://forum.ansible.com/t/writing-ansible-module-in-shell-bash-script/12145/4 "2012-12-18T08:28:48Z")

</div>

I can confirm that is a viable option. Send me a line if you want to talk more about it.

-andreas

---

<div class="post-metadata">

**Author:** ![Ser\_Heang\_Tan](https://avatars.discourse-cdn.com/v4/letter/s/ebca7d/32.png) [@Ser\_Heang\_Tan](https://forum.ansible.com/u/Ser_Heang_Tan)\
**Post date:** [December 18, 2012, 8:45am UTC](https://forum.ansible.com/t/writing-ansible-module-in-shell-bash-script/12145/5 "2012-12-18T08:45:58Z")

</div>

Hi JP,  
Yes, I know about these few variables from your sample shell script module 🙂  
But I am actually looking for a complete list of JSON returned variable, and the meaning of them.

Thank you.

---

<div class="post-metadata">

**Author:** ![Ser\_Heang\_Tan](https://avatars.discourse-cdn.com/v4/letter/s/ebca7d/32.png) [@Ser\_Heang\_Tan](https://forum.ansible.com/u/Ser_Heang_Tan)\
**Post date:** [December 18, 2012, 8:48am UTC](https://forum.ansible.com/t/writing-ansible-module-in-shell-bash-script/12145/6 "2012-12-18T08:48:27Z")

</div>

Hi Andreas,  
Thanks. I had used the sample shell script module from JP to do some testing and experiment, and I would like to findout whether there is something documented on the JSON variables which I can use to “echo” or “print” from the shell script module.

I got a number of shell scripts, which I usually use to update the remote hosts via ssh, and I am trying to make them ansible-module so that it can be reuse and I can also contribute back to the project.

Thank you.

---

<div class="post-metadata">

**Author:** ![Daniel\_Hokka\_Zakriss](https://avatars.discourse-cdn.com/v4/letter/d/f05b48/32.png) [@Daniel\_Hokka\_Zakriss](https://forum.ansible.com/u/Daniel_Hokka_Zakriss)\
**Post date:** [December 18, 2012, 10:10am UTC](https://forum.ansible.com/t/writing-ansible-module-in-shell-bash-script/12145/7 "2012-12-18T10:10:08Z")

</div>

Ser Heang Tan wrote:

> Hi JP,  
> Yes, I know about these few variables from your sample shell script module  
> 🙂  
> But I am actually looking for a complete list of JSON returned variable,  
> and the meaning of them.

You can return whatever data you want. There are really very few that have  
any special meaning, everything else is up to the module to define and the  
user to use. The special ones are:

- failed=True, indicating that the action failed  
- skipped=True, indicating a pre-condition for running the task was already  
&nbsp;&nbsp;met  
- changed=True/False, indicating the task changed/didn't change something,  
&nbsp;&nbsp;used to trigger notifiers and coloring of the output.  
- ansible\_facts=\<dict\>, containing custom facts that will be usable as  
&nbsp;&nbsp;variables in following tasks  
- stdout=\<str\>, containing text output. Will be split into lines that can be  
&nbsp;&nbsp;used if register'd  
- msg, used for e.g. failure messages

Daniel

---

<div class="post-metadata">

**Author:** ![Ser\_Heang\_Tan](https://avatars.discourse-cdn.com/v4/letter/s/ebca7d/32.png) [@Ser\_Heang\_Tan](https://forum.ansible.com/u/Ser_Heang_Tan)\
**Post date:** [December 18, 2012, 10:17am UTC](https://forum.ansible.com/t/writing-ansible-module-in-shell-bash-script/12145/8 "2012-12-18T10:17:18Z")

</div>

Thanks Daniel. With that info, it help me to better understand the possible output/return that my script should do as ansible-module.

Thank you.

---

<div class="post-metadata">

**Author:** ![Michael\_DeHaan](https://avatars.discourse-cdn.com/v4/letter/m/c4cdca/32.png) [@Michael\_DeHaan](https://forum.ansible.com/u/Michael_DeHaan)\
**Post date:** [December 19, 2012, 1:37am UTC](https://forum.ansible.com/t/writing-ansible-module-in-shell-bash-script/12145/9 "2012-12-19T01:37:37Z")

</div>

An additional tip -- If you want to read the arguments to a module,  
they are in key=value format, and can be read by parsing the file  
given as the first argument ($1) to the module script

Also also -- there is no reason to return changed if nothing has  
changed, or failed if nothing has failed, ansible assumes the value of  
these variables is no unless otherwise specified.

the JSON here document is a pretty good idea for bash.

Python modules have a slight leg up in they can use the common core  
(and are faster, due to some clever tricks), but things like Ruby and  
Perl can at least use available JSON libraries to help them along.  
The arguments are still key=value though, and not JSON, as they are  
passed from the playbook or CLI across relatively raw.

---

<div class="post-metadata">

**Author:** ![Chamberlain\_Darren](https://avatars.discourse-cdn.com/v4/letter/c/ee7513/32.png) [@Chamberlain\_Darren](https://forum.ansible.com/u/Chamberlain_Darren)\
**Post date:** [December 19, 2012, 2:10am UTC](https://forum.ansible.com/t/writing-ansible-module-in-shell-bash-script/12145/10 "2012-12-19T02:10:01Z")

</div>

\* Michael DeHaan \<michael.dehaan at gmail.com\> [2012/12/18 20:37]:

> An additional tip -- If you want to read the arguments to a  
> module, they are in key=value format, and can be read by parsing  
> the file given as the first argument ($1) to the module script

Actually, you don't even need to parse the args; the key=value  
format they use is valid sh variable syntax. All you need to do is  
source $1, and the variables become available in your env.

---

<div class="post-metadata">

**Author:** ![Michael\_DeHaan](https://avatars.discourse-cdn.com/v4/letter/m/c4cdca/32.png) [@Michael\_DeHaan](https://forum.ansible.com/u/Michael_DeHaan)\
**Post date:** [December 19, 2012, 2:41am UTC](https://forum.ansible.com/t/writing-ansible-module-in-shell-bash-script/12145/11 "2012-12-19T02:41:41Z")

</div>

Sweet! Killer feature I didn't even plan for 🙂

---

<div class="post-metadata">

**Author:** ![Antonio\_Messina1](https://avatars.discourse-cdn.com/v4/letter/a/5fc32e/32.png) [@Antonio\_Messina1](https://forum.ansible.com/u/Antonio_Messina1)\
**Post date:** [March 27, 2013, 11:06pm UTC](https://forum.ansible.com/t/writing-ansible-module-in-shell-bash-script/12145/12 "2013-03-27T23:06:30Z")

</div>

> > - Michael DeHaan \<michael.dehaan at [gmail.com](http://gmail.com)\> [2012/12/18 20:37]:
> > 
> > > An additional tip – If you want to read the arguments to a  
> > > module, they are in key=value format, and can be read by parsing  
> > > the file given as the first argument ($1) to the module script
> > 
> > Actually, you don’t even need to parse the args; the key=value  
> > format they use is valid sh variable syntax. All you need to do is  
> > source $1, and the variables become available in your env.
> 
> Sweet! Killer feature I didn’t even plan for 🙂

Sorry if I jump into this old discussion, but I’m a new user and I am as well starting to develop some ansible modules, so I would like to contribute.

I’ve noticed that the module acts a bit differently if you call it from `ansible` or from `ansible-playbook`: in the first case the module script is called with all the arguments on the command line, while in the latter it’s called with just one argument which is a file containing the module arguments.

In my module script I’ve therefore added the following at the beginning:

[-f $1] && source $1 || eval $\*

in order to make it work with both ansible and ansible-playbook.

Moreover, I usually use the following syntax to print json structures:

cat \<\<EOF  
{  
“failed”: false,  
“changed”: true,  
“foo”: “bar”  
}  
EOF

which is, IMHO, quite handy.

I still have a few question though:

- does ansible gives a special meaning to the exit status of the script? If I exit with `0` or `1` is it the same for ansible as long as the output is json-ized and meaningful?
- is the standard error ignored by ansible?
- does ansible set any environment variable the module can access, like variables or group names?
- is there a way to show the module documentation using ansible-doc.

.a.

P.S. I know the preferred way to develop modules is using Python, but sometimes a shell script is a lot easier and faster to write, and since ansible is so wonderful to allow you to do it… 🙂

---

<div class="post-metadata">

**Author:** ![Michael\_DeHaan](https://avatars.discourse-cdn.com/v4/letter/m/c4cdca/32.png) [@Michael\_DeHaan](https://forum.ansible.com/u/Michael_DeHaan)\
**Post date:** [March 27, 2013, 11:13pm UTC](https://forum.ansible.com/t/writing-ansible-module-in-shell-bash-script/12145/13 "2013-03-27T23:13:31Z")

</div>

"I've noticed that the module acts a bit differently if you call it  
from `ansible` or from `ansible-playbook`: in the first case the  
module script is called with all the arguments on the command line,  
while in the latter it's called with just one argument which is a file  
containing the module arguments."

This actually isn't the case, it is true when you write non-python  
modules you get the arguments file.

To answer other questions, modules do not see any variables -- this is  
a basically a security feature, only arguments you pass to modules get  
sent to modules, there is a principle of 'least data exchange'. (Same  
reason we don't have a fileserver).

exit codes are not important, but a script should always return 0 and  
returned failed=1 (or True) in the JSON on failure.

Ansible also supports "baby JSON" which is just a list of key=value  
pairs, so you don't technically have to output JSON.

non-Python modules won't work with ansible-doc currently.

---

<div class="post-metadata">

**Author:** ![Ed\_Greenberg](https://avatars.discourse-cdn.com/v4/letter/e/7ab992/32.png) [@Ed\_Greenberg](https://forum.ansible.com/u/Ed_Greenberg)\
**Post date:** [February 13, 2015, 8:39am UTC](https://forum.ansible.com/t/writing-ansible-module-in-shell-bash-script/12145/14 "2015-02-13T08:39:47Z")

</div>

Hi Folks,

My module, written in bash shell, does exactly what it is supposed to do (set up an snmpd v3 password), and ends with:

echo “changed=true”

but it results in:

[xxxxxx.example.com](http://xxxxxx.example.com) | FAILED \>\> {  
“failed”: true,  
“msg”: “changed=true\r\n”,  
“parsed”: false  
}

This module, rescued from an old (pre 1.0) installation of ansible, used to succeed, so I wonder, what changed, or what I might have done wrong.

This is Ansible 1.8.2-1.el6 from the epel repo, running on centos 6.5.

Any help welcome.

Thanks,

Ed Greenberg  
Lake George, NY

---

<div class="post-metadata">

**Author:** ![Tomasz\_Kontusz](https://avatars.discourse-cdn.com/v4/letter/t/bc79bd/32.png) [@Tomasz\_Kontusz](https://forum.ansible.com/u/Tomasz_Kontusz)\
**Post date:** [February 13, 2015, 8:46am UTC](https://forum.ansible.com/t/writing-ansible-module-in-shell-bash-script/12145/15 "2015-02-13T08:46:42Z")

</div>

I think the simple module output parser got deprecated and dropped in the meantime. Try echoing ‘{changed: true}’

Ed Greenberg [greenberg.ed@gmail.com](mailto:greenberg.ed@gmail.com) napisał:

---

<div class="post-metadata">

**Author:** ![Ed\_Greenberg](https://avatars.discourse-cdn.com/v4/letter/e/7ab992/32.png) [@Ed\_Greenberg](https://forum.ansible.com/u/Ed_Greenberg)\
**Post date:** [March 3, 2015, 7:01pm UTC](https://forum.ansible.com/t/writing-ansible-module-in-shell-bash-script/12145/16 "2015-03-03T19:01:04Z")

</div>

I fixed this with: echo -n ‘{“changed”: “true”}’

Note that the quotes around “changed” and “true” were essential.

Thanks all
