Skip to content

Commit 9cea92f

Browse files
committed
much better ssh example
1 parent 06497da commit 9cea92f

File tree

1 file changed

+82
-51
lines changed

1 file changed

+82
-51
lines changed

non-std-lib/ssh-client.go

Lines changed: 82 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -4,98 +4,129 @@ import (
44
"flag"
55
"fmt"
66
"io/ioutil"
7-
"net"
7+
"os"
88

99
"golang.org/x/crypto/ssh"
1010
)
1111

12-
var user string
13-
var host string
14-
var port string
15-
var keyfile string
12+
var (
13+
user string
14+
host string
15+
port string
16+
keyfile string
17+
)
18+
19+
func init() {
20+
flag.StringVar(&user, "u", "root", "SSH user")
21+
flag.StringVar(&host, "h", "example.tld", "Host")
22+
flag.StringVar(&port, "p", "22", "SSH port")
23+
flag.StringVar(&keyfile, "pk", "", "Public key file, e.g.: \"~/.ssh/id_rsa\"")
24+
}
1625

1726
func main() {
18-
flag.StringVar(&user, "u", "root", "ssh user")
19-
flag.StringVar(&host, "h", "example.tld", "host")
20-
flag.StringVar(&port, "p", "22", "ssh port")
21-
flag.StringVar(&keyfile, "pk", "", "public key file, eg.: \"~/.ssh/id_rsa\"")
2227
flag.Parse()
2328

24-
var client *ssh.Client
25-
var session *ssh.Session
26-
var err error
27-
2829
if host == "example.tld" {
29-
fmt.Println("go run ssh-client.go -h example.tld -p 22 -pk /Users/johndoe/.ssh/id_rsa")
30+
fmt.Println("Usage: go run ssh-client.go -h <host> -p <port> -pk <path_to_private_key>")
3031
flag.PrintDefaults()
3132
return
3233
}
3334

35+
var client *ssh.Client
36+
var err error
37+
3438
if keyfile != "" {
35-
client, session, err = connectToHostWithPublickey(user, fmt.Sprintf("%v:%v", host, port), keyfile)
39+
client, err = connectToHostWithPublicKey(user, fmt.Sprintf("%v:%v", host, port), keyfile)
3640
} else {
37-
client, session, err = connectToHost(user, fmt.Sprintf("%v:%v", host, port))
41+
client, err = connectToHost(user, fmt.Sprintf("%v:%v", host, port))
3842
}
3943

4044
if err != nil {
41-
panic(err)
42-
}
43-
out, err := session.CombinedOutput("ls -al")
44-
if err != nil {
45-
panic(err)
45+
fmt.Fprintf(os.Stderr, "Failed to connect: %v\n", err)
46+
return
4647
}
47-
fmt.Println(string(out))
48-
client.Close()
48+
defer client.Close()
49+
50+
runRemoteCommands(client)
4951
}
5052

51-
func connectToHost(user, host string) (*ssh.Client, *ssh.Session, error) {
52-
var pass string
53-
fmt.Print("SSH-Password: ")
54-
fmt.Scanf("%s\n", &pass)
53+
func connectToHost(user, host string) (*ssh.Client, error) {
54+
var password string
55+
fmt.Print("SSH Password: ")
56+
fmt.Scanf("%s\n", &password)
5557

5658
sshConfig := &ssh.ClientConfig{
5759
User: user,
58-
Auth: []ssh.AuthMethod{ssh.Password(pass)},
60+
Auth: []ssh.AuthMethod{
61+
ssh.Password(password),
62+
},
63+
HostKeyCallback: ssh.InsecureIgnoreHostKey(),
5964
}
60-
sshConfig.HostKeyCallback = ssh.InsecureIgnoreHostKey()
6165

6266
client, err := ssh.Dial("tcp", host, sshConfig)
6367
if err != nil {
64-
return nil, nil, err
68+
return nil, err
6569
}
6670

67-
session, err := client.NewSession()
68-
if err != nil {
69-
client.Close()
70-
return nil, nil, err
71-
}
72-
73-
return client, session, nil
71+
return client, nil
7472
}
7573

76-
func connectToHostWithPublickey(user, host, publickeyfile string) (*ssh.Client, *ssh.Session, error) {
77-
key, err := ioutil.ReadFile(publickeyfile)
74+
func connectToHostWithPublicKey(user, host, publicKeyFile string) (*ssh.Client, error) {
75+
key, err := ioutil.ReadFile(publicKeyFile)
7876
if err != nil {
79-
return nil, nil, err
77+
return nil, err
8078
}
79+
8180
signer, err := ssh.ParsePrivateKey(key)
8281
if err != nil {
83-
return nil, nil, err
82+
return nil, err
8483
}
85-
client, err := ssh.Dial("tcp", host, &ssh.ClientConfig{
86-
User: user,
87-
Auth: []ssh.AuthMethod{ssh.PublicKeys(signer)},
88-
HostKeyCallback: ssh.HostKeyCallback(func(string, net.Addr, ssh.PublicKey) error { return nil }),
89-
})
90-
if client == nil || err != nil {
91-
return nil, nil, err
84+
85+
sshConfig := &ssh.ClientConfig{
86+
User: user,
87+
Auth: []ssh.AuthMethod{
88+
ssh.PublicKeys(signer),
89+
},
90+
HostKeyCallback: ssh.InsecureIgnoreHostKey(),
9291
}
9392

93+
client, err := ssh.Dial("tcp", host, sshConfig)
94+
if err != nil {
95+
return nil, err
96+
}
97+
98+
return client, nil
99+
}
100+
101+
func runRemoteCommands(client *ssh.Client) {
102+
commands := []string{
103+
"ls -al",
104+
"df -h",
105+
"uptime",
106+
"whoami",
107+
}
108+
109+
for _, cmd := range commands {
110+
output, err := executeRemoteCommand(client, cmd)
111+
if err != nil {
112+
fmt.Fprintf(os.Stderr, "Failed to run command '%s': %v\n", cmd, err)
113+
continue
114+
}
115+
fmt.Printf("Output of '%s':\n%s\n", cmd, output)
116+
}
117+
}
118+
119+
func executeRemoteCommand(client *ssh.Client, command string) (string, error) {
94120
session, err := client.NewSession()
95121
if err != nil {
96-
client.Close()
97-
return nil, nil, err
122+
return "", err
123+
}
124+
defer session.Close()
125+
126+
output, err := session.CombinedOutput(command)
127+
if err != nil {
128+
return "", err
98129
}
99130

100-
return client, session, nil
131+
return string(output), nil
101132
}

0 commit comments

Comments
 (0)