16

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
  • 508
  • 1
  • 5
  • 18
  • Simple solution would require OpenSSH; Complicated solution but probably the most elegant solution you can hope for. – Ramhound Jun 26 '21 at 22:37
  • Ok, explain in a little more detail. How do I SSH from one distro to another? How do I give them IP addresses, etc. – intel_chris Jun 26 '21 at 23:10
  • They should already have an IP address. You would simply install OpenSSH like any other Linux installation – Ramhound Jun 27 '21 at 00:23
  • They both have the same IP addresses. So, that's not going to help. I need a way to find the Linux name of the filesystem. The Linux equivalent of "\\wsl$\U18.04_1". – intel_chris Jun 27 '21 at 08:06
  • Why don’t you assign different IP addresses? – Ramhound Jun 27 '21 at 17:04
  • @Ramhound Do you have any information on changing the IP address? To my knowledge, the `init` process in WSL is what sets the IP address based on the Hyper-V vNIC. According to [this answer](https://superuser.com/a/1619390/1210833) at least, there's no way to change that. Using different ports for each instance's sshd is the way that I would do it, if ssh is the right answer. – NotTheDr01ds Jun 27 '21 at 18:54
  • Yeah, different ports, should work. – Ramhound Jun 27 '21 at 19:01

3 Answers3

22

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
  • 17,574
  • 4
  • 44
  • 81
  • As yet another option, you may use a `mount` command like this. `sudo mount -t none / /mnt/wsl/instances/$WSL_DISTRO_NAME -o defaults,bind,X-mount.mkdir` – kamae Jul 27 '23 at 06:31
5

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}

[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.

NotTheDr01ds
  • 17,574
  • 4
  • 44
  • 81
  • I like it -- Like I said in my answer, this should be a reliable way to get around the timing issue, so I'm really glad you took the time to document the proper configuration! Systemd mounts also (IIRC) some additional flexibility with dependency management and timing. Users can even mix-and-match, using your System configuration in distributions where they have it enabled, and the `boot` option I mention in others. They'll still be accessible in both directions. Great first answer! – NotTheDr01ds Feb 09 '23 at 04:26
  • One minor suggestion as I read through it in detail - Perhaps change the filename to just `/etc/systemd/system/wsl-instance.mount` -- There's really no reason to have a unique filename based on the distro_name, right? – NotTheDr01ds Feb 09 '23 at 04:32
  • I'm not sure if that filename will work. I'm no expert, but I think systemctl wants the name of the file to match the "where" path given in the file. Also, I couldn't have gotten this answer without your original answer -- thanks. – Steve Meierhofer Feb 15 '23 at 20:22
  • It seems that the file name should be `/etc/systemd/system/wsl-instance-${WSL_DISTRO_NAME}.mount` instead (with extension `.mount`). In addition, make sure there is no hypen `-` in `WSL_DISTRO_NAME`! Or an error `Where= setting doesn't match unit name. Refusing.` will occur (https://unix.stackexchange.com/a/345518/438616). One simple solution in this case is to replace all `${WSL_DISTRO_NAME}` with a name without hypen. – sup39 Apr 17 '23 at 01:17
1

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.
kikimoro
  • 19
  • 2
  • 1
    Welcome to Super User! I recommend that you re-read the question, which specifically says in the first sentence, *"and I'd like to be able to run tools like rsync and diff between them."* Your proposal to use Windows Explorer to *"explore/copy/paste files as you see fit"* just doesn't appear to me to be a solution to this question. I'm fairly certain that there are *other* questions here on Super User to which your answer might be appropriate, but this doesn't appear to be it. Thanks! – NotTheDr01ds Feb 09 '23 at 04:11