trinth
trinth

Reputation: 6047

How to escape ssh quoted shell commands in Python

I'm trying to write a function that will issue commands via ssh with Popen and return the output.

def remote(cmd):
    escaped = escape(cmd)
    return subprocess.Popen(escaped, ...).communicate()[0]

My trouble is how to implement the escape function. Is there a Python module (2.6) that has helpers for this? Google shows there's pipes.quote and re.escape but they seem like they only work for locally run commands. With commands passed to ssh, it seems the escaping needs to be more stringent:

For example on a local machine, this is ok:

echo $(hostname)

When passing to ssh it has to be:

ssh server "echo \$(hostname)"

Also, double quotes can be interpreted in different ways depending on the context. For literal quotes, you need the following:

ssh a4ipe511 "echo \\\"hello\\\""

To do variable exansion, double quotes are also used:

ssh a4ipe511 "echo \"\$(hostname)\""

As you can see, the rules for escaping a command that goes into SSH can get pretty complicated. Since this function will be called by anyone, I'm afraid some complex commands will cause the function to return incorrect output.

Is this something that can be solved with a built-in Python module or do I need to implement the escaping myself?

Upvotes: 0

Views: 3167

Answers (1)

larsks
larsks

Reputation: 311740

First:

pipes.quote and re.escape have nothing to do with locally run commands. They simply transform a string; what you do with it after that is your business. So either -- in particular pipes.quote -- is suitable for what you want.

Second:

If you want to run the command echo $(hostname) on a remote host using ssh, you don't need to worry about shell escaping, because subprocess.Popen does not pass your commands into a shell by default. So, for example, this works just fine:

>>> import subprocess
>>> subprocess.call([ 'ssh', 'localhost', 'echo $(hostname)'])
myhost.example.com
0

Double quotes also work as you would expect:

>>> subprocess.call([ 'ssh', 'localhost', 'echo "one   two"; echo three'])
one   two
three
0

It's not clear to me that you actually have a problem.

Upvotes: 1

Related Questions