Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

No line-drawing characters on kubectl exec session to Ubuntu #1519

Closed
kierenj opened this issue Nov 21, 2021 · 41 comments
Closed

No line-drawing characters on kubectl exec session to Ubuntu #1519

kierenj opened this issue Nov 21, 2021 · 41 comments

Comments

@kierenj
Copy link

kierenj commented Nov 21, 2021

Windows, and WSL (Ubuntu) work great:

image

When I connect to a container running on Kubernetes, on Linux (via kubectl exec -it MYPOD -n MYNAMESPACE -c MYCONTAINER -- /bin/bash), all looks grey at first:

image

Then I discovered it's because TERM defaults to xterm. When export TERM=xterm-256color, I get this:

image

Compared to the first image, there's definitely no line-drawing characters.. but also maybe the bright white colour isn't there either?

I'm using Windows Terminal, which apparently aims for xterm-256color support.. and well, it works with WSL/Ubuntu with TERM=xterm-256color. I also tried just Windows PowerShell, which looks the same.

I also tried export LANG=en_US.UTF-8, or export NCURSES_NO_UTF8_ACS=1, both with no effect.

I've tried using other apps / writing general .NET code... k9s can render lines ok. Colour and emojis work fine with other apps.

I'm not sure if this is a gui.cs issue, but since other apps can render stuff ok, I thought I'd check in here. Maybe someone knows something else I could try? Thanks!

