运行 ConEmu 启动任务中带有 WSL 的 zsh 别名

Running a zsh alias with WSL in a ConEmu startup task

我当前的 WSL2 + ConEmu + bash/zsh 设置工作正常。

我在 .zshrc:

中设置了一些别名
//.zshrc
alias mycommand1="[does some stuff]"
alias mycommand2="[does other stuff]"

我想要实现的是有一个 ConEmu 启动任务,它将 运行 mycommand1mycommand2 在两个单独的选项卡中,然后让这些选项卡保持打开状态。

这需要ConEmu加载WSL+bash+zsh,然后运行命令。

根据 the docs,我的默认任务当前 运行 是原生的 wsl.exe:

// {Bash::bash} Task commands
%windir%\system32\wsl.exe -cur_console:pm:/mnt --distribution Ubuntu-20.04

并且,在仔细阅读所有文档 (1, 2, 3) 并花费大量时间摆弄参数后,我只能进行以下尝试:

%windir%\system32\wsl.exe --distribution Ubuntu-20.04 -new_console:pm:/mnt -- ls
// logs my Windows User directory and prompts "Press Enter or Esc to exit..."
%windir%\system32\wsl.exe --distribution Ubuntu-20.04 -new_console:pm:/mnt -- mycommand1
// logs "zsh:1: command not found: mycommand1" and prompts "Press Enter or Esc to exit..."

我希望得到一些指点:

简答:

  • 使用新的 .zshrc 创建一个新的启动目录,(a) 获取现有的配置文件,以及 (b) 运行s 别名基于在启动 [=174 之前设置的环境变量=].
  • 通过设置 ZDOTDIRRUN_ALIASexecing zsh -li
  • 来启动每个 shell(制表符)
  • 运行这些通过wsl.exe命令
  • 将 ConEmu 启动文件设置为 运行 适当的命令

第 1 步:启动 zsh、运行 别名,并防止 session 退出

假设:我假设您真的希望这些是别名。如果你想 运行 其他任意 scripts/commands,你仍然可以做到,但需要对说明稍作改动。我在下面总结了需要进行的更改 in-line。

您可以使用多种技术来保持 shell 运行 宁,但建议 in this question 要求您:

  • 创建一个嵌套的 shell,这并不理想。
  • modify您现有的~/.zshrc“特殊情况”使用您的命令启动。这是一个巧妙的技巧,但我不喜欢在可以避免的情况下更改默认启动文件。也就是说,这要容易得多。如果你想走这条路,我会在这个答案的底部添加一些关于如何做的信息。

但是 ~/.zshrc 解决方案让我开始思考。如果你想在启动时运行任意命令,同时保持shell运行,答案.zshrc。 您只需要有一个 different .zshrc 用于“特殊情况”。

bash 在启动时有 --rcfile 选项 select 文件到 运行,但是 zsh 等价物有点棘手,因为它涉及设置 $ZDOTDIR 和更改 zsh 读取其启动的位置(从 this answer)。

因此,首先,让我们为您的“运行 别名”配置创建一个配置目录:

mkdir -p ~/.local/share/zsh/startup/run_alias/`

当然也可以随心所欲。然后,在该目录中,创建以下内容:

~/.local/share/zsh/startup/run_alias/.zshrc:

if [ -f $HOME/.zshrc ]; then
  . $HOME/.zshrc
fi

if [ -v RUN_ALIAS ] && alias | grep -q "^$RUN_ALIAS="; then
  eval "$RUN_ALIAS"
fi

unset RUN_ALIAS
unset ZDOTDIR

~/.local/share/zsh/startup/run_alias/.zprofile

if [ -f $HOME/.zprofile ]; then
  . $HOME/.zprofile
fi

当然,如果您始终知道 $HOME/.zsh.zprofile 存在,则条件是可选的。但还是安全点好。

重复 mycommand2

如果不明显,这将:

  • 调用您现有的 $HOME/.zshrc 来定义别名(以及您启动时的任何其他内容)
  • 检查以确保 $RUN_ALIAS 的内容确实是一个别名(增加一些安全性)
  • 调用RUN_ALIAS变量中定义的别名
  • 取消设置 RUN_ALIAS 变量(清理)
  • 取消设置特殊 ZDOTDIR 以便将来的子 shell 调用将使用 $HOME.
  • 中的文件
  • 让新的 .zprofile 也有原始来源

您现在可以通过以下方式调用 subshell 来测试它:

ZDOTDIR=~/.local/share/zsh/startup/run_alias RUN_ALIAS=mycommand1 zsh -li

当然,这会留下一个额外的子shell 运行ning($SHLVL 是2)。因此,请改用 exec

ZDOTDIR=~/.local/share/zsh/startup/run_alias RUN_ALIAS=mycommand1 exec zsh -li

$SHLVL 现在是 1,你的 command/alias 应该已经在当前(且仅)shell 执行了 ,并且仍然是 运行宁.

要在 WSL 中获得 运行ning,我们确实需要启动一个“外部 shell”(由 execing 适当的 zsh 代替) .我倾向于为此使用 sh,像这样:

wsl ~ --distribution Ubuntu-20.04 --exec sh -c "ZDOTDIR=`$HOME/.local/share/zsh/startup/run_alias RUN_ALIAS=mycommand1 exec zsh -li" # PowerShell quoted
wsl ~ --distribution Ubuntu-20.04 --exec sh -c "ZDOTDIR=$HOME/.local/share/zsh/startup/run_alias RUN_ALIAS=mycommand1 exec zsh -li" # CMD (and ConEmu) quoted

