bashresizeexpect

Expect script inside bash and resize of terminal


I'm trying to get terminal resize working inside SSH session, that is spawned by expect, which is spawned by bash.

#!/bin/bash

...
SSH_PASS=XXXXX
SSH_ADDR=YYYYY

expect <(cat << EOD

    trap {
        set rows [stty rows]
        set cols [stty columns]
        stty rows $rows columns $cols < $spawn_out(slave,name)
    } WINCH
    
    spawn ssh $SSH_ADDR
    expect "Password:"
    send -- "${SSH_PASS}\n"
    interact
EOD
)

When terminal is resizing, I'm getting messages like

couldn't open (slave,name): no such file or directory
while executing
"stty rows  columns  < (slave,name)"

So, I assume, var $spawn_out(slave,name), that is created by expect is not visible inside. How it could be achieved? I've tried

global spawn_out

but it doesn't help.

Thanks in advance!

PS: I can't use SSH keys here, it's limitation I can't bypass.


Solution

  • What you need to instead is to escape some of the $ so they expanded by expect rather than bash:

    SSH_PASS=XXXXX
    SSH_ADDR=YYYYY
    
    expect <(cat << EOD
    
        trap {
            set rows [stty rows]
            set cols [stty columns]
            stty rows \$rows columns \$cols < \$spawn_out(slave,name)
        } WINCH
        
        spawn ssh $SSH_ADDR
        expect "Password:"
        send -- "${SSH_PASS}\n"
        interact
    EOD
    )
    

    Note that the $SSH_ADDR is written normally because you wish for bash to interpolate that variable. But the rows, cols, and spawn_out are delayed in their interpolation so that expect can do that variable evaluation instead.


    This issue is because the $ needs to be expanded at the right point. When you write $rows within the expect <(, it gets expanded at parse time. So the code that gets passed to expect is something like

        trap {
            set rows [stty rows]
            set cols [stty columns]
            stty rows "" columns "" < ""(slave,name)
        } WINCH
        
        spawn ssh XXXXX
        expect "Password:"
        send -- "YYYYY\n"
        interact
    

    because the rows is undefined in the script, and gets expanded at parse time.

    I had the same problem and this is how I solved it. With this change it works perfectly.