2 years ago

#42907

test-img

AR7

Interact with a shell script running remotely via SSH

I am working an application written in golang,for which one of the capability will be to SSH into a device and execute a shell script there. With my current implementation,a normal script is getting executed.The problem lies in the execution of a script that requires user input: for e.g the script asks the user, can we proceed with the installation: and the user has to type in Y or N. This is the part where it is failing. Here is my implementation:

func main() {
    
    cmdOutput,err := ExecuteScriptSSH()
    if err != nil{
        fmt.Printf("Error is %s",err)
    }
    fmt.Printf("Command Output is %s", cmdOutput)
}

func ExecuteScriptSSH() (string, error) {
    script := "#!/bin/sh\n\n ls -l \n\n date"
    params := make(map[string]interface{})
    params["Username"] = "uname"
    params["Password"] = "pwd"
    params["IPAddress"] = "ip"
    params["Port"] = "22"
    connection := NewConnection(params)

    client, err := connection.ConnectNonSecure()
    if err != nil {
        fmt.Printf("unable to Connect:%v ", err)
    }
    defer client.Close()
    ss, err := client.NewSession()
    if err != nil {
        fmt.Printf("unable to create SSH session:%v ", err)
    }
    //Converting the Script to string to a shell script file by writing to it.
    d1 := []byte(script)
    err = os.WriteFile("/tmp/script.sh", d1, 0777)
    if err != nil {
        fmt.Printf("Error constructing Script file %v", err)
    }
    // opening the script file
    scriptFile, err2 := os.OpenFile("/tmp/script.sh", os.O_RDWR|os.O_CREATE, 0777)
    if err2 != nil {
        fmt.Printf("Error opening Script file is %s", err)
    }
    cmdOutput := &bytes.Buffer{}
    ss.Stdout = cmdOutput
    ss.Stdin = scriptFile
    interpreter := "sh"
    err = ss.Run(interpreter)
    if err != nil {
        fmt.Printf("Error in Executing Script file %v", err.Error())
    }
    return cmdOutput.String(), err

}

type Params struct {
    Username string
    Password string
    IPAddress  string
    Port     string
}

func NewConnection(data map[string]interface{}) *Params {
    var params Params
    fmt.Printf("Data is %v",data)
    err := mapstructure.Decode(data,&params)
    if err != nil {
        panic(err)
    }
    fmt.Printf("Mapped Connection details %v",params)
    return &params
}

func (p *Params) ConnectNonSecure() (*ssh.Client, error){

    config := &ssh.ClientConfig{
        User: p.Username,
        Auth: []ssh.AuthMethod{
            ssh.Password(p.Password),
        },
        // Non-Production-only
        HostKeyCallback: ssh.InsecureIgnoreHostKey(),
    }
    fmt.Printf("Connection details %v",p)
    // Connect to the remote server and perform a handshake
    client, err := ssh.Dial("tcp", p.IPAddress+":"+p.Port, config)
    if err != nil {
        log.Fatalf("unable to connect to: %v %s", err,p.IPAddress)
    }

    return client, err

}

for simplicity sake I have added a very simple script,but actually the script is huge and requires user confirmation.Any idea on how to solve this issue?

go

interaction

0 Answers

Your Answer

Accepted video resources