SSH 多账号的配置

85次阅读
没有评论

共计 3986 个字符,预计需要花费 10 分钟才能阅读完成。

当我们有多个 SSH 账号时,会遇到需要使用不同 SSH 账号登录不同的远程服务器,或 push 不同的远程仓库的情况,比如:

  • github 的用户名为 user_gh, 邮箱地址为 [email protected],私钥为 id_rsa_gh
  • gitlab 的用户名为 user_gl,邮箱地址为 [email protected],私钥为 id_rsa_gl

如何在每次 push/pull/远程登录时自动匹配这些信息呢?笔者说下常用的解决方案。

多个用户信息的配置

在使用 git 推送代码到远程仓库时,若不同仓库的用户名不同,可将最常用的用户名设置为全局用户名,不常用的用户名单独在指定仓库进行设置。

全局设置

执行如下命令进行全局设置:

git config --global user.name "user_gh"
git config --global user.email "[email protected]"

也可以编辑 ~/.gitconfig,设置如下:

[user]
    name = user_gh
    email = [email protected]

指定设置

在指定仓库下执行如下命令:

git config user.name "user_gh"
git config user.email "[email protected]"

也可以编辑该仓库下的 .git/config,设置如下:

[user]
    name = user_gh
    email = [email protected]

多个 SSH key 的配置

如何让不同的 SSH key 自动识别不同的目标地址呢?笔者以开头的需求为例,说下配置 git 的过程,若需求是访问远程服务器,配置相似。

生成 SSH key

使用 ssh-keygen 命令生成公私钥,一般常用的参数如下:

  • -b:指定 key 的 bit 数,对于 RSA key 而言,默认是 3072 bits
  • -f:指定 key 的文件名,若需要指定路径,则文件名需要和路径一直,如 ~/.ssh/id_rsa_gh
  • -C:指定新的 comment,即公钥末尾的字符串,一般是邮箱地址,若不指定会是 username@hostname 的形式
  • -t:指定私钥类型,一般有 “dsa”, “ecdsa”, “ecdsa-sk”, “ed25519”, “ed25519-sk” 和 “rsa” 等几种,若指定为 rsa 还可以指定签名类型,默认为 “rsa-sha2-512”

如为 github.com 生成新 SSH key,key 名为 id_rsa_gh:

> ssh-keygen -f ~/.ssh/id_rsa_gh -C [email protected]
> ls -l
id_rsa
id_rsa.pub
id_rsa_gh
id_rsa_gh.pub

注意:若已有 ~/.ssh/id_rsa~/.ssh/id_rsa.pub,建议先对这两个文件进行备份,防止误操作覆盖了这两个文件。

将生成的 SSH 公钥(~/.ssh/id_rsa_gh.pub)内容添加到 github(Settings > SSH and GPG keys > New SSH key)中。若是要登录远程服务器,将公钥添加到远程服务器的 ~/.ssh/authorized_keys 文件中。

使用 ssh-agent 管理 SSH key

在使用上述 SSH key push 文件到 github 时可能会提示 ERROR: Permission to qileq/x.git denied to some-username,这里的用户名 “some-username” 可能不是 .git/config 设置的用户名。类似的若是 ssh 登录远程服务器,可能仍需要输入密码。这两个问题的原因可能是未使用正确的 SSH 私钥,这个问题可以通过 ssh-agent 来解决。

ssh-agent 是一个管理 SSH key 的后台辅助程序,它将私钥加载到内存中,避免每次使用私钥时都需要输入密码,自动加载 ~/.ssh/id_rsa~/.ssh/id_dsa~/.ssh/id_ecdsa 等各类型的默认私钥,这就是为什么我们不需要显式将 ~/.ssh/id_rsa 添加到 ssh-agent,却能访问远程服务器的原因。当 client 通过 ssh 连接到远程服务器时(或请求 github 时),服务器端会发送验证请求来识别 client 的身份,此时 client 会将验证请求转发给 ssh-agent,ssh-agent 根据配置查找已加载的私钥,然后将私钥处理过后的验证数据发送给 server 进行验证。从某种程序上来讲,ssh-agent 是 SSO 的一种实现。

ssh-agent 通过 ssh-add 来管理私钥,如下是 ssh-add 的一些习惯用法:

  • ssh-add filename:添加指定私钥,如 ssh-add ~/.ssh/id_rsa_gh~/.ssh/id_rsa_gh 添加到 ssh-agent 内存中
  • ssh-add -l:列出加载的私钥指纹
  • ssh-add -L:列出加载的私钥对应的公钥
  • ssh-add -D:删除所有加载的私钥
  • ssh-add -d filename:删除指定的私钥

