Reputation: 78352
I am placing a file on a remote machine using paramiko ssh as follows.
rl = str(""" {"run_list":["role[monitor_server]"]}""")
cmd = """sudo touch /etc/chef/first-boot.json;sudo su - -c 'echo "%s" >> /etc/chef/first-boot.json'""" % (rl)
ssh.exec_command(cmd)
However, when I look at the file it looks like this.
{run_list:[role[monitor_server]]}
I need it to to look this this: {"run_list":["role[monitor_server]"]}
How to I keep the quotes?
Upvotes: 1
Views: 256
Reputation: 536675
The quotes would need to be escaped once to fit in the argument to the echo
command. This is double-quote-delimited ‘weak escaping’: every "
would have to be escaped to \"
and you would also have to worry about \
, $
and `
. The results are then dropped into the argument to the su
command, in single-quote-delimited ‘strong escaping’. Here, any single quote characters have to be included by breaking out of the string, eg by replacing with '\''
.
Nested escaping is tricky to get right, and given su
is involved the consequences of any mistake would appear to be dire for security. Avoid nested templating, and templating shell commands, at all costs.
A potentially better solution would be to cat > /etc/chef/first-boot.json
and then pipe in the contents you want stored through the stdin
file-like object that exec_command
returns. No need to worry about escaping then.
Or simply use Paramiko's SFTPClient to transfer the file.
(Also, str()
on the first line is completely redundant.)
Upvotes: 1
Reputation: 8251
Try escaping quotes. This is specific solution but should work.
>>> rl = """ {"run_list":["role[monitor_server]"]}""".replace('"', '\\"')
>>> print """sudo touch /etc/chef/first-boot.json;sudo su - -c 'echo "%s" >> /etc/chef/first-boot.json'""" % (rl)
sudo touch /etc/chef/first-boot.json;sudo su - -c 'echo " {\"run_list\":[\"role[monitor_server]\"]}" >> /etc/chef/first-boot.json'
Upvotes: 1