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.