Symlinks and /snap/bin structure?

I am trying to create a symbolic link from /bin/helm to /snap/bin/microk8s.helm3, so I can invoke ‘helm’ command normally with /bin/sh in a child process.

sudo ln -s /snap/bin/microk8s.helm3 /bin/helm

However The behavior was unexpected. When I call helm, I get the help message from Snap package manager. Looking at the directory structure for /snap/bin, it appears to be because /snap/bin/microk8s.helm3 is itself a symbolic link to /usr/bin/snap

...
ubuntu@ip-10-42-74-62:~/.local/share/helm/plugins$ ls -al /snap/bin/
total 8
drwxr-xr-x 2 root root 4096 Apr  7 21:49 .
drwxr-xr-x 7 root root 4096 Apr  7 21:49 ..
lrwxrwxrwx 1 root root   13 Apr  7 20:02 amazon-ssm-agent.ssm-cli -> /usr/bin/snap
lrwxrwxrwx 1 root root   13 Apr  7 20:07 microk8s -> /usr/bin/snap
lrwxrwxrwx 1 root root   13 Apr  7 20:07 microk8s.add-node -> /usr/bin/snap
lrwxrwxrwx 1 root root   13 Apr  7 20:07 microk8s.cilium -> /usr/bin/snap
lrwxrwxrwx 1 root root   13 Apr  7 20:07 microk8s.config -> /usr/bin/snap
lrwxrwxrwx 1 root root   13 Apr  7 20:07 microk8s.ctr -> /usr/bin/snap
lrwxrwxrwx 1 root root   13 Apr  7 20:07 microk8s.disable -> /usr/bin/snap
lrwxrwxrwx 1 root root   13 Apr  7 20:07 microk8s.enable -> /usr/bin/snap
lrwxrwxrwx 1 root root   13 Apr  7 20:07 microk8s.helm -> /usr/bin/snap
lrwxrwxrwx 1 root root   13 Apr  7 20:07 microk8s.helm3 -> /usr/bin/snap
...

When I invoke /snap/bin/microk8s.helm3 in my normal interactive bash, it gives me the microk8s.helm3 output as expected. What is going on here? I appear to be missing something about something invisible that makes microk8s.helm3 work when invoked as /snap/bin/microk8s.helm3, but not when invoked through a symlink? Thanks for any input.

try snap alias:

$ snap alias --help
Usage:
  snap alias [alias-OPTIONS] [<snap.app>] [<alias>]

The alias command aliases the given snap application to the given alias.

Once this manual alias is setup the respective application command can be
invoked just using the alias.

[alias command options]
      --no-wait       Do not wait for the operation to finish but just print the change id.
2 Likes

Thank you, that seems to have gotten me a bit further. I apologize if I’ve used the wrong topic heading, was debating between this and doc. Is there more documentation on why snap alias is necessary, and what is going on with the links in /snap/bin?

The snap programs are indeed symlinks to snap. That said I cannot replicate the error you’re reporting with my own snap:

$ /snap/bin/openfortivpn --version
1.13.3
$ 
$ sudo ln -s /snap/bin/openfortivpn /bin/openfortivpn
$ 
$ /bin/openfortivpn --version
1.13.3
$ 

Note that /snap/bin is usually in your PATH so you shouldn’t need symlinks.

/usr/bin/snap uses the name of the executable that is called to determine what actual command the user wants to run. Your attempt to symlink to a name that snapd doesn’t know about is what causes it to fail to execute: it uses the name of your symlink to look up a snap package command but fails because your symlink’s name is not one it knows about.

The correct solution is as @ogra suggests to use snap alias.

@dimitri, the reason your attempt worked is because you used the same name for your symlink as the actual command that snapd knows about so it has an exact match and can launch the correct command.

3 Likes

Ok, so this is a kind of ‘routing’ to the correct executable or command based on the name that’s been input? Is there a place I can find more documentation about this mechanism? Thanks.

@daniel Indeed:

$ sudo ln -s /snap/bin/openfortivpn /bin/openfortivpn
$ 
$ /bin/openfortivpn --version
1.13.3
$ 
$ sudo ln -s /snap/bin/openfortivpn /bin/some_other_name
$ 
$ /bin/some_other_name --version
snap    2.44.2+20.04
snapd   2.44.2+20.04
series  16
ubuntu  20.04
kernel  5.4.0-21-generic
$ 

It makes sense of course now that you have told us, but this caveat should probably be documented in bold. Is there any way this could be avoided? Wouldn’t it be technically possible to have snap follow symlinks until the last one in /snap/bin and use that symlink to determine which command to run? If it is technically not possible to fix this caveat, it should documented in The snap format.

1 Like

Thanks dimitri, I think more documentation on this would be very much useful. As well as your suggestion to follow links until the last one.