1

Following Situation I need to setup the DISPLAY Variable for my WSL2 to transmit goutput to the Xserver running on my Host-System.

In general I would do this by using my .bashrc:

export DISPLAY=$(ip route list default | awk '{print $3}'):0

So I started by setting the DISPLAY Variable with

set -Ux DISPLAY $(ip route list default | awk '{print $3}'):0

which worked in the first place.

The Issue: The Variable is now set inside .config/fish/fish_variables as SETUVAR --export DISPLAY:<MY-IP>:0

Seems fine for the moment but since my Homenet uses DHCP it might happen that my IP is changing. How do I set the variable by calling the top used command?

MaKaNu
  • 762
  • 8
  • 25

2 Answers2

1

Your mistake was using set -U. That creates a "universal" variable. Instead, simply do set -x in your ~/.config/fish/config.fish so the var is created every time you start a fish shell. See also https://fishshell.com/docs/current/faq.html#why-doesn-t-set-ux-exported-universal-variables-seem-to-work. Universal variables shouldn't be used for values that can change each time you start a fish shell or that might be different for concurrently running shells.

Kurtis Rader
  • 6,734
  • 13
  • 20
  • Than I missunderstood this question: https://stackoverflow.com/questions/25632846/how-to-set-environment-variables-in-fish-shell – MaKaNu Aug 07 '22 at 14:48
  • @MaKaNu: The most popular answer to that question is awful. You should never use `set -Ux`. When I was using, and contributing changes to, the Fish shell I argued that combination should be an error. I lost that argument. Sigh. – Kurtis Rader Aug 08 '22 at 00:23
  • Can you Explain why you think this combination should not be used? I am still not that confident with fish, so I do not understand every idea. So from what I understand `-x` is the equivallent of `export` and `-U` is used for Unversal Vars. I dont grasp completly what this means and what the difference to `-g` is. – MaKaNu Aug 08 '22 at 23:47
  • 1
    @MaKaNu: A Fish universal variable is one whose value is automatically propagated to every other Fish shell instance when you change it in a particular shell instance. This is fine for something like the variables that define the color theme. It is rarely (probably never) the behavior you want for env vars. A lot of people will say that they want any change `PATH` to be automatically reflected in all their Fish shell instances. No, you do not. For example, you may have a virtual environment (aka a "venv") enabled in on of those shells. That wouldn't work if `PATH` was a universal var. – Kurtis Rader Aug 09 '22 at 01:12
  • I would say it differently than @KurtisRader. Universal variables cannot be blindly exported without fully understanding how they interact with the shell. The use of an exported universal in this case doesn't work, as explained in both answers, because the universal stays constant even when the IP address changes. But I tend to side with the current Fish maintainers that `-Ux` is an extremely useful and safe construct *when used properly*. For universals that remain fairly constant, there's no issue, which is why using the mDNS *name* will work as a universal `DISPLAY`. – NotTheDr01ds Aug 11 '22 at 19:32
  • @NotTheDr01ds: What in the heck does "remain fairly constant" mean? I think the Fish maintainers are wrong in allowing `set -Ux`. And I say that as someone who contributed significant changes to Fish for several years; such as the `getopts` command. There are, theoretically, valid uses of `set -Ux` but I've never seen an actual case where it was appropriate. In other words, the mechanism is a ["foot gun"](https://en.wiktionary.org/wiki/footgun). – Kurtis Rader Aug 12 '22 at 02:36
  • @KurtisRader My point is that `DISPLAY` is a prime example of an appropriate case. `DISPLAY` is a "fairly constant" variable when using a DNS name -- The only time you would need to change it would be when the hostname itself changes, which should be a rare (if ever) occurrence. When that happens, regardless of whether you've set it as a global (in `config.fish`) or a universal, you're going to have remember to manually change it. Even for most users, `set -Ux DISPLAY :0` would work quite well - It's just the WSL2 virtual switch between it and Windows that makes it problematic here. – NotTheDr01ds Aug 12 '22 at 05:26
  • On the other hand, I absolutely I agree with you that [this question](https://stackoverflow.com/q/25632846/11810933) was the *wrong* place to suggest universals. I'm probably going to write my own answer there to that effect. – NotTheDr01ds Aug 12 '22 at 05:28
1

Kurtis's answer would normally be correct, but this is WSL2, and there's (IMHO) a better solution on WSL2 that can use fish universal variables.

set -Ux DISPLAY (hostname).local:0

As long as the hostname matches the Windows Computer Name (which it should and does by default), then that will always use mDNS to return the correct address, even if the IP has changed.

Note that you'll need to remove the global variable definition from ~/.config/fish/config.fish or else the universal will be shadowed by the global.

Explanation:

You might think that it is the dynamically assigned DHCP address changing that is causing the problem, but that's not actually it. The IP address that you get back from ip route list default | awk '{print $3}' is not the one that is assigned to Windows by DHCP on your home network.

It's actually the address of a virtual switch provided by WSL2 that allows WSL2 to communicate with the Windows host (and beyond).

When the Windows IP address changes, it doesn't matter to this virtual switch. Side note: I just confirmed this to make sure on WSL2 by changing my Windows IP manually.

The problem here is actually that the switch address changes each time the computer (or WSL2) restarts. This is why most instructions for setting your DISPLAY on WSL2 tell you to map it to this address, rather than hardcoding it.

As Kurtis said, however, this type of assignment would (typically) be a problem if you were using a fish universal variable, since the virtual switch IP does change each reboot.

But WSL2 provides a convenient mDNS lookup for the address, in the form of <computername>.local. By hardcoding that into the universal variable, DISPLAY should always resolve correctly, even after the IP address itself changes.

NotTheDr01ds
  • 15,620
  • 5
  • 44
  • 70
  • That won't work if you ssh into the WSL instance and use X11 forwarding. Again, using `-U` with `-x` is almost always the wrong thing to do. – Kurtis Rader Aug 09 '22 at 00:58
  • @KurtisRader It works just fine when you SSH into WSL2 and use X11 forwarding, and I've tested to confirm. `ssh -X` sets the forwarding `DISPLAY` variable as usual, which means it is a global that shadows the universal inside the SSH session. Do you have any other corner cases you'd like for me to test? – NotTheDr01ds Aug 09 '22 at 14:27
  • @NotTheDroids: Yes, that is true but it is a subtlety that most Fish users won't understand. At least not until they have been been bitten by the subtlety more than once. This is a ["foot gun"](https://en.wiktionary.org/wiki/footgun). I expect to die before someone shows me a valid use of `set -Ux`. That is, a use that isn't likely to cause surprising behavior to a typical, not expert, Fish user. – Kurtis Rader Aug 12 '22 at 02:53