【发布时间】:2023-03-18 20:05:02
【问题描述】:
所以我可以通过 ssh 进入机器,但在提示中输入数据时遇到问题。
...
sshConfig := &ssh.ClientConfig{
User: user,
Auth: []ssh.AuthMethod{
ssh.Password(password),
},
HostKeyCallback: KeyPrint,
}
connection, err := ssh.Dial("tcp", connStr, sshConfig)
if err != nil {
log.Fatalln(err)
}
session, err := connection.NewSession()
if err != nil {
log.Fatalln(err)
}
modes := ssh.TerminalModes{
ssh.ECHO: 0, // disable echoing
ssh.TTY_OP_ISPEED: 14400, // input speed = 14.4kbaud
ssh.TTY_OP_OSPEED: 14400, // output speed = 14.4kbaud
}
if err := session.RequestPty("xterm", 80, 40, modes); err != nil {
session.Close()
log.Fatalf("request for pseudo terminal failed: %s", err)
}
stdin, err := session.StdinPipe()
if err != nil {
log.Fatalf("Unable to setup stdin for session: %v", err)
}
go io.Copy(stdin, os.Stdin)
stdout, err := session.StdoutPipe()
if err != nil {
log.Fatalf("Unable to setup stdout for session: %v", err)
}
go io.Copy(os.Stdout, stdout)
stderr, err := session.StderrPipe()
if err != nil {
log.Fatalf("Unable to setup stderr for session: %v", err)
}
go io.Copy(os.Stderr, stderr)
// err = session.Run("1")
session.Run("") // running it allows me to interact with the remote machines terminal in my own terminal.. session.Start("") exits and session.Wait() doesn't display the Welcome screen that normally greats users, and the prompt doesn't appear.
stdin.Write([]byte("10000"))
os.Stdin.WriteString("110000")
// log.Fatalln(n, err)
// os.Stdin.WriteString("1")
// for {
// session.Run("1")
// go os.Stdin.WriteString("1")
// go stdin.Write([]byte("10000"))
// }
...
上面的代码 sn -p 让我进入机器,机器的提示显示在我的屏幕上,就像我手动 ssh 进入一样。我可以在 shell 中输入......但我需要能够为我在 shell 中输入 Go。我正在与之交互的提示是一个基于文本的游戏,所以我不能只发出命令,例如 no(ls、echo、grep 等)。我唯一允许输入的是数字。如何将输入发送到 ssh 会话?我尝试了很多方法,但似乎没有一个输入通过。
我还附上了提示的屏幕截图,以防上面的描述在试图描述会话类型时造成混淆。
更新: 我想我已经找到了一种发送数据的方法,至少一次。
session, err := connection.NewSession()
if err != nil {
log.Fatalln(err)
}
// ---------------------------------
modes := ssh.TerminalModes{
ssh.ECHO: 0, // disable echoing
ssh.TTY_OP_ISPEED: 14400, // input speed = 14.4kbaud
ssh.TTY_OP_OSPEED: 14400, // output speed = 14.4kbaud
}
if err := session.RequestPty("xterm", 80, 40, modes); err != nil {
session.Close()
log.Fatalf("request for pseudo terminal failed: %s", err)
}
stdin, err := session.StdinPipe()
if err != nil {
log.Fatalf("Unable to setup stdin for session: %v", err)
}
go io.Copy(stdin, os.Stdin)
stdout, err := session.StdoutPipe()
if err != nil {
log.Fatalf("Unable to setup stdout for session: %v", err)
}
go io.Copy(os.Stdout, stdout)
stderr, err := session.StderrPipe()
if err != nil {
log.Fatalf("Unable to setup stderr for session: %v", err)
}
go io.Copy(os.Stderr, stderr)
go session.Start("")
for {
stdin.Write([]byte("10000000\n"))
break
}
session.Wait()
我以go session.Start("") 开始会话,记住传递命令没有意义,因为我所做的只是输入数据以响应提示。
然后我在 for 循环的末尾使用session.Wait()...有点像使用通道和等待组时所做的那样......在 for 循环中我使用stdin.Write([]byte("10000000\n")) 发送数据,其中需要注意的重要一点是添加@987654329 @delimiter 模拟在键盘上敲击回车..
如果有任何更好的方法来实现我想要实现的目标,请随意。接下来的步骤是解析标准输出以获取响应并做出相应的回复。
【问题讨论】:
-
您不能只使用
fmt.Scanln(...)接收用户输入然后从程序中执行您需要的任何命令吗? -
@acidic 这是一个 ssh 会话。 ssh 会话内部是一个正在运行的程序。这不是我的程序在运行。我不是在等待用户输入。我是用户,连接到远程终端。目标是解析标准输出,确定我的算法应该如何响应,然后提交答案以在 30 秒内赢得 10 场比赛。这意味着我不能只是远程进入并自己在键盘上输入。我的程序通过 ssh 登录到远程机器,必须解析来自标准输出的响应并为我输入数字。所以没有 fmt 扫描。
-
@acidic 我还看到你可能从哪里得到了使用扫描仪的想法,stackoverflow.com/q/23019890/4639336,但是在这种情况下,我没有输入 shell 命令。我只是通过 ssh 与游戏互动。所以终端命令对它不起作用。我需要一种将按键数据发送到游戏外壳的方法。换句话说,当我运行我的代码时,我可以在我的 shell 上与游戏进行交互,就像我手动 ssh 进入它一样。与其让我与我的终端和键盘进行交互,不如 go 与它进行交互。你知道,像 selenium 一样自动化。
-
哦,是的,我明白了。我正在做一个项目,过去几天我也一直在使用 SSH 包,我想我明白你的问题是什么。我有同样的问题,我想。我的 go 程序运行一个脚本,但我想用
sudo ...运行它,唯一的问题是,在以 sudo 执行我的命令的中途运行sudo ...之后,它会要求用户输入密码但没有完成执行。我不确定在发送命令后如何输入密码。这与您遇到的问题相同吗? -
@acidic 不是 100%,但是我上面发布的链接显示了您如何输入密码,或者我帖子中的代码显示了您如何提供密码,至少也许您可以使用那些为您自己的问题找到解决方案的人。我的更像......我很好。我收到来自服务器的提示。服务器要求我输入一个数字......这就是它下地狱的地方。我还没弄清楚如何用 go 输入数字。