mirror of
https://github.com/appleboy/drone-ssh.git
synced 2025-09-13 20:00:10 +08:00
![]() Before changes: ```sh $ # This is what `keychain --eval --inherit any` does on Ubuntu. $ # https://www.funtoo.org/Keychain $ export SSH_AUTH_SOCK=/run/user/1000/keyring/ssh $ go build example/ssh/ssh.go $ ./ssh panic: Can't run remote command: ssh: handshake failed: agent: client error: write unix @->/run/user/1000/keyring/ssh: use of closed network connection goroutine 1 [running]: main.main() /home/wsh/go/src/github.com/wataash/easyssh-proxy/example/ssh/ssh.go:32 +0x2d3 ``` Error message `write unix @->/run/user/1000/keyring/ssh: use of closed network connection` comes from [`Write()`](https://github.com/golang/crypto/blob/2b6c08872f4/ssh/agent/client.go#L277) where `SSH_AUTH_SOCK` is already `Close()`ed. After changes: ```sh $ export SSH_AUTH_SOCK=/run/user/1000/keyring/ssh $ go build example/ssh/ssh.go $ ./ssh github.com/wataash/easyssh-proxy command-line-arguments don is : true stdout is : total 640 drwxr-xr-x 68 wsh wsh 4096 10月 16 21:25 . drwxr-xr-x 3 root root 4096 9月 12 08:39 .. drwxr-xr-x 2 wsh wsh 4096 9月 20 20:48 .android ... -rw-rw-r-- 1 wsh wsh 202 9月 12 19:51 .zshrc ; stderr is : Identity added: /home/wsh/.ssh/id_rsa (/home/wsh/.ssh/id_rsa) Identity added: /home/wsh/.ssh/id_ed25519 (wsh@wsh9b) ``` https://github.com/appleboy/drone-ssh/commit/9b697286281 |
||
---|---|---|
.. | ||
easyssh.go | ||
LICENSE | ||
Makefile | ||
README.md |
easyssh-proxy
easyssh-proxy provides a simple implementation of some SSH protocol features in Go.
Feature
This project is forked from easyssh but add some features as the following.
- Support plain text of user private key.
- Support key path of user private key.
- Support Timeout for the TCP connection to establish.
- Support SSH ProxyCommand.
+--------+ +----------+ +-----------+
| Laptop | <--> | Jumphost | <--> | FooServer |
+--------+ +----------+ +-----------+
OR
+--------+ +----------+ +-----------+
| Laptop | <--> | Firewall | <--> | FooServer |
+--------+ +----------+ +-----------+
192.168.1.5 121.1.2.3 10.10.29.68
Usage:
You can see ssh
, scp
, ProxyCommand
on examples
folder.
ssh
package main
import (
"fmt"
"time"
"github.com/appleboy/easyssh-proxy"
)
func main() {
// Create MakeConfig instance with remote username, server address and path to private key.
ssh := &easyssh.MakeConfig{
User: "appleboy",
Server: "example.com",
// Optional key or Password without either we try to contact your agent SOCKET
//Password: "password",
// Paste your source content of private key
// Key: `-----BEGIN RSA PRIVATE KEY-----
// MIIEpAIBAAKCAQEA4e2D/qPN08pzTac+a8ZmlP1ziJOXk45CynMPtva0rtK/RB26
// 7XC9wlRna4b3Ln8ew3q1ZcBjXwD4ppbTlmwAfQIaZTGJUgQbdsO9YA==
// -----END RSA PRIVATE KEY-----
// `,
KeyPath: "/Users/username/.ssh/id_rsa",
Port: "22",
Timeout: 60 * time.Second,
}
// Call Run method with command you want to run on remote server.
stdout, stderr, done, err := ssh.Run("ls -al", 60)
// Handle errors
if err != nil {
panic("Can't run remote command: " + err.Error())
} else {
fmt.Println("don is :", done, "stdout is :", stdout, "; stderr is :", stderr)
}
}
scp
package main
import (
"fmt"
"github.com/appleboy/easyssh-proxy"
)
func main() {
// Create MakeConfig instance with remote username, server address and path to private key.
ssh := &easyssh.MakeConfig{
User: "appleboy",
Server: "example.com",
Password: "123qwe",
Port: "22",
}
// Call Scp method with file you want to upload to remote server.
// Please make sure the `tmp` floder exists.
err := ssh.Scp("/root/source.csv", "/tmp/target.csv")
// Handle errors
if err != nil {
panic("Can't run remote command: " + err.Error())
} else {
fmt.Println("success")
}
}
SSH ProxyCommand
ssh := &easyssh.MakeConfig{
User: "drone-scp",
Server: "localhost",
Port: "22",
KeyPath: "./tests/.ssh/id_rsa",
Proxy: easyssh.DefaultConfig{
User: "drone-scp",
Server: "localhost",
Port: "22",
KeyPath: "./tests/.ssh/id_rsa",
},
}
SSH Stream Log
func main() {
// Create MakeConfig instance with remote username, server address and path to private key.
ssh := &easyssh.MakeConfig{
Server: "localhost",
User: "drone-scp",
KeyPath: "./tests/.ssh/id_rsa",
Port: "22",
Timeout: 60 * time.Second,
}
// Call Run method with command you want to run on remote server.
stdoutChan, stderrChan, doneChan, errChan, err := ssh.Stream("for i in {1..5}; do echo ${i}; sleep 1; done; exit 2;", 60)
// Handle errors
if err != nil {
panic("Can't run remote command: " + err.Error())
} else {
// read from the output channel until the done signal is passed
isTimeout := true
loop:
for {
select {
case isTimeout = <-doneChan:
break loop
case outline := <-stdoutChan:
fmt.Println("out:", outline)
case errline := <-stderrChan:
fmt.Println("err:", errline)
case err = <-errChan:
}
}
// get exit code or command error.
if err != nil {
fmt.Println("err: " + err.Error())
}
// command time out
if !isTimeout {
fmt.Println("Error: command timeout")
}
}
}