在非交互式、非登录 shell 中的 WSL 中源 bashrc



我正在做一个项目,我在 WSL 和bashrc方面遇到了问题。为了详细说明一点,我有keychain,我想在每次使用 WSL 命令时运行一个keychain命令。

所以我在我的~./bashrc中添加了该命令.

如果我从我的 Windows 终端使用wsl bash -ic "command",我在~/.bashrc中的命令运行。

我现在的问题是,我有另一个程序在没有bash -ic参数的情况下运行 WSL,我无法更改它。

您知道如何解决此问题或找到解决方法吗?

基本上,我希望每次从Windows终端使用WSL时,它都会首先运行keychain命令。

例如,假设我想运行wsl git push. 我希望我的keychain命令在git push运行之前执行。

好吧,我已经断断续续地研究了几天,看看我是否可以想出更好的解决方案。 我想不出什么都是最佳的,但我想我最终非常接近。

要重述/构建问题:

  • 你需要一个 WSL 发行版来运行某个交互式命令 (keychain),该命令将其环境变量加载到用户的 WSL/Bash 会话中。 这需要将密钥加载到ssh-agent中,以便 IntelliJ 中的wsl git命令将与您的插件一起使用。

  • 如果需要,keychain会要求输入密码以加载密钥。

  • keychain将以可以评估/获取的格式输出ssh-agent所需的环境变量,并将其反馈到 Bash 会话中。

    (旁注:我很幸运,我已经使用keychain几十年了,所以我对它的流程相当了解)。

  • 当使用wsl git ...运行时,WSL 将 shell (Bash) 作为非交互式、非登录 shell 启动,因此不处理~/.bashrc。 因此,即使密钥之前已加载到ssh-agent(通过keychain),Bash 会话也没有正确的SSH_AUTH_SOCKSSH_AGENT_PID

因此,插件中的git命令可能会对用户失败,因为它们需要基于密钥的身份验证。

我认为以上至少抓住了您要解决的问题的精神。

不幸的是,据我所知,除了修改 WSL 命令行的内容之外,没有一种方法可以强制 Bash 加载其启动文件,因为它是非交互式、非登录 shell。

建议的解决方法 -$WSLENV链加载 IntelliJ

我相信,这"非常接近"最佳状态。 用户需要通过WSL 启动 IntelliJ,并使用$WSLENV功能传递正确的环境变量。 这可以以交互方式或通过~/.bashrc完成。

将以下内容添加到~/.bashrc

eval $(keychain --eval ~/.ssh/<keyfile>)
export WSLENV=$WSLENV:SSH_AGENT_PID:SSH_AUTH_SOCK

完成此操作后,您应该能够运行:

wsl -e bash -lic /path/to/intellij.exe

它将询问密钥密码并(像往常一样)将SSH_AGENT_PID/SSH_AUTH_SOCK环境变量添加到 shell 会话中。它还会将这些变量名称添加到$WSLENV,以便将它们传递给从 WSL 内部启动的任何Windows进程。

当 IntelliJ Windows 可执行文件以这种方式启动时,这三个变量也将在其环境中可用:

  • WSLENV
  • SSH_AGENT_PID
  • SSH_AUTH_SOCK

当IntelliJ然后运行wsl git ...时,这三个变量也将传递回WSL,以便git能够从ssh-agent访问密钥。

虽然我没有IntelliJ,但我已经成功地测试了它:

wsl -e bash -lic pwsh.exe # or powershell.exe

然后,从PowerShell:

> $env:WSLENV
WT_SESSION::WT_PROFILE_ID:SSH_AGENT_PID:SSH_AUTH_SOCK
> $env:SSH_AGENT_PID
45
> $env:SSH_AUTH_SOCK
/tmp/ssh-XXXXXXTWbsTa/agent.44
> cd some-dir
> wsl git clone "git@github.com:NotTheDr01ds/<private_repo>"

它按预期工作。

其他选项

如果您的用户正在使用(或愿意使用)Bash以外的一些shell,这实际上会更容易一些:

  • Fish shell 启动文件甚至来源于非登录、非交互式 shell,此外它还支持"通用变量",允许SSH_A*变量自动提供给所有正在运行(和将来)的 Fish 实例。

  • Zsh 有一个启动文件(~/.zshenv),它来源于非登录、非交互式 shell。 它比 Fish 复杂一点,但它是可行的。

实际上,在我发现$WSLENV是一个可行的解决方案(不需要更改外壳)之前,我实际上将这些作为建议的解决方案开始。 但是,如果您想查看我关于如何在 Zsh 或 Fish 中执行此操作的文章,请查看此答案的编辑历史记录。

在 Windows 11 上,您可以在 wsl 启动时运行脚本,创建或编辑(作为 sudo)/etc/wsl.conf,内容如下:

[boot]
command="command to run"

在此处添加所需的命令。

最新更新