views:

30

answers:

1

What is the best way to escape a string for safe usage as a command-line argument? I know that using subprocess.Popen takes care of this using list2cmdline(), but that doesn't seem to work correctly for paramiko. Example:

from subprocess import Popen
Popen(['touch', 'foo;uptime']).wait()

This creates a file named literally foo;uptime, which is what I want. Compare:

from paramiko import SSHClient()
from subprocess import list2cmdline
ssh = SSHClient()
#... load host keys and connect to a server
stdin, stdout, stderr = ssh.exec_command(list2cmdline(['touch', 'foo;uptime']))
print stdout.read()

This creates a file called foo and prints the uptime of the remote host. It has executed uptime as a second command instead of using it as part of the argument to the first command, touch. This is not what I want.

I tried escaping the semicolon with a backslash before and after sending it to list2cmdline, but then I ended up with a file called foo\;uptime.

Also, it works correctly if instead of uptime, you use a command with a space:

stdin, stdout, stderr = ssh.exec_command(list2cmdline(['touch', 'foo;echo test']))
print stdout.read()

This creates a file literally called foo;echo test because list2cmdline surrounded it with quotes.

Also, I tried pipes.quote() and it had the same effect as list2cmdline.

EDIT: To clarify, I need to make sure that only a single command gets executed on the remote host, regardless of the whatever input data I receive, which means escaping characters like ;, &, and the backtick.

A: 
AdmiralNemo