What's the best way to escape a bash command in python?

Question:

I have a function that takes in a command as a string, and runs it on an AWS container using the aws binary.

The command adds a few extra symbols before and after the command the user requested to run – I won’t get into why.

def run_command_on_aws_container(command: str, aws_info):
    full_command = f"bash -c 'echo -n "|"; {command}; echo -n "|"'"

    subprocess.run(["aws", ..., "--command", full_command], ...)
    ...

command_to_run_on_aws_machine = 'python -c "for i in range(10): print(i)"'

run_command_on_aws_container(command_to_run_on_aws_machine, aws_info)

This works, but only if my command_to_run_on_aws_machine doesn’t contain single-quotes. If my command_to_run_on_aws_machine was this for example:

command_to_run_on_aws_machine = "python -c 'for i in range(10): print(i)'"

which is exactly the same command, but using single quotes instead of double quotes, the whole thing crashes. Or at least it doesn’t do what you’d expect.

Is there a way to make my run_command_on_aws_container function work with both strings, so that as long as the command arg is a proper bash command, it will run? Ideally not just blindly converting all single quotes to double quotes in a string, but in a way where if the command includes properly escaped quotes, it will still work?

Note: All commands being sent to run_command_on_aws_container as the command arg are hard-coded into the program. There’s no security issue here of executing arbitrary commands on a remote system. This is only for convenience, so that code being written outside of the function doesn’t need to worry about how to properly use a string.

Asked By: John

||

Answers:

shlex.quote() is designed specifically for this:

full_command = "bash -c " + shlex.quote(f'echo -n "|"; {command}; echo -n "|"')
Answered By: yut23
Categories: questions Tags: ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.