-
Notifications
You must be signed in to change notification settings - Fork 18.3k
Closed
Labels
Milestone
Description
Starting a process over SSH using the /x/crypto/ssh library and then trying to send a signal to it, seems to have no effect. I've found a few musings on the internet about users with the same problem.
I've attached a full reproducer, including the crappy workaround.
package main
import (
"bytes"
"fmt"
"golang.org/x/crypto/ssh"
"time"
)
func main() {
// An SSH client is represented with a ClientConn.
//
// To authenticate with the remote server you must pass at least one
// implementation of AuthMethod via the Auth field in ClientConfig.
config := &ssh.ClientConfig{
User: "someuser", // XXX
Auth: []ssh.AuthMethod{
ssh.Password("somepass"), // XXX
},
}
client, err := ssh.Dial("tcp", "localhost: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
go func() {
time.Sleep(2 * time.Second)
// XXX none of these signals work! :(
// fmt.Println("Running signal!")
// session.Signal(ssh.SIGINT)
// session.Signal(ssh.SIGKILL)
// session.Signal(ssh.SIGQUIT)
// session.Signal(ssh.SIGHUP)
// session.Signal(ssh.SIGPIPE)
// fmt.Println("Done running signal!")
s2, err := client.NewSession()
if err != nil {
panic("Failed to create session: " + err.Error())
}
defer s2.Close()
var c bytes.Buffer
s2.Stdout = &c
if err := s2.Run("echo start && pidof sleep && killall sleep"); err != nil {
fmt.Println("s2 error!")
}
fmt.Println("Sig run done!")
fmt.Println(c.String())
}()
if err := session.Run("echo $0 && /usr/bin/sleep 10s"); err != nil {
if e, ok := err.(*ssh.ExitError); ok {
fmt.Printf("Remote: Exit msg: %s", e.Waitmsg.Msg()) // XXX (does this ever return anything useful?)
fmt.Printf("Remote: Exit signal: %s", e.Waitmsg.Signal())
fmt.Printf("Remote: Error: Output...\n%s", b.String())
fmt.Printf("Exited (%d) with: %s", e.Waitmsg.ExitStatus(), e.Error())
} else if e, ok := err.(*ssh.ExitMissingError); ok {
fmt.Printf("Exit code missing: %s", e.Error())
}
panic("Failed to run: " + err.Error())
}
fmt.Println("Done!")
fmt.Println(b.String())
}
Uncomment the signal you want, and you'll see that they all do nothing to kill the running sleep
command.
Tested with go version: 1.5.4 (but I have no reason to expect this is fixed with newer versions!) on Fedora GNU/Linux 24 as the SSH server, running OpenSSH.
Thanks!
mihaitodor