ssh - 使用 SSH 别名时如何克隆远程仓库

标签 ssh mercurial

我知道我的 ssh 配置有效,因为我可以输入 ssh myAlias.ssh并连接得很好。

我正在尝试使用命令 hg clone ssh://myAlias.ssh//path/to/repo并获得 remote: ssh: Could not resolve hostname myAlias.ssh: No such file or directory
是否可以在这里使用 SSH 别名?

最佳答案

理论
一般原则
Mercurial 可以使用在 ~/.ssh/config 中创建的别名。 -- 我一直在 Linux 和 OS X 上使用这个特性。这是因为 Mercurial 不会尝试解析主机名本身,而是依赖 SSH 来完成此操作(并在遇到错误时将错误向上传递)。这就是为什么错误是 ssh:作为其前缀的一部分。 Bitbucket 甚至有 help关于通过 .ssh/config 设置别名. (在链接的示例中,他们使用它来管理两个单独的身份。)如果您通过另一种机制创建别名,例如 BASH alias , 那么这将不起作用,因为它依赖于 Mercurial 不使用的 BASH。
来自 Mercurial 源代码
我还浏览了 clone 的 Mercurial 源代码。 ,包括检查 sshpeer.pyutil.py对于 SSH 相关部分,Mercurial 确实将主机名/别名传递给 SSH 以进行正确的解析/解释。class url 的文档字符串在 util.py Mercurial (2.6.3) 源代码:

Reliable URL parser.

This parses URLs and provides attributes for the following
components:

<scheme>://<user>:<passwd>@<host>:<port>/<path>?<query>#<fragment>

Missing components are set to None. The only exception is
fragment, which is set to '' if present but empty.

If parsefragment is False, fragment is included in query. If
parsequery is False, query is included in path. If both are
False, both fragment and query are included in path.

See http://www.ietf.org/rfc/rfc2396.txt for more information.

Note that for backward compatibility reasons, bundle URLs do not
take host names. That means 'bundle://../' has a path of '../'.

Examples:

>>> url('http://www.ietf.org/rfc/rfc2396.txt')
<url scheme: 'http', host: 'www.ietf.org', path: 'rfc/rfc2396.txt'>
>>> url('ssh://[::1]:2200//home/joe/repo')
<url scheme: 'ssh', host: '[::1]', port: '2200', path: '/home/joe/repo'>
>>> url('file:///home/joe/repo')
<url scheme: 'file', path: '/home/joe/repo'>
>>> url('file:///c:/temp/foo/')
<url scheme: 'file', path: 'c:/temp/foo/'>
>>> url('bundle:foo')
<url scheme: 'bundle', path: 'foo'>
>>> url('bundle://../foo')
<url scheme: 'bundle', path: '../foo'>
>>> url(r'c:\foo\bar')
<url path: 'c:\\foo\\bar'>
>>> url(r'\\blah\blah\blah')
<url path: '\\\\blah\\blah\\blah'>
>>> url(r'\\blah\blah\blah#baz')
<url path: '\\\\blah\\blah\\blah', fragment: 'baz'>

Authentication credentials:

>>> url('ssh://joe:xyz@x/repo')
<url scheme: 'ssh', user: 'joe', passwd: 'xyz', host: 'x', path: 'repo'>
>>> url('ssh://joe@x/repo')
<url scheme: 'ssh', user: 'joe', host: 'x', path: 'repo'>

Query strings and fragments:

>>> url('http://host/a?b#c')
<url scheme: 'http', host: 'host', path: 'a', query: 'b', fragment: 'c'>
>>> url('http://host/a?b#c', parsequery=False, parsefragment=False)
<url scheme: 'http', host: 'host', path: 'a?b#c'> 
但是,__init__ class sshpeer的方法在 sshpeer.py (用于通过 SSH 克隆)引入了 URL 中不允许密码的附加限制:
    u = util.url(path, parsequery=False, parsefragment=False)
    if u.scheme != 'ssh' or not u.host or u.path is None:
        self._abort(error.RepoError(_("couldn't parse location %s") % path))

    self.user = u.user
    if u.passwd is not None:
        self._abort(error.RepoError(_("password in URL not supported")))
