2

Context

I am currently trying to setup Windows Subsystem 2 for Linux in my Windows 10 Pro OS. After downloading Ubuntu 20.04 LTS from the Microsoft store, installing it, and creating my user profile, I started wondering how I could run and use all the Ubuntu programs that have a graphical interface. I then discovered Xming, which allowed me to establish a connection between my Windows OS and the Ubuntu kernel via IP: everything works fine, except for the fact that since there is no way to set a static IP for the WSL virtual ethernet card, every time I restart my PC I have to check and change the address to which I want to connect. I am currently doing this by editing each time my .bashrc file, and adding a line like

export DISPLAY=172.29.112.1:0.0

which corresponds to the IP I have listed in the IPv4 sub-section of the WSL web configuration. I obtained it by running

ipconfig

inside a PowerShell/Windows terminal. The two zeroes I added to the IP are the ports requested by Xming, (and also, indirectly, the cause of my problem).

My idea has been to try and automate all this process, so that every time I boot my PC I just have to launch Xming and Ubuntu.

Issue description

The problem is that I had close to zero knowledge about terminal syntax, so I managed to come up with just a partial solution: I managed to automatically load the correct IP, but I cannot append the ports without deleting part of the IP itself. This is what I came up with so far:

export DISPLAY=$(/mnt/c/Windows/System32/ipconfig.exe | grep IPv4 | cut -d: -f2 | awk '{print $1}' | awk 'END{print}')

This line, added to my .bashrc, allows me to get the correct IPv4, which happens to always be the one at the end of the list (hence the second awk call). It invokes the same ipconfig one uses inside Windows, so that I can obtain the desired address. I studied a bit how this syntax works and found some interesting solutions to the next problem, i.e. attaching the ':0.0' at the end of the query above. One, for instance, is this. Unfortunately, even if replicating that solution works fine with normal strings, it seems like my IP address is stored as a different kind of variable, or at least it behaves differently: trying to apply that same concept makes so that the initial portion of my IP gets overwritten.

What I want

A (possibly) one-line formula like the one I made, but which also incorporates the ports at the end, without overwriting any of the IP's digits. In any case, the DISPLAY variable assigned in the .bashrc must be of the same type of the current one I have with my partial implementation, as I need it to be read by Xming, or any other program. I would also appreciate some explanations about the solution and about the reason of the overwriting phenomenon I described.

What I have tried so far

I have devoted all the afternoon to this issue, starting from learning a little bit of the syntax of the Ubuntu terminal, as well as trying to find examples of sed and awk, among other functions. I also tried many slightly altered versions of my query in order to fit in the ports, but all these tries only yielded syntax errors or the same overwriting effect described above.

Why I am asking this

Given that I expect this to take me probably a little while to solve, and that I am confident this should not be time-consuming at all for anybody with some experience in the field, I hope to receive some help.

Thank you!

Update

After several tries, it turns out that the WSL IP sub-category could indeed be listed in a different position than last. I thought the entries would follow the alphabetical order, but it is clear now that that was just a coincidence.
Thus, if I have something like this: WSL IP sub-section

I now have the need to actually grep this precise portion of the ipconfig output, rather than blindly picking the last of the list as I have been doing until now. I have tried to wrap my head around your solutions, and with some further research I managed to find a way to make it work regardless of the postioning:

export DISPLAY=$(/mnt/c/Windows/System32/ipconfig.exe | awk '/WSL/{getline; getline; getline; getline; print}' | grep IPv4 | cut -d: -f2 | tail -n1 | sed 's/\r//g' | awk 'END {print($1":0.0");}')

obtained attaching @Zilog80 formula. What I understood is that getline should read and ignore the current line and move to the next one, so by doing that 4 times I could apply the rest of the formula to the line I was originally interested in. There are surely better ways to do it, but I can confirm that this is pretty reliable, even if not elegant. Looking forward to see your suggestion/improvements also for this update.

ps I removed part of the IPv6 as I am not aware if that is sensible information; sorry if that was not the case.

Jetboy
  • 129
  • 8
  • Can you create a bash script that collects the information you need in separate variables and then combines them into one variable? Then you'd just need to run one command to run the script. – wxz Mar 29 '21 at 20:41
  • 1
    @wxz This could be an idea, albeit having a one-line solution would be more elegant. And I assume I would have the same problem with the "data type". Update: I tried one of the answers and it worked, so no problem anymore I guess. Thank you also for your help! :) – Jetboy Mar 29 '21 at 21:00
  • Doesn't `DISPLAY=:0.0` just work? – Diego Torres Milano Apr 21 '21 at 23:16
  • As far as I remember, that was one of the first things I tried, with no success edit: anyway it's been a month since this issue, so I could be racalling wrong. Maybe I'll try again when I get back working over Windows – Jetboy Apr 22 '21 at 13:45
  • @DiegoTorresMilano I can confirm that `DISPLAY=:0.0` does not work, at least for me. – Jetboy Apr 23 '21 at 15:12
  • @Jetboy and what about `DISPLAY=localhost:0.0` ? – Diego Torres Milano Apr 23 '21 at 23:46
  • @DiegoTorresMilano I just tried that too, and I can confirm that it does not work. If I restore my awk query and re-source my .bashrc, everything is fine again. – Jetboy Apr 25 '21 at 10:00

