Snap application launchers don't appear in applications menu when using Zsh - How I fixed it

I’m making this topic for anyone else that might find themselves in the same position I was in and not wanting to settle with having to symbolically link snapd .desktop files to their .local/share/applications directory. I’m also hoping the snapd dev team might come across this post and implement a change to solve this issue.

To start off, here’s some of my relevant system specifications:

  • OS: Parrot OS Home (based on Debian Linux)
  • Desktop: Xfce
  • Shell: Z Shell

My issue: After doing a fresh install of Parrot and switching to Z Shell as my default shell, I installed snapd and used it to install the Spotify and VSCode snaps. While I could run these applications from the command line, the application launchers (which I found out were located in the applications folder within the /var/lib/snapd/desktop directory) were not being shown in either of my applications menus.

I’ve spent a few days figuring out exactly why this was occurring and how to go about fixing it, and after reading quite a few different posts on this topic, I finally discovered a fix that didn’t involve me having to put in a script somewhere symbolically linking the .desktop files located in snapd’s desktop directory to my .local/share/applications directory. The applications aren’t shown because Zsh doesn’t use any of the files located in /etc/profile.d/ and so the /etc/profile.d/apps-bin-path.sh file that’s supposed to include /var/lib/snapd/desktop in $XDG_DATA_DIRS (the environment variable that tells the system where to look for these .desktop application files) doesn’t get used. I tried using

emulate sh -c ‘/etc/profile.d/apps-bin-path.sh’

to emulate apps-bin-path.sh file, but for whatever reason (could’ve been because I wasn’t putting it in the right config file, I tried putting it in /etc/zsh/zprofile like one person on a thread suggested but that didn’t do anything) I still wasn’t seeing the snapd applications directory showing up in $XDG_DATA_DIRS when trying that method.

How I fixed this: I came across a thread mentioning a change that was made to take out the 65snappy file that used to be installed in /etc/X11/Xsession.d/ and found the file on github.

Here’s the link: https://github.com/snapcore/snapd/blob/1182f06962bbf96f9923fef9a7f47c4ceac4559e/etc/X11/Xsession.d/65snappy

I then simply created the same file within /etc/X11/Xsession.d/ and pasted the code found in the above link in it. After deleting all my symlinks inside my ~/.local/share/applications directory and restarting the session, the directory was set in XDG_DATA_DIRS and my snap installed applications were showing up (and after installing a new application I wouldn’t have to logout and log back in to have the application appear in my app menu)

I hope this helps anyone else dealing with the same problem. Thanks.

For what it’s worth that file was deleted from snapd with https://github.com/snapcore/snapd/pull/3398, are you suggesting that file should be added back to support Parrot OS?

Well just to be clear, this is only an issue if you change your default shell to Zsh in Parrot OS.

That said, I would like to suggest adding the file back in to support Parrot (and any other distros where this is an issue) that currently don’t have anything adding the /var/lib/snapd/desktop path to XDG_DATA_DIRS if Zsh is set as the default shell instead of bash. I don’t know exactly why it was originally removed, but this has been an issue for those of us using zsh instead of bash for some time now it seems.

