Home > Net >  WSL2 distro shell can't launch a file copied from outside
WSL2 distro shell can't launch a file copied from outside

Time:04-21

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

CodePudding user response:

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>
  • Related