# Shell variables in command line usage

**URL:** <https://forum.ansible.com/t/shell-variables-in-command-line-usage/11367>\
**Category:** Ansible Project\
**Created:** [March 23, 2012, 1:23pm UTC](https://forum.ansible.com/t/shell-variables-in-command-line-usage/11367 "2012-03-23T13:23:31Z")\
**Posts on this page:** 17\
**Page:** 1

<div class="post-metadata">

**Author:** ![Dag\_Wieers](https://avatars.discourse-cdn.com/v4/letter/d/45deac/32.png) [@Dag\_Wieers](https://forum.ansible.com/u/Dag_Wieers)\
**Post date:** [March 23, 2012, 1:23pm UTC](https://forum.ansible.com/t/shell-variables-in-command-line-usage/11367/1 "2012-03-23T13:23:31Z")

</div>

Hi,

Being used to tools like ssh or shmux, I was wondering why the examples for command line usage are more complex wrt. escaping special characters.

&nbsp;&nbsp;&nbsp;[root@moria ansible]# ssh localhost 'echo $TERM'  
&nbsp;&nbsp;&nbsp;dumb

I would expect the following to work:

&nbsp;&nbsp;&nbsp;[root@moria ansible]# ansible all -a 'echo $TERM'  
&nbsp;&nbsp;&nbsp;127.0.0.1 | success | rc=0 \>\>  
&nbsp;&nbsp;&nbsp;$TERM

But as the example shows, you need double escaping.

&nbsp;&nbsp;&nbsp;[root@moria ansible]# ansible all -a 'echo \$TERM'  
&nbsp;&nbsp;&nbsp;127.0.0.1 | success | rc=0 \>\>  
&nbsp;&nbsp;&nbsp;$TERM

&nbsp;&nbsp;&nbsp;[root@moria ansible]# ansible all -a "echo \\$TERM"  
&nbsp;&nbsp;&nbsp;127.0.0.1 | success | rc=0 \>\>  
&nbsp;&nbsp;&nbsp;xterm

This makes using the command line functionality much harder than one would expect in the first place. What's more escaping does not even work with single quotes, which is what one would use. Having to use double quotes requires one to have double escaping.

Where is this coming from ? And can this be improved ?

Should I open an issue for this ?

---

<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 23, 2012, 1:28pm UTC](https://forum.ansible.com/t/shell-variables-in-command-line-usage/11367/2 "2012-03-23T13:28:15Z")

</div>

Don’t open an issue, it’s entirely a shell thing.

That example was about echoing the remote’s term, not my local term on the remote machine.

The only thing in play there is bash, there is nothing from Ansible requiring it … so it may be the example just needs correcting IF  
that isn’t required for you. But I think it is.

(Again though, there is nothing in Ansible that is trying to replace that dollar sign, because TERM isn’t set to a variable, and it knows it should not mess  
with 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 23, 2012, 1:43pm UTC](https://forum.ansible.com/t/shell-variables-in-command-line-usage/11367/3 "2012-03-23T13:43:06Z")

</div>

Yeah, the issue was the example should have used single quotes versus double quotes. Not an Ansible thing.

If you want to file an issue against the docs project, that’s good.

---

<div class="post-metadata">

**Author:** ![Dag\_Wieers](https://avatars.discourse-cdn.com/v4/letter/d/45deac/32.png) [@Dag\_Wieers](https://forum.ansible.com/u/Dag_Wieers)\
**Post date:** [March 23, 2012, 1:44pm UTC](https://forum.ansible.com/t/shell-variables-in-command-line-usage/11367/4 "2012-03-23T13:44:19Z")

</div>

Of course. But that's not what is happening in the example:

&nbsp;&nbsp;&nbsp;[root@moria ansible]# echo "$TERM"  
&nbsp;&nbsp;&nbsp;xterm  
&nbsp;&nbsp;&nbsp;[root@moria ansible]# echo "\$TERM"  
&nbsp;&nbsp;&nbsp;$TERM  
&nbsp;&nbsp;&nbsp;[root@moria ansible]# echo "\\$TERM"  
&nbsp;&nbsp;&nbsp;\xterm

So if you do the example as provided in [http://ansible.github.com/examples.html](http://ansible.github.com/examples.html)

&nbsp;&nbsp;&nbsp;ansible raleigh -m shell -a "echo \\$TERM"

You are sending "echo \xterm" to the remote bash. Which does:

&nbsp;&nbsp;&nbsp;[root@moria ansible]# echo "echo \\$TERM" | bash  
&nbsp;&nbsp;&nbsp;xterm

Now, the whole problem here obviously is that the example makes it very confusing, if we would use a different variable that is unique (e.g. $$) you'll see what I mean

&nbsp;&nbsp;&nbsp;[root@moria ansible]# echo "$$"  
&nbsp;&nbsp;&nbsp;5334  
&nbsp;&nbsp;&nbsp;[root@moria ansible]# echo "\$$"  
&nbsp;&nbsp;&nbsp;$$  
&nbsp;&nbsp;&nbsp;[root@moria ansible]# echo "\\$$"  
&nbsp;&nbsp;&nbsp;\5334

In fact what you would expect to work is this:

&nbsp;&nbsp;&nbsp;[root@moria ansible]# echo 'echo $$' | bash  
&nbsp;&nbsp;&nbsp;11531  
or  
&nbsp;&nbsp;&nbsp;[root@moria ansible]# echo "echo \$$" | bash  
&nbsp;&nbsp;&nbsp;11534

instead of

&nbsp;&nbsp;&nbsp;[root@moria ansible]# echo "echo \\$$" | bash  
&nbsp;&nbsp;&nbsp;5334

I hope this makes it more clear what I meant. So that's why I am convinced something is not being processed as it should.

---

<div class="post-metadata">

**Author:** ![Dag\_Wieers](https://avatars.discourse-cdn.com/v4/letter/d/45deac/32.png) [@Dag\_Wieers](https://forum.ansible.com/u/Dag_Wieers)\
**Post date:** [March 23, 2012, 1:48pm UTC](https://forum.ansible.com/t/shell-variables-in-command-line-usage/11367/5 "2012-03-23T13:48:41Z")

</div>

> > Don't open an issue, it's entirely a shell thing.
> > 
> > That example was about echoing the remote's term, not my local term on the  
> > remote machine.
> 
> Of course. But that's not what is happening in the example:

-snip-

> I hope this makes it more clear what I meant. So that's why I am convinced something is not being processed as it should.

What I think is happening (and why using single quotes or single escaping does not work) is that paramiko is escaping the commandline. I wonder if this is configurable ?

I should really dig into the code now that I know this is a real issue.

Sorry for the noise...

---

<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 23, 2012, 1:51pm UTC](https://forum.ansible.com/t/shell-variables-in-command-line-usage/11367/6 "2012-03-23T13:51:33Z")

</div>

There is some escaping going on in Runner with regards to the setup module, in particular.

It can probably be refined.

If you’d like to play with it, be my guest…

(Much more likely to be args processing prior to paramiko)

–Michael

---

<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 23, 2012, 1:53pm UTC](https://forum.ansible.com/t/shell-variables-in-command-line-usage/11367/7 "2012-03-23T13:53:55Z")

</div>

Sorry for the spam – here’s the crux of it. It should not be hard to fix at all.

The system tends to treat module\_args as an array in places. It’s a string. There is no reason anything should see it as anything BUT a string (the modules like strings), so removing the things that treat args as an array is probably the best way to go.

Treat them as a string all the way through the stack.

There are some places where we have to be careful, like when replacing variables that might contain spaces, so that they DO get quoted. This can happen  
when assigning a long string of text for a motd message variable, for instance.

–MPD

---

<div class="post-metadata">

**Author:** ![Dag\_Wieers](https://avatars.discourse-cdn.com/v4/letter/d/45deac/32.png) [@Dag\_Wieers](https://forum.ansible.com/u/Dag_Wieers)\
**Post date:** [March 23, 2012, 2:12pm UTC](https://forum.ansible.com/t/shell-variables-in-command-line-usage/11367/8 "2012-03-23T14:12:48Z")

</div>

The only piece I can find that interprets the string might be shlex.split(), however using it as a string still does not work as expected.

While it does work with a basic paramiko script.

---

<div class="post-metadata">

**Author:** ![Seth\_Vidal](https://avatars.discourse-cdn.com/v4/letter/s/7ba0ec/32.png) [@Seth\_Vidal](https://forum.ansible.com/u/Seth_Vidal)\
**Post date:** [March 23, 2012, 2:14pm UTC](https://forum.ansible.com/t/shell-variables-in-command-line-usage/11367/9 "2012-03-23T14:14:50Z")

</div>

I suspect this is due to the args being passed in as a file to the  
commands running them. This was done b/c otherwise we would end up with  
shell expansion from where you've run them and then shell expansion  
again when exec\_command ran them.

-sv

---

<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 23, 2012, 2:26pm UTC](https://forum.ansible.com/t/shell-variables-in-command-line-usage/11367/10 "2012-03-23T14:26:04Z")

</div>

This in /usr/bin/ansible is what I’m saying should be unnecessary, because strings are tolerated:

```auto

            module_args=shlex.split(options.module_args),

```

(The argsfile stuff to transfer the data should not be hurting anything in theory…. the code should not have to split anything at all until the module picks it up on the other side)

This results in the code trying to make the array back into a string and that is not necessary.

```auto

    

```

---

<div class="post-metadata">

**Author:** ![Dag\_Wieers](https://avatars.discourse-cdn.com/v4/letter/d/45deac/32.png) [@Dag\_Wieers](https://forum.ansible.com/u/Dag_Wieers)\
**Post date:** [March 23, 2012, 2:31pm UTC](https://forum.ansible.com/t/shell-variables-in-command-line-usage/11367/11 "2012-03-23T14:31:03Z")

</div>

I doubt the above is the culprit. The command module is using sys.argv directly. This was what confused me until Seth hinted this.

However, I noticed that the command module is running Popen in a shell, and I think that's being a problem (this together potentially with the shlex.split in the command module).

But what I lack to understand is how Popen integrates with Paramiko. I was made to believe we were using exec\_command() for remote commands, but that's apparently not the case :-/

---

<div class="post-metadata">

**Author:** ![Seth\_Vidal](https://avatars.discourse-cdn.com/v4/letter/s/7ba0ec/32.png) [@Seth\_Vidal](https://forum.ansible.com/u/Seth_Vidal)\
**Post date:** [March 23, 2012, 2:32pm UTC](https://forum.ansible.com/t/shell-variables-in-command-line-usage/11367/12 "2012-03-23T14:32:58Z")

</div>

So here is what ansible does.

it sends over the module (in this case command) with a set of arguments.

Then it exec\_command()s that module with those arguments on the remote  
machine.

if you look in your syslog on the remote machine you will see what is  
being run.

-sv

---

<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 23, 2012, 2:41pm UTC](https://forum.ansible.com/t/shell-variables-in-command-line-usage/11367/13 "2012-03-23T14:41:56Z")

</div>

Let’s take the debugging discussion off list (or use IRC) and just include you/me/Seth.

I doubt too many people are interested in it low level details, just in making sure that shell vars are happy for those that want to use them 🙂

---

<div class="post-metadata">

**Author:** ![Dag\_Wieers](https://avatars.discourse-cdn.com/v4/letter/d/45deac/32.png) [@Dag\_Wieers](https://forum.ansible.com/u/Dag_Wieers)\
**Post date:** [March 23, 2012, 2:42pm UTC](https://forum.ansible.com/t/shell-variables-in-command-line-usage/11367/14 "2012-03-23T14:42:24Z")

</div>

> > But what I lack to understand is how Popen integrates with Paramiko.  
> > I was made to believe we were using exec\_command() for remote  
> > commands, but that's apparently not the case :-/
> 
> So here is what ansible does.

Thanks !

> it sends over the module (in this case command) with a set of arguments.
> 
> Then it exec\_command()s that module with those arguments on the remote  
> machine.
> 
> if you look in your syslog on the remote machine you will see what is  
> being run.

So the example piece of code from command fails even locally:

---

<div class="post-metadata">

**Author:** ![Seth\_Vidal](https://avatars.discourse-cdn.com/v4/letter/s/7ba0ec/32.png) [@Seth\_Vidal](https://forum.ansible.com/u/Seth_Vidal)\
**Post date:** [March 23, 2012, 2:46pm UTC](https://forum.ansible.com/t/shell-variables-in-command-line-usage/11367/15 "2012-03-23T14:46:01Z")

</div>

so two things:  
1. If you specify the module name to ansible as 'shell' I believe it  
says shell=True in there and does what you want.  
2. the string vs list thing is involved too.

-sv

---

<div class="post-metadata">

**Author:** ![Seth\_Vidal](https://avatars.discourse-cdn.com/v4/letter/s/7ba0ec/32.png) [@Seth\_Vidal](https://forum.ansible.com/u/Seth_Vidal)\
**Post date:** [March 23, 2012, 2:46pm UTC](https://forum.ansible.com/t/shell-variables-in-command-line-usage/11367/16 "2012-03-23T14:46:38Z")

</div>

I think that's exactly what a list is for - so people can find this  
discussion later when they search for a question.

archiving for the future!! 🙂  
-sv

---

<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 23, 2012, 4:27pm UTC](https://forum.ansible.com/t/shell-variables-in-command-line-usage/11367/17 "2012-03-23T16:27:34Z")

</div>

Seems like this is resolved by using the shell module instead of the command module, combined with single quoting versus double quoting when passing arguments for the CLI.

(I still am going to make some cleanup around string processing.)

–Michael
