0

Im running the following command in my GitLab CI job:

ssh ${REMOTE_HOST} "docker restart $(docker ps --format '{{.Names}}' | grep '^backend')"

The problem is that it returns me the following error:

/usr/bin/bash: line 156: docker: command not found
"docker restart" requires at least 1 argument.

I know that docker does exist and works on the remote host, because I can log in to the host's shell and execute docker commands myself.

Based on my understanding the error seems two be two-fold - it tells me that "docker command is not found" and then tells me that "docker restart needs at least 1 argument".

So, I assume that the docker executable is not found for the nested command, which returns the "docker: command not found" error, and since that returns no names of containers, then docker restart fails as well.

I also tried replacing docker with /usr/bin/docker inside the nested command, but to no avail.

I know the ssh tunnel works correctly because just before that command, I execute the following two commands, which work fine:

ssh ${REMOTE_HOST} "docker pull my_registry/backend:${VERSION} "
ssh ${REMOTE_HOST} "docker-compose -f docker-compose.yml up --detach --remove-orphans"

So, I really believe the issue is that the docker executable isn't found for the inner command.

1 Answers1

3

Double quoted string will still allow local bash shell to expand the variables, command substitution,... inside the string.

This means that your command will execute docker ps --format '{{.Names}}' | grep '^backend' on the local machine, not on the remote machine as you intend.

ssh ${REMOTE_HOST} "docker restart $(docker ps --format '{{.Names}}' | grep '^backend')"

You could try escaping it with:

ssh ${REMOTE_HOST} "docker restart \$(docker ps --format '{{.Names}}' | grep '^backend')"

Or use single quotes. Here is an example:

ssh ${REMOTE_HOST} 'docker restart $(docker ps --format {{.Names}} | grep ^backend)'

More details you can find the the bash(1) man page in the QUOTING section.

   There are three quoting mechanisms: the escape character, single
   quotes, and double quotes.

A non-quoted backslash () is the escape character. It preserves the literal value of the next character that follows, with the exception of <newline>. If a &lt;newline> pair appears, and the backslash is not itself quoted, the &lt;newline> is treated as a line continuation (that is, it is removed from the input stream and effectively ignored).

Enclosing characters in single quotes preserves the literal value of each character within the quotes. A single quote may not occur between single quotes, even when preceded by a backslash.

Enclosing characters in double quotes preserves the literal value of all characters within the quotes, with the exception of $, , \, and, when history expansion is enabled, !. When the shell is in posix mode, the ! has no special meaning within double quotes, even when history expansion is enabled. The characters $ and retain their special meaning within double quotes. The backslash retains its special meaning only when followed by one of the following characters: $, `, ", , or <newline>. A double quote may be quoted within double quotes by preceding it with a backslash. If enabled, history expansion will be performed unless an ! appearing in double quotes is escaped using a backslash. The backslash preceding the ! is not removed.