rdebug/rdebug.go

143 lines
3.3 KiB
Go
Raw Normal View History

2021-10-06 17:31:52 +00:00
// Helper script for remote gdb
2021-10-14 12:13:21 +00:00
// Copyright (C) 2017 Moritz Bitsch
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
2021-10-06 17:31:52 +00:00
package main
import (
"bufio"
"flag"
"fmt"
"io"
"os"
"path"
"strconv"
"strings"
"golang.org/x/crypto/ssh"
)
var (
optUser = flag.String("user", "default", "username for ssh user")
optPassword = flag.String("pass", "", "password")
optGdbPort = flag.Uint("port", 10001, "remote gdb port to use")
)
func main() {
flag.Usage = func() {
fmt.Fprintf(os.Stderr, "Usage: %s [OPTIONS] hostname program args\n", os.Args[0])
flag.PrintDefaults()
}
flag.Parse()
if flag.NArg() < 2 {
flag.Usage()
os.Exit(2)
}
connection, err := createConnection(flag.Arg(0), *optUser, *optPassword)
if err != nil {
fmt.Fprintf(os.Stderr, "Can't connect to host: %s", err.Error())
os.Exit(1)
}
defer connection.Close()
2021-10-14 12:13:49 +00:00
err = deployFile(connection, flag.Arg(1), "/tmp/"+path.Base(flag.Arg(1)), "0755")
2021-10-06 17:31:52 +00:00
if err != nil {
fmt.Fprintf(os.Stderr, "Can't deploy file: %s", err.Error())
os.Exit(1)
}
2021-10-14 12:13:49 +00:00
session, err := startGDB(connection, "/tmp/"+path.Base(flag.Arg(1)))
2021-10-06 17:31:52 +00:00
if err != nil {
fmt.Fprintf(os.Stderr, "Can't start gdb: %s", err.Error())
os.Exit(1)
}
defer session.Close()
}
func startGDB(client *ssh.Client, remoteCommand string) (*ssh.Session, error) {
session, err := client.NewSession()
if err != nil {
return nil, err
}
output, err := session.StderrPipe()
if err != nil {
return nil, err
}
err = session.Start("exec nohup gdbserver --once :" + strconv.Itoa(int(*optGdbPort)) + " " + remoteCommand)
if err != nil {
return nil, err
}
reader := bufio.NewReader(output)
for line, err := reader.ReadString('\n'); err == nil; line, err = reader.ReadString('\n') {
if strings.HasPrefix(line, "Listening on port") {
println(line)
break
}
}
return session, nil
}
func deployFile(client *ssh.Client, localPath, remotePath string, permissions string) error {
2021-10-14 12:13:49 +00:00
fmt.Printf("Deploy: %s -> %s\n", localPath, remotePath)
2021-10-06 17:31:52 +00:00
reader, err := os.Open(localPath)
if err != nil {
return err
}
defer reader.Close()
st, err := reader.Stat()
if err != nil {
return err
}
session, err := client.NewSession()
if err != nil {
return err
}
defer session.Close()
writer, _ := session.StdinPipe()
go func() {
fmt.Fprintf(writer, "C%s %d %s\n", permissions, st.Size(), path.Base(remotePath))
io.Copy(writer, reader)
writer.Write([]byte{0x00})
writer.Close()
}()
return session.Run("/usr/bin/scp -t " + path.Dir(remotePath))
}
func createConnection(host string, username string, password string) (*ssh.Client, error) {
config := &ssh.ClientConfig{
User: username,
Auth: []ssh.AuthMethod{
ssh.Password(password),
},
HostKeyCallback: ssh.InsecureIgnoreHostKey(),
}
return ssh.Dial("tcp", host, config)
}