Pexpect and Terminal Resizing

Viewed 1311

I'm using pexpect to automate ssh-ing into a remote server that prompts for a password. The process is very simple, and works great:

child = pexpect.spawn("ssh -Y remote.server")
child.expect(re.compile(b".*password.*"))
child.sendline(password)
child.interact()

This works great, however, I notice one quite annoying quirk I have not been able to figure out. When I use vim in this terminal, it seems to not resize correctly. When ssh-ing directly, and using a program such as vim, I can resize my terminal window (locally), and the remote program automatically/interactively fixes the columns and lines. My pexpect instance does not. There are a few other minor quirks that I can lvie with, but this one is quite annoying.

I'm hoping to find a way I can get my pexpect ssh session to behave the same way a native ssh session does, or at the very least understand the reason the two behave differently.

2 Answers

The SIGWINCH handles window size change. If you need it behave the same of native ssh, you should also set the pexpect initial window size:

import pexpect, struct, fcntl, termios, signal, sys

def get_terminal_size():
    s = struct.pack("HHHH", 0, 0, 0, 0)
    a = struct.unpack('hhhh', fcntl.ioctl(sys.stdout.fileno(), termios.TIOCGWINSZ, s))
    return a[0], a[1]

def sigwinch_passthrough(sig, data):
    global p
    if not p.closed:
        p.setwinsize(*get_terminal_size())

p = pexpect.spawn('/bin/bash')
# Set the window size the same of current terminal window size
p.setwinsize(*get_terminal_size())
# Hook the window change signal so that the pexpect window size change as well
signal.signal(signal.SIGWINCH, sigwinch_passthrough)

p.interact()
Related