Гарантируется ли получение выходных данных из ssh?

# #go #ssh #output #buffer

Вопрос:

Я использую пакет ssh для подключения к серверу Linux и получения выходных данных команд. Вспомогательная функция, которую я написал для этого, приведена ниже:

 func sshRunCommand(host string, command string) (output string, err error) {
    keyData, err := ioutil.ReadFile("srv.private.openssh")
    if err != nil {
        return "", err
    }
    key, err := ssh.ParsePrivateKey(keyData)
    if err != nil {
        return "", err
    }
    // Authentication
    config := amp;ssh.ClientConfig{
        User: "root",
        HostKeyCallback: ssh.InsecureIgnoreHostKey(),
        Auth: []ssh.AuthMethod{
            ssh.PublicKeys(key),
        },
    }
    // Connect
    client, err := ssh.Dial("tcp", net.JoinHostPort(host, "22"), config)
    if err != nil {
        return "", err
    }
    // Create a session. It is one session per command.
    session, err := client.NewSession()
    if err != nil {
        return "", err
    }
    defer session.Close()
    var b bytes.Buffer
    session.Stdout = amp;b // 👈 this is the place I am concerned with
    // Finally, run the command
    err = session.Run(command)
    return b.String(), err
}

 

Эта команда обычно работает нормально: она всегда подключается, но случайным образом не возвращает результат.

Прежде чем продолжить свои исследования, я хотел убедиться, что выходной буфер очищен, прежде чем возвращать вывод. Так ли это на самом деле?

Комментарии:

1. Если ОС Linux, то гарантированно будет сброшен только stderr, а не stdout AFAIK.

2. Попробуйте также проверить stderr на наличие каких-либо выходных данных там. Ожидается, что любые проблемы с вводом-выводом будут возвращены как ошибка Session.Run .

Ответ №1:

В этом примере использования/проблеме вы можете видеть, что stdout и stderr связаны с одним и тем же буфером.
посмотрите, поможет ли это в вашем случае.

 
    sess, err := client.NewSession()
    if err != nil {
        log.Fatal("Failed to create session: ", err)
    }
    defer sess.Close()

    stdin, err := sess.StdinPipe()
    if err != nil {
        log.Fatal(err)
    }

    var b bytes.Buffer
    sess.Stdout = amp;b
    sess.Stderr = amp;b

    err = sess.Shell()
    if err != nil {
        log.Fatal(err)
    }

    ...

    _, err = fmt.Fprintf(stdin, "%sn", cmd)