从 bash heredoc 调用函数

Invoke function from bash heredoc

我正在从克隆存储库的 heredoc 中调用一个函数。但是存储库是在本地机器上克隆的,而不是我想要的远程机器。脚本在本地机器上执行。

_git_clone() {
    git clone myrepo
    git fetch --all --tags
}

ssh myserver <<EOF
    echo $(_git_clone)
EOF

问题 2) git fetch 仅将“获取来源”打印到控制台,而不是整个获取日志。我们如何使该命令将完整日志打印到控制台。

您需要将代码 逐字 传输到另一台服务器以 [​​=20=] 它在那里。带有不带引号的起始定界符的 heredoc 的工作方式类似于双引号字符串,这意味着任何命令替换,例如您在 运行ning before 结果字符串被传递到远程服务器。您可以通过将函数定义放在 heredoc 中并单引号起始分隔符来解决此问题:

ssh myserver <<'EOF'
_git_clone() {
    git clone myrepo
    git fetch --all --tags
}
echo $(_git_clone)
EOF

或者您可以在本地定义函数,然后在 heredoc 中替换它的定义:

_git_clone() {
    git clone myrepo
    git fetch --all --tags
}

ssh myserver <<EOF
$(declare -f _git_clone)
EOF

此处文档的内容在本地计算,就像用双引号括起来的字符串一样。为避免这种行为,您需要在此处 文档中“引用”,如下所示:

ssh myserver <<'EOF'
  echo $(_git_clone)
EOF

当然,这仍然不起作用,因为您已经在本地定义了 _git_clone 函数,因此在远程系统上您只会看到 bash: _git_clone: command not found...。如果您希望该功能远程可见,它需要进入您的此处文档:

ssh myserver <<'EOF'
    _git_clone() {
        git clone myrepo
        git fetch --all --tags
    }

    echo $(_git_clone)
EOF

但这似乎不必要地复杂;你不妨这样做:

ssh myserver <<EOF
    git clone myrepo
    git fetch --all --tags
EOF

此处文档语法的bash手册页的相关部分位于“此处文档”部分,内容为:

The format of here-documents is as follows:

<<[-]word
        here-document
delimiter

No parameter expansion, command substitution, pathname expansion, or arithmetic expansion is performed on word. If any characters in word are quoted, the delimiter is the result of quote removal on word, and the lines in the here-document are not expanded.

我强调了关键信息。

准确地说,这就是使用 i0b0 的回答中的想法解决了我的问题:

_git_clone() {
    git clone myrepo
    git fetch --all --tags
}

ssh myserver <<EOF
    $(declare -f _git_clone)
    _git_clone
EOF

因此解决方法是在 heredoc 中声明函数,然后将调用移出命令替换。