26

I have several Unbuntu WSL 2 "installations" on my Windows 10 system and I'd like to be able to run tools like rsync and diff between them. Is it possible to mount/find where the files for these other copies exist and run Linux commands on them. I don't want to copy into that area, just be able to "copy out".

To make this more concrete I have:

X:\WSL\U18.04_1 and X:\WSL\U18.04_2

And, I can get into the 2nd one by saying:

wsl -d X:\WSL\U18.04_2 -u myname

That will bring up a bash shell in my home direction in the U18.04_2 image. Now, I would like to do effectively:

diff -rbitw /mnt/x/WSL/U18.04_1/home/myname /home/myname

But of course, that doesn't work because /mnt/x/WSL/U18.04 is not actually a filesystem (as far as I can tell).

intel_chris
  • 658
  • 3
  • 7
  • 21

6 Answers6

29

There are a few ways to accomplish this.

Option 1: /etc/fstab entries in each distro

Updated, answer with the method I've personally been using for some time.

In each distribution, run the following command, one-time:

echo "/ /mnt/wsl/instances/$WSL_DISTRO_NAME none defaults,bind,X-mount.mkdir 0 0" | sudo tee -a /etc/fstab

1 (Credit and thanks to @mtraceur for the comment/suggestion and subsequent edited command. Simplified quoting is always a welcome change!)

After terminating the WSL distribution and restarting (to process /etc/fstab), your distribution will be available under /mnt/wsl/instances/<distroname> from all other WSL2 distributions.

2 See Option 1.5 if this doesn't work

See my related answer on Ask Ubuntu for details on why this works.

Option 1.5: /etc/fstab workaround for recent WSL releases

Under recent WSL releases (0.47.1 and later, I believe), a timing issue/change means that the fstab is processed and mounted before /mnt/wsl (a tmpfs filesystem) is mounted. If you are using a recent WSL release, and you find that /mnt/wsl/ does not contain an instances subdirectory, then:

sudo -e /etc/wsl.conf

And add the following:

[automount]
mountFsTab = false

[boot] command = sleep 5; mount -a

This should wait long enough before processing /etc/fstab to allow /mnt/wsl to be mounted by WSL first.

If you are using Systemd, you can also create a .mount file to workaround the issue. See @SteveMeierhofer's answer for details.

Option 2: Use wsl.exe's stdin/stdout

(Bonus #1: This method works on WSL1 as well)
(Bonus #2: It requires no advance configuration)
(Bonus #3: It will work even if the second distribution isn't running yet. Option 1 requires that the distro be running in advance for it to be available in /mnt/wsl.)

For certain use cases, you can just use normal input/output redirection through the wsl.exe command to access a given file. For instance:

wsl.exe -d otherinstance cat ~/myfile | diff myfile -

or

diff myfile <(wsl.exe -d otherinstance cat ~/myfile) # bash (probably all posix)
diff myfile (wsl.exe -d otherinstance cat ~/myfile | psub) # fish

This is similar to how you might perform the same operations on a remote host through ssh. You can even send entire directories through the pipeline using tar (or other means).

This also does not require the second distro to be running in advance

Option 3: ssh

For the rare case, you can even set up ssh servers in each instance. The only case I've come across where I have to do this is Ansible, although rsync might be a possibility as well.

Note that setting up ssh on WSL instances isn't all that straightforward, but it's probably easier if you are only accessing it via localhost. At the least, you'll need a separate port number for each instance. I recommend reserving 22 for the Windows host itself (potentially using the Windows OpenSSH Server).

Option 4: A bind mount in /mnt/wsl

Older version of Option 1, left here for posterity.

Adapted from this GitHub comment, you should be able to do:

mkdir /mnt/wsl/otherinstance
wsl.exe -d otherinstance -u root mount --bind / /mnt/wsl/otherinstance/

Honestly, this one scares me a little bit, because the "otherinstance" shuts down soon after the command is run (unless it was already running elsewhere). However, the mount seems stable, probably because (as later comments in that GitHub issue mention) all of the "drives" are available from the WSL2/Hyper-V subsystem anyway; they aren't necessarily dependent on the instance itself.

Regardless, it would be easy to allay my (probably unfounded) fears by simply running the "otherinstance" manually and performing the mount --bind from that instance itself.

NotTheDr01ds
  • 28,025
9

If you have a recent WSL release from the Microsoft Store then Systemd can be used. Once a WSL instance is running Systemd, create a mount file such as:

/etc/systemd/system/mnt-wsl-instances-${WSL_DISTRO_NAME}.mount

[Unit]
Description=WSL Instances

[Mount] What=/ Where=/mnt/wsl/instances/${WSL_DISTRO_NAME} Type=none Options=defaults,bind,X-mount.mkdir

[Install] WantedBy=multi-user.target

And then enable the mount:

sudo systemctl daemon-reload

sudo systemctl enable mnt-wsl-instances-${WSL_DISTRO_NAME}.mount --now

All WSL files are available at /mnt/wsl/instances.

6

Easiest way ever: is Windows Explorer.

  1. Open windows explorer and access the "remote" address \\wsl$, you will see something like these: example result
  2. Now right-click one of them and select "Open in a New Window"
  3. Set them side by side and explore/copy/paste files as you see fit.
1

You can copy files from an old WSL to a new WSL through SSH, and preserve file permissions. Ex:

Old WSL:

sudo apt install ssh
sudo vi /etc/ssh/sshd_config   =>   port 22000
sudo service ssh restart

New WSL:

# ssh localhost:22000
rsync -av -e 'ssh -p 22000' localhost:src_old_machine_file dst_new_machine_file
Kiruahxh
  • 301
1

Building on Steve's answer, I've wrapped it to be an all-in-one command that you can just paste into all WSL distros that you want to link filesystems with. It also includes the fixes for distro's that have dashes in them, e.g. Ubuntu distros.

This is tested on Ubuntu 20.04 and 24.04 with systemd enabled in both.

cat <<EOF | sudo tee /etc/systemd/system/mnt-wsl-instances-${WSL_DISTRO_NAME/-/}.mount
[Unit]
Description=WSL Instances

[Mount] What=/ Where=/mnt/wsl/instances/${WSL_DISTRO_NAME/-/} Type=none Options=defaults,bind,X-mount.mkdir

[Install] WantedBy=multi-user.target EOF

sudo systemctl daemon-reload

sudo systemctl enable mnt-wsl-instances-${WSL_DISTRO_NAME/-/}.mount --now

0

As a supplement to @NotTheDr01ds's Option 1 (1.5), you can simply use one single mount command in wsl.conf:

[boot]
command = "mount --bind / /mnt/wsl/instances/$WSL_DISTRO_NAME/ -o x-mount.mkdir"

The boot command always runs after wsl's automount, and runs once only – at the startup of a wsl instance.


P.S. There is a shortcut -B for --bind and (in recent versions) -m for -o x-mount.mkdir, so it can be simplified as

[boot]
command = "mount -Bm / /mnt/wsl/instances/$WSL_DISTRO_NAME/"

P.P.S. If you have other startup commands as well, just concatenate them in series:

[boot]
command = "mount -Bm / /mnt/wsl/instances/$WSL_DISTRO_NAME/; service ssh start; ..."
FaniX
  • 101