![无法通过 ssh 隧道在远程主机上执行嵌套命令](https://linux22.com/image/786043/%E6%97%A0%E6%B3%95%E9%80%9A%E8%BF%87%20ssh%20%E9%9A%A7%E9%81%93%E5%9C%A8%E8%BF%9C%E7%A8%8B%E4%B8%BB%E6%9C%BA%E4%B8%8A%E6%89%A7%E8%A1%8C%E5%B5%8C%E5%A5%97%E5%91%BD%E4%BB%A4.png)
我在我的 GitLab CI 作业中运行以下命令:
ssh ${REMOTE_HOST} "docker restart $(docker ps --format '{{.Names}}' | grep '^backend')"
问题是它返回以下错误:
/usr/bin/bash: line 156: docker: command not found
"docker restart" requires at least 1 argument.
我知道它docker
确实存在并且可以在远程主机上运行,因为我可以登录到主机的 shell 并自己执行 docker 命令。
根据我的理解,错误似乎是双重的 - 它告诉我“未找到docker命令”,然后告诉我“docker restart至少需要1个参数”。
因此,我假设docker
嵌套命令未找到可执行文件,该命令返回“docker:未找到命令”错误,并且由于该命令不返回容器名称,因此docker restart
也会失败。
我也尝试在嵌套命令中替换docker
,/usr/bin/docker
但无济于事。
我知道 ssh 隧道工作正常,因为就在执行该命令之前,我执行了以下两个命令,它们工作正常:
ssh ${REMOTE_HOST} "docker pull my_registry/backend:${VERSION} "
ssh ${REMOTE_HOST} "docker-compose -f docker-compose.yml up --detach --remove-orphans"
所以,我确实相信问题在于docker
没有找到内部命令的可执行文件。
答案1
双引号字符串仍然允许本地 bash shell 扩展字符串内的变量、命令替换等。
这意味着您的命令将docker ps --format '{{.Names}}' | grep '^backend'
在本地机器上执行,而不是您所希望的在远程机器上执行。
ssh ${REMOTE_HOST} "docker restart $(docker ps --format '{{.Names}}' | grep '^backend')"
您可以尝试使用以下方法进行转义:
ssh ${REMOTE_HOST} "docker restart \$(docker ps --format '{{.Names}}' | grep '^backend')"
或者使用单引号。以下是示例:
ssh ${REMOTE_HOST} 'docker restart $(docker ps --format {{.Names}} | grep ^backend)'
更多详细信息,您可以找到重击(1)手册页中的 QUOTING 部分。
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 \<newline> pair appears, and the backslash is not itself quoted, the \<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.