How to use shell_interact()?

I’ve never managed to use it. It seems very useful for debugging my tests but every time I try I get

OSError: [Errno 9] Bad file descriptor

Up until now I’ve managed to survive by writing the same configuration to my test and to a vm.nix file to run with nixos-shell but this falls apart when my tests have multiple machines and my last resort is using a lot of print()s and echos, which is getting too time consuming.

Anyone had the same problem?

1 Like

I don’t have anything terribly smrt to add since I’ve never even tried to use it, but it may help if you clarify what you’ve tried?

For example, have you tried starting it as suggested in Integration testing using virtual machines (VMs) — nix.dev documentation ?

Thanks for your answer.

I hadn’t try nixos-test-driver until now since I understood that it allows you to run the python instructions interactively, which wasn’t exactly what I wanted to do. What I wanted was to run the test normally and then be dropped into the shell of one machine at the exact point I needed. Anyway, I’ve tried now with some strange results

I arranged the simplest test possible:

let
  pkgs = import <nixpkgs> {};
in pkgs.nixosTest {
  machine = { ... }:
  { };

  testScript = ''
      machine.shell_interact()
    '';
}

And here you can see my experience with it
https://asciinema.org/a/7EHf89Bqy2mbPPCOixxzqafvm

So, it kinda works? It’s not exactly the use-case I wanted, the terminal is a bit broken and I’ve still randomly gotten some Broken pipe error in another test, but it’s an improvement at least

1 Like

Nice catch! It seems that the machine’s shell writes something into the telnet’s connection that cannot be coerced to ascii to be written to the stdout. The Python’s telnetlib is ancient and I never got the chance to use it. I wonder if this is a bug of the library still there after the port from 2.7 to 3.x or if the telnet protocol RFC states that the wire encoding should be ascii… probably both. Not so quickly fixable though… the quickest thing is a monkey patch to that telnetlib.Telnet.interact() to make it do a text.decode('utf-8') instead at line 555.

1 Like

I’m getting this:

client: Terminal is ready (there is no initial prompt):
2023/02/27 20:38:11 socat[72] E tcgetattr(0, 0x5555555f8ac0): Inappropriate ioctl for device

And the test continues without entering any interactive console.

Sorry, I couldn’t find any telnetlib usage in NixOS tests. shell_interact uses socat:

def shell_interact(self) -> None:
    """Allows you to interact with the guest shell

    Should only be used during test development, not in the production test."""
    self.connect()
    self.log("Terminal is ready (there is no initial prompt):")

    assert self.shell
    subprocess.run(
        ["socat", "READLINE,prompt=$ ", f"FD:{self.shell.fileno()}"],
        pass_fds=[self.shell.fileno()],
    )

@azazel75, what file do you suggest to patch?

But there’s no point if telnetlib isn’t used… maybe it was used at the time