0

The situation in short

I can't launch an executable (binary or a script) in a WSL2 distro if it wasn't created inside this distro

I can launch scripts and binaries that were created inside the distro shell (not using /mnt/c or /mnt/d in any way)

But I can't launch anything that was created outside and copied inside from Windows (using /mnt/c or /mnt/d)

I can see the copied files in the file system, can "cat" them, can look them up with "which", but I cannot launch them by entering the path into the command line

The questions I have in regards to all this

  • How come that the shell can't see the files while utils you run from the shell can?
  • How do I make the shell see files that were copied from outside?
  • If I can't make the shell launch the files, then how do I launch them?

The Situation in detail

I have Windows 10 with WSL2 and two distros

  • Ubuntu-20.04
  • Alpine

In Ubuntu I have a "Hello, World!" project written in C

It compiles in Ubuntu and then and runs in Ubuntu just fine

But, when I copy it from Ubuntu to Windows

cp hello /mnt/d/

and then go to Alpine and copy it inside from Windows

cp /mnt/d/hello .

I then have trouble launching it inside Alpine

Here is the output of file hello command in Ubuntu with some extra formatting (just in case)

$ file hello
hello:
    ELF 64-bit LSB shared object, 
    x86-64, 
    version 1 (SYSV), 
    dynamically linked, 
    interpreter /lib64/ld-linux-x86-64.so.2, 
    BuildID[sha1]=021352ab7bf244e340c3c42ce34225b74baa6618, 
    for GNU/Linux 3.2.0, 
    not stripped

Here's what I have in Alpine

$ cp /mnt/d/hello .
$ ls -l
-rwxr-xr-x    1 pavel    pavel        16760 Apr 19 19:07 hello
$ ./hello
-ash: ./hello: not found

Now same with a script copied from Windows

Copy the script inside Alpine from Windows

$ cp /mnt/d/hello.sh .

Checking the contents

$ cat hello.sh
#!/bin/ash
echo Hello!

Setting the execute permission just in case

$ chmod agu+x hello.sh

Trying to run it

$ ./hello.sh
-ash: ./hello.sh: not found

But, I can launch the hello.sh by explicitly calling the ash tool and passing the script path as the argument

$ ash ./hello.sh
Hello!

At the same time, a script created inside Alpine runs just by entering it's path to the command line

$ cat << EOF > hello-local.sh
> #!/bin/ash
> echo Local hello!
> EOF
$ chmod agu+x hello-local.sh
$ ./hello-local.sh
Local hello!

Also, I couldn't make a file that would run from one that wouldn't either by copying it with cp

cp hello.sh hello2.sh

or by copying it with cat

cat hello.sh > hello3.sh
cmod agu+x hello3.sh

Why do I need to copy things from outside

It all started when I wanted to explore how Docker for Windows uses Linux namespaces to separate containers

The distro that Docker for Windows uses is called docker-desktop

The docker-desktop distro neither has utilities that I need for my experiments, nor a package manager to get those utilities

So I tried to copy them from outside

But now Docker for Windows studies is not the only concern

I want to understand this magic that is happening just as bad

1 Answers1

0

To be fair, there really are three separate questions here, but not necessarily the questions you listed in your post:

Secondary question -- Why does your script that you copied to Alpine fail?

As @MarkPlotnick covered in the comments (and you confirmed), it was due to the script having DOS/Windows line endings (CRLF). In general, try to avoid creating or editing Linux text files using Windows tools unless you are sure that they are using Linux line-endings.

Secondary question -- Why does your C program fail when you compile on Ubuntu and copy the binary to Alpine?

Also as @MarkPlotnick mentioned in the comments, this is because Ubuntu uses glibc as the standard library implementation by default, but Alpine uses musl. See a number of questions here for more information. The first one in the list sorted by "relevance" is actually a pretty good one to start with.

Main question -- How to explore the docker-desktop distro

Really, your main goal seems to be how to gain access to certain tools inside the docker-desktop distro in order to learn more about it.

I was going to say, "don't" (with more explanation), but the reality is that I think it's a potentially good learning experience. I've done it, to some degree, so who am I to say it's "too dangerous" or recommend against it? ;-)

I will give fair warning, though -- The docker-desktop distro isn't intended to be run by users. Docker Desktop "injects" links and sockets into your other WSL2 distros (which you can enable/disable per-distro in Docker Desktop) so that its tools, processes, etc., are available to all your WSL2 (and PowerShell/CMD) instances.

I'd personally try to avoid making any changes to the docker-desktop distro itself. They'll likely be overwritten anyway by Docker Desktop when it extracts a new rootfs.

However, we can still gain access to the tools we need by accessing them from another distribution, but without copying them into docker-desktop.

First, a note -- As I think you have probably already figured out,docker-desktop is also musl-basesd. So you'll want to use tools from another musl-based distro like Alpine.

This can be easily accomplished by running the following line once in your Alpine instance (as root):

echo "/ /mnt/wsl/instances/Alpine none defaults,bind,X-mount.mkdir 0 0" >> /etc/fstab

That will add a mount to the Alpine instance into the tmpfs /mnt/wsl mount. You can see my Super User answer here for more details on that.

Once you wsl --terminate Alpine and restart it, you'll have access to the Alpine files from any other WSL2 distribution.

As a useful (for your intent) example, install the util-linux package in Alpine to get access to the lsns command.

Then, in the docker-desktop distro (which I assume you already know to access with wsl -u root -d docker-desktop, but I'll include that command here for other future readers), to list the namespaces:

/mnt/host/wsl/instances/Alpine/usr/bin/lsns

The docker-desktop instance automounts at a slightly different directory than default (see cat /etc/wsl.conf), so you need to adjust the path to /mnt/host/wsl instead of /mnt/wsl.

But with that in place, you can run all (most?) of your Alpine binaries directly in docker-desktop without having to modify it directly. If you have a script in your home directory that you want to run in docker-desktop, for instance:

/mnt/host/wsl/instances/Alpine/home/users/<yourusername>/hello.sh

Note that if you have a binary that requires a dynamically-linked library on Alpine, I'm assuming you'll need to adjust your LD_LIBRARY_PATH accordingly, although I haven't tested. For instance:

LD_LIBRARY_PATH=/mnt/host/wsl/instances/Alpine/usr/lib /mnt/host/wsl/intances/Alpine/usr/bin/<whatever>
NotTheDr01ds
  • 15,620
  • 5
  • 44
  • 70
  • Thank you! I was able to resolve all my issues with the info from @MarkPlotnick, but your answer gave me a lot of useful information as well – Pavel Taruts Apr 20 '22 at 18:13
  • btw, I found out two things. First, it's not that dangerous to tinker with docker-desktop, since you can easily recreate it by deleting it and restarting Docker for Windows. All containers will be in place after that. Second, docker-desktop has apk package manager that you can use to get utils from – Pavel Taruts Apr 21 '22 at 13:00
  • @PavelTaruts Nice! I didn't even check for `apk` since you mentioned needing to copy the files over, but that's good news. And yes, while "not intended for user access", it should all be recoverable even if something does go wrong. In general, WSL-type stuff is pretty resilient. – NotTheDr01ds Apr 21 '22 at 13:22