While building a small expect script I noticed that, after executing the script, some characters were automatically on the input of bash. I have seen that on other programs before, but here I have something reproducable.
My expect script is the following:
#!/usr/bin/expect
spawn ssh root@[lindex $argv 0]
expect "password:"
send "[lindex $argv 1]\r"
expect "~#"
And this is the result:
user@PC:~$ expect test.exp 192.168.0.2 root
spawn ssh root@192.168.0.2
root@192.168.0.2's password:
^[[51;117Rroot@device:~# user@PC:~$ ;117R
-bash: syntax error near unexpected token `;'
user@PC:~$
So as you can see on the fifth line of the output, there are some random characters on stdout (^[[51;117R
) and some of them leak onto the shell input line (;117R
). If I press enter after executing the expect script, bash then tries to interpret that (;117R
) as if I had entered it into bash.
My question is, what happens here and how do I stop it?
Best Answer
These are not "random characters".
Something run during the log-on process for the remote system is, by sending a Device Status Report control sequence to its terminal, requesting a Cursor Position Report from that terminal. The terminal (your terminal, several hops away, passed the DSR output via
ssh
andexpect
) is duly generating and sending it.Such reports arrive from a terminal to the host (i.e. the machine directly connected to the terminal) in exactly the same way as typed input does. Programs running on the host have no reliable way to know that you did not simply type that Cursor Position Report. Of course
expect
is not reading and sending on terminal input at that point, so the CPR has queued up to be read by the next program that does read input from your terminal, which is your shell afterexpect
has finished. What you are seeing is how your shell reacts to such control sequences as input.Such things are one of the reasons that terminal input processing should really always be a proper ECMA-48 decoder with a proper state machine. Your shell's line editing system is not. (None of ZLE, Readline, or libedit really handle terminal input control sequences properly.) It is decoding things using pattern matching, which does not do the right thing. Notice how it has only ignored the first four characters of the control sequence. A proper ECMA-48 input decoder would decode the whole control sequence, including all of the Parameter characters up to the Final character, recognize it as a CPR, and (one hopes) throw it away as input for which it has no use.
As to what is requesting the CPR in the first place: For that you'll have to inspect the remote system, and what programs it runs at terminal log-on. A likely culprit is the Xterm
resize
program. (Note that you should not use that program when Xterm is not your terminal, as it will incorrectly set theTERM
environment variable to anxterm
type.) Butresize
is not the sole possibility.Further reading
console-decode-ecma48
". nosh Guide. Softwares.TERM
". nosh Guide. Softwares.