Search code examples
bashshellsshquoting

How to pass commands as arguments to ssh


My need is to make this command work:

sshpass -p XXXX ssh -oStrictHostKeyChecking=no [email protected] sudo docker exec -u postgres postgres-container /bin/bash -c \" psql -d crawl-configuration -c 'select * from schema_version'\"

But the result indicates that * is expanded by the shell and all matching files are passed as arguments to the psql command. So I searched how to protect the command from being expanded, but without success.

My experimentations gave me the following results.

A - The following command works, TOTO is displayed on my shell

sshpass -p XXXX ssh -oStrictHostKeyChecking=no [email protected] sudo docker exec -u postgres postgres-container /bin/bash -c \"echo TOTO\"

B - The following command doesn't work, a blank line is displayed on my shell

sshpass -p XXXX ssh -oStrictHostKeyChecking=no [email protected] sudo docker exec -u postgres postgres-container /bin/bash -c "echo TOTO"

C - This works, the result of ls is displayed. I don't understand why it works but not case B ?

sshpass -p XXXX ssh -oStrictHostKeyChecking=no [email protected] sudo docker exec -u postgres postgres-container /bin/bash -c "ls"

D - This works, I have the expected result

sshpass -p XXXX ssh -oStrictHostKeyChecking=no [email protected] sudo docker exec -u postgres postgres-container /bin/bash -c \" psql -d crawl-configuration -c \'select version from schema_version\' \"

E - Execution of this command on the host without passing by ssh works

sudo docker exec -u postgres postgres-container /bin/bash -c " psql -d crawl-configuration -c 'select * from schema_version'"

What is the solution to make my first command work ?


Solution

  • I would say this:

    sshpass -p XXXX ssh -oStrictHostKeyChecking=no [email protected] \
      "sudo docker exec -u postgres postgres-container \
      /bin/bash -c \"psql -d crawl-configuration -c 'select * from schema_version'\""
    

    Double quote the whole command to be executed by ssh, then escape double quotes within the command.

    Alternatively, use a here-doc:

    sshpass -p XXXX ssh -T -oStrictHostKeyChecking=no [email protected] <<-'EOF'
        sudo docker exec -u postgres postgres-container \
        /bin/bash -c "psql -d crawl-configuration -c 'select * from schema_version'"
    EOF
    

    No quoting needed because of the quoted 'EOF' delimiter. The -T disables allocation of a pseudo-terminal.