So far we use /etc/profile.d/snapd.sh, which works on distros that aren’t too picky about emualting sh in zsh (eg. Arch, Fedora), we also drop a file under /usr/lib/environment.d, which is picked up by the user environment generators when the user session starts up, lastly we rely on display managers eg. gdm to import environment variables from your shell. Flatpak also used /etc/gdm/*.env files, but AFAICT it has been dropped in favor of environment generators.

What is different about Parrot OS or your setup that makes those environment variables not set correctly?

I’m not entirely sure what exactly is different about it… What I can tell you about Parrot OS is it comes with bash as the default shell and uses the mate desktop environment by default, but I use XFCE on mine and switched the default shell to zsh.

From what I’ve read zsh doesn’t source any of the files located in /etc/profile.d/, which is why it doesn’t set the XDG_DATA_DIRS environment variable correctly. I can give you some more detailed specifications of my system if you’d like, just let me know which commands you’d like the output from. I would very much like to find out exactly why this issue is occurring as it was pretty frustrating finally finding a fix for it.

Also I actually don’t have a file named shapd.sh located inside my /etc/profile.d directory, instead I have one called apps-bin-path.sh that seems to be the file snapd added into the directory. Below is the contents of the file:

# shellcheck shell=sh

# Expand $PATH to include the directory where snappy applications go.
snap_bin_path="/snap/bin"
if [ -n "${PATH##*${snap_bin_path}}" -a -n "${PATH##*${snap_bin_path}:*}" ]; then
    export PATH=$PATH:${snap_bin_path}
fi

# Ensure base distro defaults xdg path are set if nothing filed up some
# defaults yet.
if [ -z "$XDG_DATA_DIRS" ]; then
    export XDG_DATA_DIRS="/usr/local/share:/usr/share"
fi

# Desktop files (used by desktop environments within both X11 and Wayland) are
# looked for in XDG_DATA_DIRS; make sure it includes the relevant directory for
# snappy applications' desktop files.
snap_xdg_path="/var/lib/snapd/desktop"
if [ -n "${XDG_DATA_DIRS##*${snap_xdg_path}}" -a -n "${XDG_DATA_DIRS##*${snap_xdg_path}:*}" ]; then
    export XDG_DATA_DIRS="${XDG_DATA_DIRS}:${snap_xdg_path}"
fi

If there’s any information about system that I can provide that might help let me know. Also this is the only environment variable (XDG_DATA_DIRS) that doesn’t get set correctly with snap. From what I’ve been able to gather, it seems the main difference about my setup that makes this environment variable not get set correctly is zsh being the default shell.

I’ve done some more reading and the reason the .sh file for snap in /etc/profile.d isn’t being used is because zsh (for whatever reasons) doesn’t source files in that directory. I did take a look at the file in the /usr/lib/environment.d directory and the snapd.conf file for it is in there, however I don’t know why it isn’t being picked up by zsh. Oh and in case this matters, I am logging in via a graphical login screen to my XFCE desktop. Now I’m trying to figure out whether or not zsh by default picks up any of the files located in /usr/lib/environment.d/ but on my system it doesn’t seem it does. I actually don’t know much about this directory, this is the first time I’ve come across it.

Here’s the output of env in case this might help further track down what is (or isn’t) occurring:

SSH_AUTH_SOCK=/run/user/1000/keyring/ssh
SESSION_MANAGER=local/parrot:@/tmp/.ICE-unix/4479,unix/parrot:/tmp/.ICE-unix/4479
SSH_AGENT_PID=4585
LANG=en_US.UTF-8
NO_AT_BRIDGE=1
XDG_CURRENT_DESKTOP=XFCE
XDG_GREETER_DATA_DIR=/var/lib/lightdm/data/doc
QT_IM_MODULE=fcitx
GPG_AGENT_INFO=/run/user/1000/gnupg/S.gpg-agent:0:1
DESKTOP_SESSION=xfce
USER=doc
XDG_MENU_PREFIX=xfce-
XDG_SESSION_PATH=/org/freedesktop/DisplayManager/Session1
HOME=/home/doc
DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/1000/bus
XDG_VTNR=7
XDG_SEAT=seat0
GTK_MODULES=gail:atk-bridge
XDG_DATA_DIRS=/usr/share/xfce4:/usr/local/share/:/usr/share/:/usr/share
GTK_IM_MODULE=fcitx
XDG_SESSION_DESKTOP=xfce
XDG_CONFIG_DIRS=/etc/xdg
QT_ACCESSIBILITY=1
CLUTTER_IM_MODULE=fcitx
XDG_SEAT_PATH=/org/freedesktop/DisplayManager/Seat0
LOGNAME=doc
VTE_VERSION=6201
PATH=/home/doc/miniconda3/condabin:/home/linuxbrew/.linuxbrew/bin:/home/linuxbrew/.linuxbrew/sbin:/home/doc/bin:/usr/local/bin:usr/share:/snap/bin:/usr/local/bin:/usr/bin:/bin:/usr/local/games:/usr/games
XDG_RUNTIME_DIR=/run/user/1000
XMODIFIERS=@im=fcitx
XDG_SESSION_ID=6
SHELL=/bin/zsh
XDG_SESSION_TYPE=x11
WINDOWID=81788935
PWD=/home/doc
XAUTHORITY=/home/doc/.Xauthority
COLORTERM=truecolor
XDG_SESSION_CLASS=user
GDMSESSION=xfce
TERM=xterm-256color
DISPLAY=:0.0
SHLVL=1
OLDPWD=/home/doc
ZDOTDIR=/home/doc/.config/zsh
ZSH=/home/doc/.config/zsh/.oh-my-zsh
HOMEBREW_PREFIX=/home/linuxbrew/.linuxbrew
HOMEBREW_CELLAR=/home/linuxbrew/.linuxbrew/Cellar
HOMEBREW_REPOSITORY=/home/linuxbrew/.linuxbrew/Homebrew
MANPATH=/home/linuxbrew/.linuxbrew/share/man::
INFOPATH=/home/linuxbrew/.linuxbrew/share/info:
LDFLAGS=-L/home/linuxbrew/.linuxbrew/opt/isl@0.18/lib
CPPFLAGS=-I/home/linuxbrew/.linuxbrew/opt/isl@0.18/include
PKG_CONFIG_PATH=/home/linuxbrew/.linuxbrew/opt/isl@0.18/lib/pkgconfig
EDITOR=nvim
PAGER=less
LESS=-R
LSCOLORS=Gxfxcxdxbxegedabagacad
LS_COLORS=(I've deleted the output of LS_COLORS as I only see it as being an annoying block of text in this context)
AUTOJUMP_SOURCED=1
AUTOJUMP_ERROR_PATH=/home/doc/.local/share/autojump/errors.log
MARKPATH=/home/doc/.marks
CONDA_EXE=/home/doc/miniconda3/bin/conda
_CE_M=
_CE_CONDA=
CONDA_PYTHON_EXE=/home/doc/miniconda3/bin/python
CONDA_SHLVL=0
P9K_SSH=0
P9K_TTY=old
_P9K_TTY=/dev/pts/0
_=/usr/bin/env

EDIT: I wasn’t having any luck getting my system to use the /usr/lib/environment.d/990-snapd.conf file, even though when I used the systemd generator to generate environment variables it would show that it sets the required environment variable, for whatever reason it still doesn’t get set during login. I ended up just renaming 990-snapd.conf to 990-snapd and moving it to /etc/X11/Xsession.d/, as this is the one directory that I know Parrot uses.

I believe it would be worth looking into possibly including a file within /etc/X11/Xsession.d/ for this purpose, as it definitely sets the XDG_DATA_DIRS environment variable correctly for Parrot, in my case at least.

Not sure how you got that file, but AFAICT this file isn’t part of snapd since 2.28 which was released back in 2017. What is the version of snapd package provided by your distro?

TBH it’s up to the maintainer of your distro to have zsh source files from /etc/profile.d. It is done like this on Arch and Fedora AFAIK.

This is done by systemd user session manager, which sets that in its environment and all child processes it spawns.

The version provided by my distro is 2.45.2-1

I understand, also I appreciate the information about the systemd user session manager, I didn’t know about any of that previously. I’m still somewhat new to Linux in general, being someone that’s used Windows systems primarily for most of my life up until I completely switched to Linux last year.

I’ll see about bringing up this issue on the forums for Parrot or something like that. Hopefully in the meantime this thread will help others having similar issues to the one I had.

Okay so, just an update, after looking into this problem again and looking deeper into how those systemd generators work, I found that the issue is the snapd.service not being enabled and starting. After I enabled and started it I had things set correctly.

This is weird, the user environment generator (systemd-environment-d-generator, part of system) is unrelated to snapd, and its only purpose is to pick up files frim /usr/lib/environment.d and add values from those files to the environment. Similarly /etc/profile.d/snapd.sh (though that as we already concluded is not used for zsh in your distro). There’s one more generator at /usr/lib/systemd/system-environment-generators/snapd-env-generator which is only invoked for system services and does not care whether snapd service is active. Your session is not a system service, so that generator isn’t called there either.

I spoke too soon when I stated the issue was the snapd.service… I had been doing some looking into on systemd and the environment generators you’d mentioned and something (can’t’ remember what if I’m being honest) had me thinking the service had something to do with why XDG_DATA_DIRS wasn’t being set. I’d actually found a file in my /etc/X11/Xsession.d directory that I’d forgotten to delete (and forgot about) that had solved the issue when I posted that. So my apologies for that. AFAIK the service was already enabled and set up to run in the first place.
I did have to do a completely fresh install of Parrot and set up my Parrot desktop environment again recently, due to upgrading a kernel image without realizing I didn’t also install the corresponding headers package (couldn’t install the package because a linux-compiler-gcc-10-x86 package wasn’t obtainable from the parrot repos, but I’m getting off track here)

As a result of having to install Parrot, and then snapd again, I started looking into this issue again.
I found the same problems I talked about in my first post; that the snap-installed application launchers were appearing when the default shell was bash, but after changing my default shell to zsh, they were no longer appearing, at least part of the reason for that being that the snap application path was not being set in XDG_DATA_DIRS.

I did try copying the /usr/lib/environment.d/990-snapd.conf file to /etc/environment.d/ and this DID end up showing the snap app launcher path in XDG_DATA_DIRS but I still wasn’t seeing any of my snap applications appearing in my application menus. I feel like this might be because it ends up being added to the XDG variable too late or at the wrong time (or something like that), but I don’t really know what it is. When I copied the 990-snapd.conf file to /etc/X11/Xsession.d/ I did have snap applications showing in my application menus.

In short, after installing Parrot again and having to get the snap application launchers appearing in whiskermenu within XFCE4, I placed a file in the /etc/X11/Xsession.d directory adding the /var/lib/snapd/desktop path to XDG_DATA_DIRS and the launchers were appearing in my application menus again.

I still believe that having a file (like 65snappy before it was removed) in /etc/X11/Xsession.d would be a good idea, at least for Parrot OS.