2014-04-11 6 views
1

ssh와 같은 터미널 서브 프로세스에서 입력을 보내고 출력을받는 방법에 관한 질문이 있습니다. 내가 어떻게 위의 작업과 유사하다 Golang에서 간단한 예제를 찾을 수 없습니다Golang은 터미널 프로세스에서 입력을 입력하고 출력을 얻습니다.

how to give subprocess a password and get stdout at the same time

: 파이썬의 예는 다음과 같이 될 것이다.

는 Golang에서

이 같은 일을 할 것입니다하지만 작동하지 않습니다 그러나

cmd := exec.Command("ssh", "[email protected]") 
    cmd.Stdout = os.Stdout 
    cmd.Stderr = os.Stderr 
    stdin, _ := cmd.StdinPipe() 
    stdin.Write([]byte("password\n")) 
    cmd.Run() 

; 나는이 명령을 exec 할 때마다 출력을 얻을 수 밖에 없으므로이 작업을 수행하는 방법을 잘 모릅니다. 코드에서 암호를 자동으로 입력 할 수 없습니다. 누구나 ssh와 같은 터미널 프로세스에 쓰는 예제가 있습니까? 그렇다면 공유하십시오.

+2

'stdin'에서 암호를 읽지 않기 때문에'ssh'를 사용하면이 작업을 매우 쉽게 할 수 있습니다. http://stackoverflow.com/q/1340366을 참조하십시오. 가장 좋은 옵션은 키 쌍을 생성하고이를 사용하여 인증하는 것 같습니다. –

+2

이전에 파이썬에서이 작업을 시도했습니다. 나는 [Paramiko] (http://www.lag.net/paramiko/)를 사용하여 작동시킬 수있었습니다. [go.crypto/ssh] (http://godoc.org/code.google.com/p/go.crypto/ssh)로 시도해야합니다. –

+0

stdin과 stdout을 처리하는 법을 잘 알고있는 것 같습니다. 문제는 당신의 코드에있는 것이 아니라 ssh가 쉘이나 tty에서 돌아 가지 않는다는 것을 감지했을 때 다른 행동을하기 때문에 발생합니다. 암호 대신 인증서 인증을 사용해야합니다. –

답변

2

위의 의견에 감사 드리며 암호로 작업하는 ssh 액세스를 얻을 수있었습니다. golang의 ssh API 라이브러리를 사용했습니다. https://godoc.org/golang.org/x/crypto/ssh#example-Dial

우선 go get golang.org/x/crypto/ssh 의해 terminal 패키지를 얻을

func ExampleDial() { 
    // An SSH client is represented with a ClientConn. Currently only 
    // the "password" authentication method is supported. 
    // 
    // To authenticate with the remote server you must pass at least one 
    // implementation of AuthMethod via the Auth field in ClientConfig. 
    config := &ClientConfig{ 
      User: "username", 
      Auth: []AuthMethod{ 
        Password("yourpassword"), 
      }, 
    } 
    client, err := Dial("tcp", "yourserver.com:22", config) 
    if err != nil { 
      panic("Failed to dial: " + err.Error()) 
    } 

    // Each ClientConn can support multiple interactive sessions, 
    // represented by a Session. 
    session, err := client.NewSession() 
    if err != nil { 
      panic("Failed to create session: " + err.Error()) 
    } 
    defer session.Close() 

    // Once a Session is created, you can execute a single command on 
    // the remote side using the Run method. 
    var b bytes.Buffer 
    session.Stdout = &b 
    if err := session.Run("/usr/bin/whoami"); err != nil { 
      panic("Failed to run: " + err.Error()) 
    } 
    fmt.Println(b.String()) 
} 
1

이 상기 실시 예의 변형/완전한 버전이다

https://code.google.com/p/go/source/browse/ssh/example_test.go?repo=crypto

구체적 : I부터 실시 예를 다음과 같이은 상당히 단순

package main 

import (
    "bufio" 
    "bytes" 
    "fmt" 
    "os" 
    "strings" 

    "golang.org/x/crypto/ssh" 
    "golang.org/x/crypto/ssh/terminal" 
) 

func main() { 
    if len(os.Args) < 3 { 
     usage := "\n./remote-ssh {host} {port}" 
     fmt.Println(usage) 
    } else { 
     host := os.Args[1] 
     port := os.Args[2] 

     username, password := credentials() 
     config := &ssh.ClientConfig{ 
      User: username, 
      Auth: []ssh.AuthMethod{ 
       ssh.Password(password), 
      }, 
     } 
     connectingMsg := fmt.Sprintf("\nConnecting to %s:%v remote server...", host, port) 
     fmt.Println(connectingMsg) 

     hostAddress := strings.Join([]string{host, port}, ":") 
     // fmt.Println("Host add %s ", hostAddress) 
     client, err := ssh.Dial("tcp", hostAddress, config) 
     if err != nil { 
      panic("Failed to dial: " + err.Error()) 
     } 

     for { 
      session, err := client.NewSession() 
      if err != nil { 
       panic("Failed to create session: " + err.Error()) 
      } 
      defer session.Close() 

      // Once a Session is created, can execute a single command on remote side 
      var cmd string 
      str := "\nEnter command (e.g. /usr/bin/whoami OR enter 'exit' to return) : " 
      fmt.Print(str) 
      fmt.Scanf("%s", &cmd) 
      if cmd == "exit" || cmd == "EXIT" { 
       break 
      } 
      s := fmt.Sprintf("Wait for command '%s' run and response...", cmd) 
      fmt.Println(s) 

      var b bytes.Buffer 
      session.Stdout = &b 
      if err := session.Run(cmd); err != nil { 
       panic("Failed to run: " + err.Error()) 
      } 
      fmt.Println(b.String()) 
     } 
    } 
} 

func credentials() (string, string) { 
    reader := bufio.NewReader(os.Stdin) 

    fmt.Print("Enter Username: ") 
    username, _ := reader.ReadString('\n') 

    fmt.Print("Enter Password: ") 
    bytePassword, err := terminal.ReadPassword(0) 
    if err != nil { 
     panic(err) 
    } 
    password := string(bytePassword) 

    return strings.TrimSpace(username), strings.TrimSpace(password) 
} 

https://play.golang.org/p/4Ad1vKNXmI

관련 문제