旁注:我的 Windows wsl 终端配置文件实际上与此非常相似。我对它们进行了一些简化,但在开始我的 shell (fish) 和 tmux.[=66= 之前,我仍然设置了一个环境变量(我想要的选项卡标题) ]

旁注 #2:我原来的回答使用了两个单独的 ZDOTDIR 和相应的目录。如果你想执行不同的 commands(相对于 aliases),这仍然有用。在这种情况下,创建额外的目录,并通过更改 ZDOTDIR 指向它们。把你的命令放在相应目录下修改后的.zshrc即可。

运行 ConEmu 启动时的命令

简单的部分。在任何地方(和任何名称)创建一个 conemu_start.txt,真的:

>%windir%\system32\wsl.exe -cur_console:t:"MyCommand1" -cur_console:pm:/mnt ~ --distribution Ubuntu-20.04 --exec sh -c "ZDOTDIR=$HOME/.local/share/zsh/startup/run_alias RUN_ALIAS=mycommand1 exec zsh -li"
>%windir%\system32\wsl.exe -cur_console:t:"MyCommand2" -cur_console:pm:/mnt ~ --distribution Ubuntu-20.04 --exec sh -c "ZDOTDIR=$HOME/.local/share/zsh/startup/run_alias RUN_ALIAS=mycommand2 exec zsh -li"

在ComEmu中,设置设置 -> 启动 -> 任务文件到这个文件.

应该可以了。启动 ConEmu 现在应该打开两个带有 zsh 的选项卡,每个选项卡对应 aliases/commands.

备选方案:将现有 .zshrc 修改为 运行 基于环境变量的别名

将以下内容添加到 ~/.zshrc 的底部:

if [ -v RUN_ALIAS ] && alias | grep -q "^$RUN_ALIAS="; then
  eval "$RUN_ALIAS"
fi

测试:

RUN_ALIAS=mycommand1 exec zsh -li

然后将conemu_start.txt改为:

>%windir%\system32\wsl.exe -cur_console:t:"MyCommand1" -cur_console:pm:/mnt ~ --distribution Ubuntu-20.04 --exec sh -c "RUN_ALIAS=mycommand1 exec zsh -li"
>%windir%\system32\wsl.exe -cur_console:t:"MyCommand2" -cur_console:pm:/mnt ~ --distribution Ubuntu-20.04 --exec sh -c "RUN_ALIAS=mycommand2 exec zsh -li"

将此添加为第二个答案,以防它对您有用(而且很有可能)。

我的(很长的)其他答案假设您需要在继续到 运行 的同一子 shell 实例中使用 运行 的别名。如果您对别名 运行ning 没意见,那么 exec'ing a new shell,那么这个答案将是 简单得多

只需创建一个 conemu_start.txt(或任何你想称呼它的东西,无论你想把它放在哪里),具有以下内容:

>%windir%\system32\wsl.exe -cur_console:t:"MyCommand1" -cur_console:pm:/mnt ~ --distribution Ubuntu-20.04 --exec zsh -li -c "mycommand1; zsh -li"
>%windir%\system32\wsl.exe -cur_console:t:"MyCommand2" -cur_console:pm:/mnt ~ --distribution Ubuntu-20.04 --exec zsh -li -c "mycommand2; zsh -li"

与其他答案一样,在 ComEmu 中,设置 设置 -> 启动 -> 任务文件 添加到此文件。

就是这样。 -li 将导致 shells 成为 login(处理 .zprofile)和 interactive(哪个进程 .zshrc)。这样,别名被定义、执行,然后另一个子shell是运行保持ConEmu选项卡打开。