Got a Windows & Linux dual boot setup? Rather than setting up a new WSL install, wouldn't it be nice to be able to "import" your existing native Linux install into WSL? While this method is not exactly an import, it is functionally similar.
Mounting the disk partition
Resources
The first step is mounting the partition containing your Linux install. If you only want to access the files of an ext4 partition from Windows, you'll only need this step.
I have defined a couple of PowerShell functions to making mounting and unmounting easier:
# These WSL (un)mount commands must be run in PowerShell as administrator
# TODO: Replace the Model string with your own value: 'SHGS31-500GS-2'
# TODO: Replace the parition number with your own value: 4
Function linuxmnt { wsl --mount (gcim -query "SELECT * from Win32_DiskDrive WHERE Model = 'SHGS31-500GS-2'" | select -expandproperty DeviceID) --partition 4 }
Function linuxunmnt { wsl --unmount (gcim -query "SELECT * from Win32_DiskDrive WHERE Model = 'SHGS31-500GS-2'" | select -expandproperty DeviceID) }
The linuxmnt
function will mount partition 4 of drive 0 in WSL at the mountpoint /mnt/wsl/PHYSICALDRIVE0p4
. This path will vary based on the drive/device id and partition number you are targeting. The linuxunmnt
will simply unmount all mountpoints for that drive.
You can include these in your PowerShell profile so they are always available. Your profile file path can be found with echo $profile
, which will likely output one of the two following paths, depending on the version of PowerShell you are running:
C:\Users\<your-user>\Documents\WindowsPowerShell\Microsoft.PowerShell_profile.ps1
C:\Users\<your-user>\Documents\PowerShell\Microsoft.PowerShell_profile.ps1
You'll need to modify the linuxmnt
and linuxunmnt
functions, as I have hardcoded the model (to choose the correct disk) and partition number I need to target.
Determining the device id
Begin by querying for this information in PowerShell:
> gcim -query "SELECT * from Win32_DiskDrive"
DeviceID Caption Partitions Size Model
-------- ------- ---------- ---- -----
\\.\PHYSICALDRIVE0 SHGS31-500GS-2 3 500105249280 SHGS31-500GS-2
\\.\PHYSICALDRIVE1 WDC WD1003FZEX-00K3CA0 1 1000202273280 WDC WD1003FZEX-00K3CA0
\\.\PHYSICALDRIVE2 ST2000DM008-2FR102 1 2000396321280 ST2000DM008-2FR102
\\.\PHYSICALDRIVE3 Samsung SSD 990 EVO 1TB 3 1000202273280 Samsung SSD 990 EVO 1TB
We target the Model
attribute rather than DeviceID
, since the physical drive number can change if hardware is added or removed. Although, in the bash function below we hardcode the path /mnt/wsl/PHYSICALDRIVE0p4
, physical drive 0. Something to be aware of, which could technically be made dynamic.
Determining the partition number
To determine the partition number containing the Linux filesystem, we can start with a bare mount, which will make all the drive's partitions visible in WSL, but without a mount point.
# Run in PowerShell as administrator
wsl --mount \\.\PHYSICALDRIVEX --bare # Specify correct id instead of X
After the WSL bare mount, run lsblk
from WSL.
$ lsblk
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINTS
sda 8:0 0 388.4M 1 disk
sdb 8:16 0 2G 0 disk [SWAP]
sdc 8:32 0 465.8G 0 disk
├─sdc1 8:33 0 512M 0 part
├─sdc3 8:35 0 3.7G 0 part
└─sdc4 8:36 0 461.5G 0 part
sdd 8:48 0 1T 0 disk /mnt/wslg/distro
/
Based on the partition sizes, I can see that sdc4
is what I'm looking for, the main ext4 filesystem. If you want to inspect a partition further to verify, you can use mount
in the usual way to mount its contents to a directory.
Chroot-ing into the Linux install
The helper function (named walter because that's the hostname that was chosen for the original native install):
# TODO: Replace PHYSICALDRIVE0p4 with the correct value based on the device id and partition number mounted
# TODO: Replace zach with the user you wish to switch to
function walter() {
if [[ ! -e /mnt/wsl/PHYSICALDRIVE0p4 ]]; then
echo "'/mnt/wsl/PHYSICALDRIVE0p4' does not exist. Did you call linuxmnt?"
return 1
fi
sudo mount -t proc /proc /mnt/wsl/PHYSICALDRIVE0p4/proc
sudo mount -t sysfs /sys /mnt/wsl/PHYSICALDRIVE0p4/sys 2> /dev/null
sudo mount --rbind /dev /mnt/wsl/PHYSICALDRIVE0p4/dev
sudo mount --rbind /mnt /mnt/wsl/PHYSICALDRIVE0p4/mnt
sudo chroot /mnt/wsl/PHYSICALDRIVE0p4/ su zach
}
Add the above function to your .bashrc
or other config file in your WSL install.
Random note, in my Debian WSL install, when I added a function to the .bashrc
file, running which walter
did not find the function, but type walter
did. More on that here.
At a minimum, all that's really needed is this line, sudo chroot /mnt/wsl/PHYSICALDRIVE0p4/ su zach
, to choot into the mountpoint and switch from the root user to your regular user.
sudo mount --rbind /mnt /mnt/wsl/PHYSICALDRIVE0p4/mnt
- This is helpful so that the typical WSL mounts to access the Windows C:\ drive (/mnt/c
) and any additional drives are accessible.
The /proc
, /sys
, and /dev
mounts are necessary for certain programs to work. In my case for tmux
.
Bringing it all together: The Workflow
Open PowerShell as Administrator and run
linuxmnt
Open a terminal for your WSL install, and run
walter
(or whatever you chose to name it).You have now chroot'd into your non-WSL Linux install! You'll have access to that shell and your installed programs, kind of as if you had SSH'd into it.