Голанг правильно обрабатывает стандартный вывод сессии SSH
Я пишу программу Go для подключения к беспроводному контроллеру Cisco для запуска нескольких команд настройки на подключенных точках доступа. Я могу подключиться и отправить команды на контроллер через пакет SSH Go golang.com/x/crypto/ssh
,
Мне нужно: а) печатать только выходные данные каждой отправляемой команды, а не подсказку контроллера или запросы на вход в систему, и б) выяснить, как отправлять последовательные команды после команды, вывод которой включает --More-- or (q)uit
подсказки.
Прямо сейчас у меня есть os.Stdout
назначен в SSH session.Stdout
Вот почему я печатаю больше, чем просто вывод команд, которые я посылаю. Как бы я вручную контролировал вывод session.Stdout
? Я знаю session.Stdout
является io.Writer
, но я не знаю, как контролировать то, что он пишет os.Stdout
, Вот мой код вместе с его выводом:
package main
import (
"bufio"
"fmt"
"golang.org/x/crypto/ssh"
"golang.org/x/crypto/ssh/terminal"
"log"
"os"
"time"
"io"
)
func SendCommand(in io.WriteCloser, cmd string) error {
if _, err := in.Write([]byte(cmd + "\n")); err != nil {
return err
}
return nil
}
func main() {
// Prompt for Username
fmt.Print("Username: ")
r := bufio.NewReader(os.Stdin)
username, err := r.ReadString('\n')
if err != nil {
log.Fatal(err)
}
// Prompt for password
fmt.Print("Password: ")
password, err := terminal.ReadPassword(int(os.Stdin.Fd()))
if err != nil {
log.Fatal(err)
}
// Setup configuration for SSH client
config := &ssh.ClientConfig{
Timeout: time.Second * 5,
User: username,
Auth: []ssh.AuthMethod{
ssh.Password(string(password)),
},
HostKeyCallback: ssh.InsecureIgnoreHostKey(),
}
// Connect to the client
client, err := ssh.Dial("tcp", "host:22", config)
if err != nil {
log.Fatal(err)
}
defer client.Close()
// Create a session
session, err := client.NewSession()
if err != nil {
log.Fatal(err)
}
defer session.Close()
// Setup StdinPipe to send commands
stdin, err := session.StdinPipe()
if err != nil {
log.Fatal(err)
}
defer stdin.Close()
// Route session Stdout/Stderr to system Stdout/Stderr
session.Stdout = os.Stdout
session.Stderr = os.Stderr
// Start a shell
if err := session.Shell(); err != nil {
log.Fatal(err)
}
// Send username
if _, err := stdin.Write([]byte(username)); err != nil {
log.Fatal(err)
}
// Send password
SendCommand(stdin, string(password))
// Run configuration commands
SendCommand(stdin, "show ap summary")
SendCommand(stdin, "logout")
SendCommand(stdin, "N")
session.Wait()
}
Образец прогона:
$ go run main.go
Username: username
Password:
(Cisco Controller)
User: username
Password:****************
(Cisco Controller) >show ap summary
Number of APs.................................... 1
Global AP User Name.............................. its-wap
Global AP Dot1x User Name........................ Not Configured
AP Name Slots AP Model Ethernet MAC Location Country IP Address Clients DSE Location
------------------ ----- -------------------- ----------------- ---------------- ---------- --------------- -------- --------------
csc-ap3500 2 AIR-CAP3502I-A-K9 00:00:00:00:00:00 csc-TESTLAB-ap35 US 10.10.110.10 0 [0 ,0 ,0 ]
(Cisco Controller) >logout
The system has unsaved changes.
Would you like to save them now? (y/N) N
Моя следующая проблема возникает, когда вывод команды имеет один или несколько --More-- or (q)uit
подсказки и я пытаюсь отправить последовательную команду. Например, вот вывод моего кода при запуске show sysinfo
с последующим logout
:
$ go run main.go
Username: username
Password:
(Cisco Controller)
User: username
Password:****************
(Cisco Controller) >show sysinfo
Manufacturer's Name.............................. Cisco Systems Inc.
Product Name..................................... Cisco Controller
Product Version.................................. 8.2.161.0
Bootloader Version............................... 1.0.20
Field Recovery Image Version..................... 7.6.101.1
Firmware Version................................. PIC 16.0
Build Type....................................... DATA + WPS
--More-- or (q)uit
Configured Country............................... US - United States
Operating Environment............................ Commercial (0 to 40 C)
Internal Temp Alarm Limits....................... 0 to 65 C
Internal Temperature............................. +23 C
External Temperature............................. +28 C
Fan Status....................................... 3900 rpm
# the "l" is missing in "logout"
(Cisco Controller) >ogout
Incorrect usage. Use the '?' or <TAB> key to list commands.
(Cisco Controller) >N
Incorrect usage. Use the '?' or <TAB> key to list commands.
# the program hangs here
(Cisco Controller) >
TL; DR Как вручную управлять выводом io.Writer
и как правильно обрабатывать отправку команд подряд?
Любая помощь приветствуется. Заранее спасибо.