(Couldn't be anything to do with 356b0f8 could it?)

@tznind
Copy link
Collaborator

tznind commented Nov 21, 2021

Hey. Thanks for creating this issue. Are you able to replicate the issue using UICatalog demo app (in this repo).

git clone https://github.com/migueldeicaza/gui.cs.git
cd gui.cs
cd UICatalog
dotnet run

Also worth trying with Application.UseSystemConsole = true;. You can pass -usc to UICatalog to switch to that Driver (i.e. dotnet run -- -usc).

I'm not sure I can help with the actual issue but this might be a workaround for now? Either way adding support to your app for this switch could help with flexibility of deployments.

@kierenj
Copy link
Author

kierenj commented Nov 21, 2021

Thanks for the quick reply!

UICatalog - defaults:

image

Tried to find out how to exit the app.. Ctrl+C didn't do it. After a while it seemed to hang. I saw Ctrl+Q to quit but that didn't work by that point either.

Then I had to kubectl exec into the container again, get a new shell.

export TERM=xterm-256color:

image

And finally -usc:

image

Ok, finally-finally, here's -usc with export TERM=xterm (i.e. the original):

image

That's great, so it can work! I can probably workaround this way. But on Windows, the UseSystemConsole route was visibly slow to paint, and mouse controls are a little funky sometimes (hard to quantify that objectively, sorry!). It's also going to be a little tricky to detect this combination and know to use UseSystemConsole.

It does look like there may be an issue with CursesDriver? Anything I can do to diagnose/help?

@tznind
Copy link
Collaborator

tznind commented Nov 21, 2021

Thanks for testing this out! Glad that usc is working. But yeah it is very slow on Windows. I make it a command line switch to my app rather than trying to detect the environment but that is a bit cryptic from user perspective.

I'll let @BDisp respond on the actual issue as I don't know the low level stuff.

@BDisp
Copy link
Collaborator

BDisp commented Nov 21, 2021

Maybe playing around:

static public int LC_ALL { get; private set; }
static Curses ()
{
	LC_ALL = System.Runtime.InteropServices.RuntimeInformation.IsOSPlatform (System.Runtime.InteropServices.OSPlatform.OSX) ? 0 : 6;
}

@kierenj
Copy link
Author

kierenj commented Nov 22, 2021

I found that in the version I'm using (along with a reference to #949). Is there something specifc I can try changing it to?

@BDisp
Copy link
Collaborator

BDisp commented Nov 22, 2021

(Couldn't be anything to do with 356b0f8 could it?)

No. Since these runes was added to the ConsoleDriver abstract class, errors come up because the values in Curses is bigger than the MaxRune that is 0x10FFFF.

I found that in the version I'm using (along with a reference to #949). Is there something specifc I can try changing it to?

Try changing that values between 0 to 6. But I think it's something with a lack of font. I never tried run on Kubernetes. So, if it's not very difficult to configure I could try to see what going on.

@kierenj
Copy link
Author

kierenj commented Nov 22, 2021

It's a big of an undertaking to get going with Kubernetes! I'm going to create a DigitalOcean droplet and try to repro it there, I think it'll be a general Linux issue

@BDisp
Copy link
Collaborator

BDisp commented Nov 22, 2021

Try this #949 (comment) as last resource. Change int to InPtr.

@kierenj
Copy link
Author

kierenj commented Nov 22, 2021

Ok... sshing to a regular Ubuntu VM, it all works:

image

So it's either something to do with:

  • Kuberentes
  • Docker
  • The specific OS version/setup in my container

I'll try to find a way to ssh into the same container environment, to rule out the 3rd one.

@BDisp
Copy link
Collaborator

BDisp commented Nov 22, 2021

Believe me, I could never run on a functional terminal with WSL or Docker directly by the Visual Studio 2019 or 2022 (there is no great visual). I only can do it with Visual Studio Code.

@kierenj
Copy link
Author

kierenj commented Nov 22, 2021

Ok cool, I managed to set up an ssh server, create a user, forward port 22 and SSH into the container.

image

So it's not docker exec or kubectl exec that's doing anything.. it's something to do with the specific setup of that Linux environment. Any info I can share to help?

@BDisp
Copy link
Collaborator

BDisp commented Nov 22, 2021

Do you can use another Linux image into the Kubernetes?

@kierenj
Copy link
Author

kierenj commented Nov 22, 2021

  • IntPtr for setlocale had no effect
  • Swapping 0 and 6 for LC_ALL had no effect

Edit: discovered that the default .NET Core docker images use Debian 10, not Ubuntu. I created another VM with Debian 10, which worked. So we have:

Working: Windows, Ubuntu on WSL, Ubuntu VM, Debian 10 VM
Not working: dotnet/aspnet:5.0 Docker image on Kubernetes (based on Debian 10 slim) via kubectl exec or ssh

Will try an Ubuntu-based Docker image on Kubernetes later today.

@kierenj
Copy link
Author

kierenj commented Nov 22, 2021

Both Debian and Ubuntu variants of the dotnet/aspnet 5.0 images have this same issue.

Repro steps below - note, not using Kubernetes, just Docker.

Debian: docker run -it mcr.microsoft.com/dotnet/aspnet:5.0 /bin/bash
Ubuntu: docker run -it mcr.microsoft.com/dotnet/aspnet:5.0-focal /bin/bash

Ubuntu (general, not Microsoft image): docker run -it ubuntu /bin/bash - also fails

Setup within container for the above:

apt-get update
apt-get install -y git
apt-get install -y wget
wget https://packages.microsoft.com/config/debian/10/packages-microsoft-prod.deb -O packages-microsoft-prod.deb
dpkg -i packages-microsoft-prod.deb
rm packages-microsoft-prod.deb
apt-get update
apt-get install -y apt-transport-https
apt-get update
apt-get install -y dotnet-sdk-5.0

git clone https://github.com/migueldeicaza/gui.cs.git
cd gui.cs
cd UICatalog

export TERM=xterm-256color
dotnet run

I also tried Alpine: docker run -it mcr.microsoft.com/dotnet/sdk:5.0-alpine sh

This one comes with SDK installed, so just apk add git then git clone etc...

But gives:

Curses failed to initialize, the exception is: System.EntryPointNotFoundException: Unable to find an entry point named 'dlopen' in shared library 'libcoreclr.so'.
  at Unix.Terminal.UnmanagedLibrary.CoreCLR.dlopen(String filename, Int32 flags)
  at Unix.Terminal.UnmanagedLibrary.PlatformSpecificLoadLibrary(String libraryPath) in /gui.cs/Terminal.Gui/ConsoleDrivers/CursesDriver/UnmanagedLibrary.cs:line 189
  at Unix.Terminal.UnmanagedLibrary..ctor(String[] libraryPathAlternatives, Boolean isFullPath) in /gui.cs/Terminal.Gui/ConsoleDrivers/CursesDriver/UnmanagedLibrary.cs:line 113
  at Unix.Terminal.Curses.LoadMethods() in /gui.cs/Terminal.Gui/ConsoleDrivers/CursesDriver/binding.cs:line 86
   at Unix.Terminal.Curses.FindNCurses() in /gui.cs/Terminal.Gui/ConsoleDrivers/CursesDriver/binding.cs:line 92
   at Unix.Terminal.Curses.initscr() in /gui.cs/Terminal.Gui/ConsoleDrivers/CursesDriver/binding.cs:line 104
etc

@BDisp
Copy link
Collaborator

BDisp commented Nov 22, 2021

Since is Ubuntu I only changed to wget https://packages.microsoft.com/config/ubuntu/20.04/packages-microsoft-prod.deb -O packages-microsoft-prod.deb
I confirm the issue on Ubuntu. Is possible to debug with this image? Maybe installing openssh-server? What do you recommend?

@kierenj
Copy link
Author

kierenj commented Nov 22, 2021

I can try to set up a VM with remote access, Rider or VS Code etc, to debug. I'll try it later :) Then I can share access to that VM, maybe

@BDisp
Copy link
Collaborator

BDisp commented Nov 22, 2021

I'm already debugging using the VSCode remote containers. All the border characters appear fine on watch when debugging but the ncurses don't print them. I think the font used by the image doesn't contains these characters, but I don't know how to check that.

@BDisp
Copy link
Collaborator

BDisp commented Nov 22, 2021

I got it running with borders adding the following:

apt-get install -y locales && \
locale-gen en_US.UTF-8 && \
export LANG=en_US.UTF-8 && \
export LANGUAGE=en_US:en && \
export LC_ALL=en_US.UTF-8 && \

About Alpine and due the error, it seems the ncurses doesn't have the correct version.

@kierenj
Copy link
Author

kierenj commented Nov 23, 2021

That’s great! Can I ask how you found that out, or any more information around the problem? I’m wondering if it’s something I can programmatically detect etc. thanks 🙂

@BDisp
Copy link
Collaborator

BDisp commented Nov 23, 2021

One of the information I saw was here https://stackoverflow.com/questions/28405902/how-to-set-the-locale-inside-a-debian-ubuntu-docker-container.

The best workaround I used was:


	apt-get install -y locales && \
	sed -i -e 's/# en_US.UTF-8 UTF-8/en_US.UTF-8 UTF-8/' /etc/locale.gen && \
    dpkg-reconfigure --frontend=noninteractive locales && \
    update-locale LANG=en_US.UTF-8
ENV LANG=en_US.UTF-8 \
	TERM=xterm-256color

I would like to know if is possible to debug from Visual Studio 2019 or 2022, opening in interactive mode on a terminal, like the VSCode does. Thanks.

@leomoty
Copy link

leomoty commented Nov 23, 2021

You actually can debug binaries inside containers:

Debug > Attach to Process:

Connection Type: Docker (Linux Containers)
Connection Target: either use the combobox or press find, at least for me, find is more reliable

image

@leomoty
Copy link

leomoty commented Nov 23, 2021

Just remembered, there is also this:

https://docs.microsoft.com/en-us/dotnet/architecture/containerized-lifecycle/design-develop-containerized-apps/visual-studio-tools-for-docker

Which can play nice with docker-compose and then you can start debugging directly through VS.

My previous example might need something like while(!Debugger.IsAttached) to be able to catch early initialization

@BDisp
Copy link
Collaborator

BDisp commented Nov 23, 2021

Thanks, I know attaching is possible and I use it very much after launch the application and to catch early I have to use the following, as is in the Application.cs.

// Used only for start debugging on Unix.
#if DEBUG
			while (!System.Diagnostics.Debugger.IsAttached) {
				System.Threading.Thread.Sleep (100);
			}
			System.Diagnostics.Debugger.Break ();
#endif

Thanks for the link. I'll study very carefully. I realy prefer the concept in the docker-compose but without adding a Dockerfile in each project. I prefer having a common image for all projects with a configuration to run the select project. Is more and less the .devcontainer in VSCode. I hope this is possible.

@leomoty
Copy link

leomoty commented Nov 23, 2021

So i'll keep using the example from my previous issue, if you run something like this:

  1. Uncomment that debugging block
  2. Build the UICatalog with debug configuration
  3. Lets use your devcontainer, I am using net5.0 shouldnt change for 6.0:
 docker run -v $pwd/bin/Debug/net5.0:/app `
-it `
-e "TERM=xterm-256color" `
--name uicatalog `
mcr.microsoft.com/vscode/devcontainers/dotnet:5.0 dotnet /app/UICatalog.dll
  1. You should be a blinking cursor, as it should be in that while loop
  2. Go back to VS, open Terminal.Gui solution
  3. Menu > Debug > Attach to Process
  4. Select Connection Type => Docker (Linux Containers), under Connection Target => press Find
  5. CLI Host should remain Local Machine, below pick 'uicatalog'
  6. select which process, should only have UICatalog.dll, press attach, tick Managed

Should reach the breakpoint as expected inside the container:

image

@leomoty
Copy link

leomoty commented Nov 23, 2021

Also shouldn't need a Dockerfile to convert that to a docker-compose, let me know if you would accept a PR and I can try to take a stab at it

@BDisp
Copy link
Collaborator

BDisp commented Nov 23, 2021

@leomoty, personally I would like to know how do you configure the docker-compose without a Dockerfile, although I'll try to find a way to do a script to start debugging without a while(!Debugger.IsAttached).
Sorry but it's not up to me to decide if I accept or not a PR, because I'm just a contributor. But it would be great to have an alternative to make remote debug for Visual Studio 2019 or 2022, just like VSCode already does.

@BDisp
Copy link
Collaborator

BDisp commented Nov 23, 2021

@leomoty you must set the locale into the container to be able to see vertical and horizontal lines, as also some glyphs. See the comments above.

@leomoty
Copy link

leomoty commented Nov 23, 2021

So I spent a lot of time trying to get this to work inside VS, turns out it doesn't, even if you add the relevant bits that match -it (stdin_open and tty) you won't get a terminal, thus it won't start. Even running with docker-compose up is kinda spotty and doesn't start the UI properly.

Added the lang bits you mentioned and glyphs appear properly. This command works:

 docker run -v $pwd/bin/Debug/net5.0:/app `
-it `
-e "TERM=xterm-256color" `
-e "LANG=en_US.UTF-8" `
--name uicatalog `
mcr.microsoft.com/vscode/devcontainers/dotnet:5.0 dotnet /app/UICatalog.dll

@BDisp
Copy link
Collaborator

BDisp commented Nov 23, 2021

Not working, there is no lines. That must be created through docker-compose and then using docker build. Putting all the commands in the command line is not worth.

docker-issue

@leomoty
Copy link

leomoty commented Nov 23, 2021

Weird af, works for me, I agree that it is not worth it, but then you'd need a Dockerfile

image

@BDisp
Copy link
Collaborator

BDisp commented Nov 23, 2021

I tried again and is not working. If someone else can test would be great too. But I was intrigued because it is working for you. Are you using an image where the locale is already set and the configuration on the command line does not affect his behavior?

@kierenj
Copy link
Author

kierenj commented Nov 25, 2021

I'm happy to try something - which steps exactly would be helpful?

Also, is there anything I can do in the code to auto-detect if the locale is correctly installed? Then we could programatically set UseSystemConsole if the dependency is missing?

@BDisp
Copy link
Collaborator

BDisp commented Nov 25, 2021

I'm happy to try something - which steps exactly would be helpful?

Anything you have to improve this is always welcome. My intention is making a Linux environment to deal with Visual Studio 2022. For now I have Windows 10 installed, but if this is not possible with this OS, perhaps I'll install Windows 11. If someone who seeing this and know this will only work with Windows 11, please say anything, thanks.

Also, is there anything I can do in the code to auto-detect if the locale is correctly installed? Then we could programatically set UseSystemConsole if the dependency is missing?

Any code that may automatically detect if some image doesn't contains some resources is good for the creation of the image. Forcing programmatically set UseSystemConsole if the dependency is missing isn't a solution. That resources must be previously installed in the image before run.


I was trying to create only one Dockerfile in the solution folder with a docker-compose. My idea was using env variables to be replaced by the service name, but without success. So I ended up creating a Dockerfile for each project, whose runtime image is inherited by a base image created by a Dockerfile in the solution folder. Now my goal is automatically build this base image first, case not exist, before running any of the projects. Another challenge I really want to achieve is opening the project iteratively on tty terminal when the debug button is pressed, but this is impossible for now. Even with WSL I can't achieve this. If someone can help with this would be great.
For VSCode already exist the devcontainer.json file which work very well.
I'll commit in my PR #1515 because the images is for Net6.0.

@leomoty
Copy link

leomoty commented Nov 25, 2021

I am actually running Windows 11, would that explain the difference between my Windows Terminal and yours?

@BDisp
Copy link
Collaborator

BDisp commented Nov 25, 2021

I am actually running Windows 11, would that explain the difference between my Windows Terminal and yours?

This may absolutely explains the differences, thanks for share. Does the Windows 10 license valid for Windows 11?

@leomoty
Copy link

leomoty commented Nov 25, 2021

I am actually running Windows 11, would that explain the difference between my Windows Terminal and yours?

This may absolutely explains the differences, thanks for share. Does the Windows 10 license valid for Windows 11?

Yup

@BDisp
Copy link
Collaborator

BDisp commented Nov 25, 2021

What options did you used?

  • Updated from the online software.
  • Installed from scratch from a downloaded image.
  • From Windows Update.

Run from the Compatibility Checker Utility and obtained the following information:

This PC will run Windows 11.
Your PC meets the hardware requirements and is eligible to receive the free upgrade when it is available (4, 7).

(4) Certain features require specific hardware, see https://www.microsoft.com/windows/windows-11-specifications.
(7) Update for Windows 11 will be supplied to eligible devices between the end of 2021 and 2022. The date will vary depending on the device. Certain features require specific hardware; See Windows 11 Specifications.

Based on this, I think it is preferable to wait for the update of Windows Update

@leomoty
Copy link

leomoty commented Nov 25, 2021

Hey, I got the update through Windows Update since I did test the betas. But afaik the advisor they have will give you the same upgrade result.

If you already qualify you won't need to fight to enable TPM / UEFI, or anything like that.

@tig
Copy link
Collaborator

tig commented Aug 4, 2022

Can this issue be closed as fixed?

@BDisp
Copy link
Collaborator

BDisp commented Aug 4, 2022

Yes it was a docker configuration image that I think the user has already figured out the workaround on the Kubernetes.

@tig tig closed this as completed Aug 4, 2022
@thunder7553
Copy link

One of the information I saw was here https://stackoverflow.com/questions/28405902/how-to-set-the-locale-inside-a-debian-ubuntu-docker-container.

The best workaround I used was:


	apt-get install -y locales && \
	sed -i -e 's/# en_US.UTF-8 UTF-8/en_US.UTF-8 UTF-8/' /etc/locale.gen && \
    dpkg-reconfigure --frontend=noninteractive locales && \
    update-locale LANG=en_US.UTF-8
ENV LANG=en_US.UTF-8 \
	TERM=xterm-256color

Thanks, that's just what I needed (debian:bullseye-slim based image with .net 7)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

6 participants