expect
expect copied to clipboard
spawn ssh send large/long command got /r(carriage return) and (/b)backspace
when spawn ssh client , send large/long command , expect recv /r and /b
we can:
- use
stty -echodisable input echo , just pick up output , but block on some device - resize tty size use github.com/kr/pty.Setsize
has better way? etc syscall.SYS_IOCTL+syscall.ECHO?
test code
func TestExpect_SSH(t *testing.T) {
var PROMPT = `(?m)[^$]*#` // or (?m)[^$]*$
exp, err := expect.Spawn(
"ssh",
"-F", "/dev/null",
"-o", "UserKnownHostsFile /dev/null",
"-o", "StricthostKeyChecking false",
"localhost",
)
if err != nil {
t.Error("Unexpected error spawning 'ssh'", err)
}
defer exp.Close()
exp.SetLogger(expect.TestLogger(t))
exp.SetTimeout(time.Second * 15)
// Login
exp.Expect(`[Pp]assword:`)
exp.SendMasked("ban password")
exp.Send("\n")
exp.Expect(PROMPT) // Wait for prompt
time.Sleep(1 * time.Second)
// tty attr
exp.SendLn("stty -a")
match, err := exp.Expect(PROMPT) // Wait for prompt
t.Logf("stty -a:%s", match.Before)
// less then column size
exp.SendLn("echo START_1234567890_1234567890_END")
match, err = exp.Expect(PROMPT) // Wait for prompt
t.Logf("long command output:%s", match.Before)
exp.Send("\n")
exp.Expect(PROMPT) // Wait for prompt
// got carriage return
exp.SendLn("echo START_1234567890_1234567890_1234567890_1234567890_1234567890_1234567890_1234567890_1234567890_1234567890_1234567890_1234567890_1234567890_END")
match, err = exp.Expect(PROMPT) // Wait for prompt
t.Logf("long command output:%s", match.Before)
exp.SetWinSize(10240, 768)
exp.SendLn("echo START_0987654321_0987654321_END")
match, err = exp.Expect(PROMPT) // Wait for prompt
t.Logf("long command output:%s", match.Before)
exp.Send("\n")
exp.Expect(PROMPT) // Wait for prompt
exp.SendLn("echo START_0987654321_0987654321_0987654321_0987654321_0987654321_0987654321_0987654321_0987654321_0987654321_0987654321_0987654321_0987654321_END")
match, err = exp.Expect(PROMPT) // Wait for prompt
t.Logf("long command output:%s", match.Before)
time.Sleep(5 * time.Second)
// Wait for EOF
exp.SendLn("exit")
exp.ExpectEOF()
}
func SetWinSize
func (exp *Expect) SetWinSize(rows, cols uint16) error {
ws := pty.Winsize{rows, cols, 0, 0}
return pty.Setsize(exp.pty.(*os.File), &ws)
}
@slmint are you still wanting to use this project in production code at all?
I've left this project abandoned for a long time and am at the point where I may not want to maintain this project unless there's significant interest.
@jamesharr yes , it is still working
What are you using it for if you don't mind me asking? I had originally intended this to be used for SSH, but I think Go's native SSH support has improved a lot since then. If I were doing it again I probably would probably use Go's libraries rather than terminal emulation
call ssh ,telnet , sftp client to: execute command switch user in session upload/download file use sftp\scp\cat command change shell prompt
Oh cool. I'm glad this project has been useful to you.
I'm not trying to push you away from this project, but I do want to make sure you're getting QA, bug fixes, features that you need.
In that vein, have you looked at https://github.com/google/goexpect ? Does it match the features/flow that you'd like? The main reason I bring this up is that the goexpect project has been much more active than this one. If it doesn't match the code-flow you like, that's cool tool.
Yes, despite some problems, the situation is still under control, and it is not the time to switch tools (too busy).
At that time, this tool was an appropriate choice. Now that the requirements for function expansion and stability are becoming stricter, its basic functions are capable of doing its part.
Thank you @jamesharr