Issue
I have a sed command that I need to execute through SSH. I'm coding in Python using Paramiko to SSH. The connection works and the sed command too. My problem is when I tried to merge them: I need to use sed as sudo (the sudo command works, I've test it with another command). Here's what I have:
session.exec_command("sudo bash -c \"" + """sudo sed -i "s/\"hostname\":" *"\".*\"/\"hostname\":" *"\"adddvariable\"/" /home/frappe/frappe-bench/sites/test-dev.site1.local/site_config.json""" + "\"")
The problem is that when this command run, the sed is considered 'unfinished', I get:
sed: -e expression #1, char 11: unterminated `s' command
I think it may be due to spaces in the sed command? I have no idea how to solve this one. I'm new to Python, Paramiko and SSH. Do someone know how to fix this?
Here's the full code if it helps:
ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.connect(
hostname=server_address,
username=server_username,
key_filename=server_key_file
)
session = ssh.get_transport().open_session()
session.set_combine_stderr(True)
session.get_pty()
session.exec_command("sudo bash -c \"" + """sudo sed -i "s/\"hostname\":" *"\".*\"/\"hostname\":" *"\"adddvariable\"/" /home/frappe/frappe-bench/sites/test-dev.site1.local/site_config.json""" + "\"")
stdin = session.makefile('wb', -1)
stdout = session.makefile('rb', -1)
stdin.flush()
frappe.msgprint(_(stdout.read().decode("utf-8"))) # same as print(stdout.read().decode("utf-8"))
Solution
Your code is rather unclear. There should definitely be no need to run nested sudo
commands, and for a single command, wrapping it in sudo bash -c
accomplishes nothing and introduces a superfluous process and a significantly increased security surface, as well as significant quoting issues.
Your immediate problem is probably most easily solved by using single quotes instead of double quotes around the sed
script, and getting rid of the extra sudo bash -c
.
session.exec_command("""sudo sed -i 's/"hostname": *"[^"]*"/"hostname": "adddvariable"/' /home/frappe/frappe-bench/sites/test-dev.site1.local/site_config.json""")
I'm not entirely sure I was able to guess what the sed
command should really accomplish. This one replaces (what appears to be) a JSON key/value hostname
with "hostname": "adddvariable"
, replacing whatever the old value was.
The argument to sed -i
should be a single string; a pair of single quotes prevent the shell from breaking up and tokenizing or otherwise changing the text between the single quotes. You should basically always use single quotes if you don't specifically need the shell to perform variable interpolation and/or command substitutions in the string.
Answered By - tripleee