Shutdown or Reboot a WSL session from inside the WSL session

Viewed 7239

I would like to be able to reboot WSL sessions. To do so is a little awkward as WSL does not use systemd so we cannot use reboot. Within a WSL session, we can run any Windows executable:

boss@Asus: ~ $ wsl.exe -l -v
  NAME            STATE           VERSION
* Ubuntu-20.04    Running         2
  fedoraremix     Stopped         1
  Alpine          Stopped         1
  Ubuntu          Stopped         1

Therefore, we can use wsl.exe (you have to make sure to always add .exe when calling Windows commands or they will not work) to shutdown the currently running WSL session wsl.exe -t Ubuntu-20.03, but the problem is that I don't know the session name.

When we are inside a WSL session, hostname is something different, and so I don't know how to find the name of the currently running session that I am inside (maybe a Windows process command that tells me what process I am running from??).

Ideally, I would like a command to equate to a reboot. I guess this would have to look something like:

  • Run an asynchronous command that will initiate a new session 5-10 seconds in the future to allow the previous session to fully shutdown (and that will not terminate when this session is terminated).
  • Terminate the currently running session with wsl.exe -t <my found name>.
  • A few seconds later, the new session will start up.
2 Answers

Credits to the commenters above.

To shutdown a session from within a WSL guest, you can run:

wsl.exe --terminate $WSL_DISTRO_NAME

Rebooting is also possible, however so far I do not know how to get a new terminal inside the same console window. The following will reboot the WSL guest and open a new console window of it when it has finished:

cd /mnt/c/ && cmd.exe /c start "rebooting WSL" cmd /c "timeout 5 && wsl -d $WSL_DISTRO_NAME" && wsl.exe --terminate $WSL_DISTRO_NAME

Explanation:

  • From the perspective of Windows, WSL systems are mounted as network resources. cmd does not support the resulting UNC path formats such as \\wsl$\Debian\<...>. Therefore it may be best to cd to a directory it can resolve as a Windows path instead, such as C:\, before it is executed. If ommited, cmd will complain and change its directory to cmd's %windir%.
  • && runs another command after the previous one has finished in linux and windows cmd.
  • cmd.exe /c starts a cmd instance and tells it to execute a command that follows.
  • start "<WindowTitle>" ... is a cmd-internal command to run another program inside its own window, independent of the cmd instance. In this case the program is another cmd window. It will not be affected when WSL shuts down.
  • In the original Linux-Terminal, the first cmd /c command has finished, and the third command after && shuts down the guest like above.
  • The second cmd window waits for a few seconds, then starts a new WSL session of the same WSL machine.

Creating an Alias

You can make this easier to use by creating an alias. For bash users, edit your ~/.bashrc file and apply the changes afterwards:

nano ~/.bashrc && source ~/.bashrc

Add either or both of the lines below anywhere in the file.

You can of course choose any name you want. Both shutdown and reboot exist as systemd commands, but since they do not work in WSL machines, you can replace them with an alias as follows:

alias shutdown='wsl.exe --terminate $WSL_DISTRO_NAME'
alias reboot='cd /mnt/c/ && cmd.exe /c start "rebooting WSL" cmd /c "timeout 5 && wsl -d $WSL_DISTRO_NAME" && wsl.exe --terminate $WSL_DISTRO_NAME'

Expanding on the ansver from @BasementScience

To manage a remote WSL I've set up a Windows TaskScheduler job to start wsl with an /etc/init-wsl which in turn starts cron, ssh, rsyslog and autossh (so I can connect back to WSL).

So naturally I'm keen to get these processes started also on a remote WSL reboot, so I'm able to login again afterwards.

# Added to $HOME/.bashrc - Renamed aliases to separate from OS commands
alias wslshutdown='wsl.exe --terminate $WSL_DISTRO_NAME'
alias wslreboot='cd /mnt/c/ && cmd.exe /c start "Rebooting WSL" cmd /c "timeout 5 && wsl -d $WSL_DISTRO_NAME" -- sudo /etc/init-wsl && wsl.exe --terminate $WSL_DISTRO_NAME'

The detail is here ... & wsl -d $WSL_DISTRO_NAME" -- sudo /etc/init-wsl & ...

This will not start a new shell, but will start my processes so I can login again.

The /etc/init-wsl script have to be created:

sudo touch /etc/init-wsl && sudo chmod 755 /etc/init-wsl

# Add services as needed
sudo bash -c 'cat << EOF > /etc/init-wsl
service ssh start
service cron start
EOF'
# Ensure your user (the %sudo group) can sudo the init script without password
sudo bash -c 'cat << EOF > /etc/sudoers.d/user-service
%sudo ALL=NOPASSWD: /usr/sbin/service *
%sudo ALL=NOPASSWD: /etc/init-wsl
EOF'
Related