macOS 系统是开机自动启动 ssh-agent,而 Linux 需要执行 eval $(ssh-agent -s) 来启动 ssh-agent。在启动 ssh-agent 后,执行 ssh-add ~/.ssh/id_rsa_gh 将新生成的私钥添加到 ssh-agent,然后执行 ssh -T [email protected] 测试私钥是否正确。

这里有个问题,前面说到 ssh-agent 将私钥保存在内存中,那么当机器重启后,这些私钥信息都将失效,需要把所有需要的私钥再加载一遍。如何解决这个问题呢?这里有两种方案:

  1. 每次执行 ssh-add filename 添加私钥时,都将操作命令保存到 ~/.zshrc~/.bashrc 等终端工具中。
  2. 使用 keychain 来管理私钥。使用 ssh-add -K filename 可将私钥添加到用户的 keychain 中。
    1. macOS 自带 keychain,若 ssh 未使用 keychain,尝试在 ~/.ssh/config 中添加 UseKeychain yes,如:
      Host github.com
      UseKeychain yes
      
    2. Linux 通过包管理器可安装 keychain。

使用 ssh-agent 还能实现 SSH 代理转发的功能,更多内容可参考 An Illustrated Guide to SSH Agent Forwarding使用 SSH 代理转发,由于这些内容和本文关系不大,故此不赘述。

配置 ssh config

编辑 ~/.ssh/config,针对不同的仓库地址配置不同的 HostHostNameUserIdentityFile,如下:

Host github.com
  HostName github.com
  User user_gh
  IdentityFile ~/.ssh/id_rsa_gh

Host gitlab.com
  HostName gitlab.com
  User user_gl
  IdentityFile ~/.ssh/id_rsa_gl

这样不同的仓库即使用不同的信息了。

修改仓库配置

这里还有个问题,如果 github.com 上两个仓库使用的用户信息不同该如何处理呢?假设一个用户是 user_gh,一个用户是 qileq,分别有各自的私钥。配置过程如下:

  1. 修改 ~/.ssh/config,添加 User qileq 相关的信息,如下:
Host github.com
  HostName github.com
  User user_gh
  IdentityFile ~/.ssh/id_rsa_gh

Host github-qileq.com
    HostName github.com
    User qileq
    IdentityFile ~/.ssh/id_rsa_qileq

Host gitlab.com
    HostName gitlab.com
    User user_gl
    IdentityFile ~/.ssh/id_rsa_gl
  1. 修改仓库的 git 信息,将仓库配置 url 中的 github.com 替换为 ssh config 中设置的 Host 值。
    以 Java 教程 java-roam-guide 为例,可以使用如下两种方式来修改仓库地址:

    1. 执行命令 git remote set-url origin [email protected]:qileq/java-learning.git
    2. 将该仓库 .git/config 中的 url = [email protected]:qileq/java-learning.git 修改为 url = [email protected]:qileq/java-learning.git
      修改完成后,执行 git remote -v 查看仓库地址是否正确。

    注:这里的仓库设置为 git 协议,非 https 协议

  2. 若是某仓库想覆盖默认设置的用户和邮箱的话,可在该仓库的 .git/config 文件中增加如下 nameemail 的配置,如下:

[user]
    email = [email protected]
    name = qileq

若不设置的话,会使用 ~/.gitconfig 中配置的默认用户信息。

问题

Repository not found

在 push/pull 部分仓库的数据时,有如下报错:

ERROR: Repository not found.
fatal: Could not read from remote repository.

Please make sure you have the correct access rights
and the repository exists.

除了检查完仓库是否输入错误外,若有多个 ssh 账户,可以执行 ssh-add -l 确认下是否相应的私钥未加载到内存中。若未加载,通过 ssh-add 加载后再次 push/pull 重试。

可以看到 SSH 有一套强大而又复杂的规则体系,通过正确的设置能节省我们不少时间。笔者这里抛砖引玉,对多账号的设置进行了一个总结,若有不当之处,请多指正。

正文完
 0
管理员
版权声明:本站原创文章,由 管理员 于2022-05-29发表,共计3986字。
转载说明:除特殊说明外本站文章皆由 CC-4.0 协议发布,转载请注明出处。
评论(没有评论)