3 Answers3

3

The issue you have come from the fact that you're are launching ipconfig.exe, a windows tools for ip adapters, which output with Windows line terminators (CR+LF). That drives AWK to keep the CR in the output, thus overwriting.

To prevent that, filter the damn CR with the sed utility, which permits to remove the troubling CR (\r) :

export DISPLAY=$(/mnt/c/Windows/System32/ipconfig.exe | grep IPv4 | cut -d: -f2 | tail -n1 | sed 's/\r//g' | awk 'END {print($1":0.0");}')

As @Ed Morton suggested, it may be useful to let know that all your command can be done with AWK only :

export DISPLAY=$(/mnt/c/Windows/System32/ipconfig.exe | awk -F\: '/IPv4/{adr=$NF}END{sub(/\r$/,"",adr); print adr":0:0"}')
Zilog80
  • 2,534
  • 2
  • 15
  • 20
  • Thank you! this worked flawlessly! I would have never figured out the line terminators issue. I see there are many ways to do this, I'll try to wrap my head around all these different versions. Also, would anyone mind to give me some links where to actually get some grasps of how to exploit these bash functions? Thank you again! – Jetboy Mar 29 '21 at 21:06
  • 2
    lack of terminology is surely part of my issues - I am trying to do stuff without adequate prior studies. I am doing this as I have faced many different issues in many "fields" in these days (working for thesis/exams), and studying everything "how it should be done" would take me too much time. Nonetheless, I found this particular gray (black) area I had to be particularly interesting - as well as serious, I assume. Thank you for also correcting my lexicon – Jetboy Mar 29 '21 at 21:23
  • 1
    No worries, people with years of experience say Linux when they mean Unix, bash when they mean shell, bash when they mean Unix, bash when they mean awk, refer to some non-existent sed/awk, etc. It takes a bit of getting used to but once you understand the differences using the appropriate tools for each task becomes much simpler! – Ed Morton Mar 29 '21 at 21:26
  • 1
    @EdMorton Updated with your suggest. I must admit i'm always tempted to kill every possible CR. – Zilog80 Mar 29 '21 at 21:28
  • @Zilog80 that corrupts your data though. If your data contains mid-line `\r`s then they are there for a reason, just like any other character. If it only contains undesirable line-ending `\r`s then `sub(/\r$/,"")` will remove them. If you want to remove all mid-line control characters then you'd use `gsub(/[[:cntrl:]]/," ")` or similar to replace them with blanks instead of removing them and concatenating the strings around them. There's no reason to assume `gsub(/\r/,"")` would be a better approach than `sub(/\r$/,"")` for just removing DOS line endings AFAIK. – Ed Morton Mar 29 '21 at 21:31
  • @EdMorton I agree, output can contain non line ending CR (ANSI sequence, etc.). I'm simply too much used with data migration from Windows system, data where you'll never find ANSI sequences. (which could change, with ANSI support in W10) – Zilog80 Mar 29 '21 at 21:34
  • @Jetboy If you're using WSL2, you can't use localhost for the IP, but you can get the binding IP of the running Xming Server. Two ways, the easy = get the binding ip from Xming log, the less easy but interesting = get the process instance of the running Xming through wmic or tasklist and then get the binding IPs from the process through netstat/wmic. Not so simple than parsing ipconfig output, but more reliable ^^ – Zilog80 Mar 29 '21 at 22:17
3

Here's a shorter one-liner leveraging @Zilog80's point about the carriage return:

export DISPLAY=$(/mnt/c/Windows/System32/ipconfig.exe| awk '/IPv4/ {addr=$NF} END {printf "%.*s:0.0", length(addr)-1, addr}')

This searches for the lines that have "IPv4" embedded in them and captures the last whitespace-delimited item on the line. At the end, it prints it out, restricting the string to the first length-1 characters (which deletes the carriage return).

Vercingatorix
  • 1,838
  • 1
  • 13
  • 22
2

Sorry, I haven't read all parts, only your issue description and "what I want". This should help you:

export DISPLAY=$(/mnt/c/Windows/System32/ipconfig.exe | sed 's/\r$//' | awk '/IPv4/{ip=$NF}END{print ip ":0:0"}')
  • Your windows command gives DOS line endings. I convert them with sed.
  • awk stores the last field of all lines containing IPv4 in the variable ip which gets printed in the end.
  • awk can concatenate strings: print ip ":0:0"

P. S.: Don't forget to replace the previously appended line in your .bashrc.

steffen
  • 16,138
  • 4
  • 42
  • 81
  • Thank you, your answer was helpful too. In the end I gave the tick to @Zilog80 just because he had answered half a second earlier. If I could, I would equally split all the points and the glory of being "chosen". Thank you again! – Jetboy Mar 29 '21 at 21:09