Short answer:
- Create a new startup directory with a new
.zshrc
that (a) sources the existing profile, and (b) runs aliases based on an environment variable set before starting the shell.
- Start each shell (tab) by setting
ZDOTDIR
, RUN_ALIAS
, and exec
ing zsh -li
- Run these through the
wsl.exe
command
- Set a ConEmu startup file to run the appropriate commands
Step 1: Launch zsh
, run an alias, and keep the session from exiting
Assumptions: I'm going to assume you really do want these to be aliases. If you want to run other arbitrary scripts/commands, you can still do it, but it will require a slight change to the instructions. I've summarized the changes needed in-line below.
There are several techniques you could use to keep the shell running, but the ones suggested in this question require you to either:
- Create a nested shell, which is not ideal.
- Or modify your existing
~/.zshrc
to "special case" a launch with your command. It's a neat trick, but I'm not a fan of changes to the default startup files when they can be avoided. That said, it's much easier. If you want to go this route, I'll add some info at the bottom of this answer on how to do it.
But the ~/.zshrc
solution got me thinking. If you want to run any arbitrary command at startup, and yet keep the shell running, the answer is .zshrc
.
You just need to have a different .zshrc
that you use for the "special case".
bash
has the --rcfile
option to select the file to run at startup, but the zsh
equivalent is a bit trickier, as it involves setting $ZDOTDIR
and changing the location from which zsh
reads its startup (from this answer).
So to start, let's create a config directory for your "run an alias" config:
mkdir -p ~/.local/share/zsh/startup/run_alias/`
Or wherever you want, of course. Then, in that directory, create the following:
~/.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
And ~/.local/share/zsh/startup/run_alias/.zprofile
:
if [ -f $HOME/.zprofile ]; then
. $HOME/.zprofile
fi
The conditionals, of course, are optional if you always know that your $HOME/.zsh
and .zprofile
exist. But better to be safe.
Repeat for mycommand2
.
If it's not obvious, this will:
- Call your existing
$HOME/.zshrc
to define the aliases (and anything else in your startup)
- Check to make sure the contents of
$RUN_ALIAS
really is an alias (some added security)
- Call the alias defined in the
RUN_ALIAS
variable
- Unset the RUN_ALIAS variable (cleanup)
- Unset the special
ZDOTDIR
so that future subshell invocations will use the files in $HOME
.
- Have the new
.zprofile
source the original as well
You can now test this by calling a subshell with:
ZDOTDIR=~/.local/share/zsh/startup/run_alias RUN_ALIAS=mycommand1 zsh -li
But of course, that leaves an extra subshell running ($SHLVL
is 2). So, use exec
instead:
ZDOTDIR=~/.local/share/zsh/startup/run_alias RUN_ALIAS=mycommand1 exec zsh -li
$SHLVL is now 1, your command/alias should have been executed in the current (and only) shell, and it is still running.
To get that running in WSL, we do need to start an "outer shell" (that is replaced by exec
ing the proper zsh
). I tend to use sh
for this, like so:
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
Side note: My Windows Terminal profiles for wsl
actually used to look very similar to this. I've streamlined them a bit, but I still set an environment variable (the title I want for the tab) before starting my shell (fish
) and tmux
.
Side note #2: My original answer used two separate ZDOTDIR
's and corresponding directories. This would still be useful if you wanted to execute different commands (as opposed to aliases). In that case, create additional directories, and point to them by changing the ZDOTDIR
. Just put your commands in the modified .zshrc
in the corresponding directory.
Run the commands at ConEmu Startup
The easy part. Create a conemu_start.txt
anywhere (and any name), really:
>%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"
In ComEmu, set Settings -> Startup -> Tasks file to this file.
That should do it. Starting ConEmu should now open two tabs with zsh
, one for each of these aliases/commands.
Alternative: Modify existing .zshrc
to run an alias based on an environment variable
Add the following to the bottom of ~/.zshrc
:
if [ -v RUN_ALIAS ] && alias | grep -q "^$RUN_ALIAS="; then
eval "$RUN_ALIAS"
fi
Test it with:
RUN_ALIAS=mycommand1 exec zsh -li
And then change the conemu_start.txt
to:
>%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"