(其他协议(protocol)允许使用 URL 中的密码,但我会将查找相关代码块留给读者作为练习,或者参见 URLs 上的文档)
现场演示——调试的潜在帮助
我们可以使用 -v选项以查看 Mercurial 在克隆期间如何与 SSH 交互。但首先,我的配置文件中的一些相关摘录。
来自我的.ssh/config文件:
Host bitbucket.ssh 
  Hostname bitbucket.org
  User hg
来自我的.hgrc文件:
[ui]
# Irrelevant settings omitted
# enable compression in SSH
ssh = ssh -C
现在,我们来看看在克隆期间会发生什么:
livius@localhost ~ $ hg clone -v ssh://bitbucket.ssh/palday/splitauthor
running ssh -C bitbucket.ssh 'hg -R palday/splitauthor serve --stdio'
destination directory: splitauthor
requesting all changes
adding changesets
adding manifests
adding file changes
added 3 changesets with 9 changes to 6 files
updating to branch default
resolving manifests
getting .hgignore
getting COPYING
getting README.rst
getting filter-revisions.awk
getting splitauthor.sh
getting testregex.sh
6 files updated, 0 files merged, 0 files removed, 0 files unresolved
第一个输出行确实说明了一切:Mercurial 将它从 URL 中解析出来的主机名(在本例中为您的别名)传递给 SSH,后者处理解析主机名/别名的实际问题。
其他评论和提示
  • 在您的示例中 hg clone ssh://myAlias.ssh//path/to/repo ,主机名后面的斜杠太多了,但我假设这仅在示例中。如果不是,这可能会导致您的路径是绝对的,而不是相对于用户名(如 .ssh/config 中的配置)。另见 hg clone 文档中的示例
  • 我还发现确切的错误消息有点奇怪。当我使用未定义的主机名尝试此操作时,例如我没有在我的 .ssh/config 中定义的别名,我在 OS X 上收到以下错误:remote: ssh: Could not resolve hostname server.ssh: nodename nor servname provided, or not known .在 Linux 上,我得到 remote: ssh: Could not resolve hostname server.ssh: Name or service not known .
    所以,我怀疑你是在 Windows 上这样做的。我不知道 PuTTY 之类的如何处理 Windows 上的配置文件,这可能意味着存在不同的语法,这就是您的问题所在。运行hg clone -v还将让您看到 Mercurial 正在调用的确切电话,这对于追踪哪里出了问题也非常有用。
  • 在 Unix-y 系统上,您可以尝试 ssh -T myAlias.ssh测试连接和您的别名通过/失败,或 ssh -v myAlias.ssh获得关于连接期间发生的事情的异常详细的输出。如果 ssh -T失败了,那肯定是比 Mercurial 级别低的问题。
  • 您还可以将 set SSH 本身设置为详细:而不是 ssh = ssh -C就像我的 .hgrc上面的片段,你可以设置ssh = ssh -Cv从 SSH 获取详细的调试输出。这为我生成了大约 70 行调试输出。
  • 关于ssh - 使用 SSH 别名时如何克隆远程仓库,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17380216/

    相关文章:

    linux - 无法在正在运行的 Docker 容器中 ssh localhost

    Windows 网络驱动器通过 ssh 和 powershell

    svn - 单图颠覆

    mercurial - 从 CVS 迁移到 Mercurial - 如何处理跨存储库符号链接(symbolic link)?

    linux - stunnel 和 sshuttle 有什么区别

    mysql - 使用 Workbench 将 Django 连接到远程 MySQL 数据库

    git - 如何更改git中的用户名?

    mercurial - Mercurial 命令之间的区别 pull -b <branchname> 与 pull -r <branchname>

    version-control - 如何退出 Mercurial 中的 merge ,然后与该分支重新 merge ?

    git - hg-git push 悄无声息地失败了