gssh-agent 1.0.2 → 1.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/daemon +0 -0
- package/bin/gssh +0 -0
- package/cmd/gssh/main.go +42 -18
- package/internal/session/manager.go +53 -2
- package/package.json +1 -1
package/bin/daemon
CHANGED
|
Binary file
|
package/bin/gssh
CHANGED
|
Binary file
|
package/cmd/gssh/main.go
CHANGED
|
@@ -18,6 +18,7 @@ import (
|
|
|
18
18
|
|
|
19
19
|
const (
|
|
20
20
|
defaultSocketPath = "/tmp/gssh.sock"
|
|
21
|
+
version = "0.1.0"
|
|
21
22
|
)
|
|
22
23
|
|
|
23
24
|
var (
|
|
@@ -25,6 +26,20 @@ var (
|
|
|
25
26
|
)
|
|
26
27
|
|
|
27
28
|
func main() {
|
|
29
|
+
// Check for version flag before parsing
|
|
30
|
+
if len(os.Args) > 1 && (os.Args[1] == "-v" || os.Args[1] == "--version") {
|
|
31
|
+
fmt.Printf("gssh version %s\n", version)
|
|
32
|
+
os.Exit(0)
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// Check for help flag before parsing
|
|
36
|
+
for _, arg := range os.Args[1:] {
|
|
37
|
+
if arg == "-h" || arg == "--help" {
|
|
38
|
+
printUsage()
|
|
39
|
+
os.Exit(0)
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
28
43
|
flag.Parse()
|
|
29
44
|
|
|
30
45
|
if flag.NArg() < 1 {
|
|
@@ -58,7 +73,7 @@ func main() {
|
|
|
58
73
|
err = handleSCP()
|
|
59
74
|
case "sftp":
|
|
60
75
|
err = handleSFTP()
|
|
61
|
-
case "help"
|
|
76
|
+
case "help":
|
|
62
77
|
printUsage()
|
|
63
78
|
default:
|
|
64
79
|
fmt.Fprintf(os.Stderr, "Unknown command: %s\n", cmd)
|
|
@@ -566,42 +581,51 @@ func handleSFTP() error {
|
|
|
566
581
|
}
|
|
567
582
|
|
|
568
583
|
func printUsage() {
|
|
569
|
-
fmt.
|
|
584
|
+
fmt.Printf(`gssh - SSH Session Manager for Agents v%s
|
|
570
585
|
|
|
571
586
|
Usage:
|
|
572
587
|
gssh connect -u user -h host [-p port] [-i key_path] [-P password] [--ask-pass]
|
|
573
588
|
gssh disconnect [-s session_id]
|
|
574
589
|
gssh reconnect [-s session_id]
|
|
575
|
-
gssh exec [-s session_id] [-S password | --ask-sudo-pass] "
|
|
590
|
+
gssh exec [-s session_id] [-S password | --ask-sudo-pass] "command"
|
|
576
591
|
gssh list
|
|
577
592
|
gssh use <session_id>
|
|
578
|
-
gssh forward [-s session_id] -l local_port -r remote_port
|
|
593
|
+
gssh forward [-s session_id] -l local_port -r remote_port [-R]
|
|
579
594
|
gssh forwards
|
|
580
595
|
gssh forward-close <forward_id>
|
|
581
|
-
gssh scp [-s session_id]
|
|
582
|
-
gssh
|
|
583
|
-
|
|
584
|
-
|
|
596
|
+
gssh scp [-s session_id] -put <local> <remote>
|
|
597
|
+
gssh scp [-s session_id] -get <remote> <local>
|
|
598
|
+
gssh sftp [-s session_id] -c <ls|mkdir|rm> -p <path>
|
|
599
|
+
gssh -v, --version
|
|
585
600
|
|
|
586
601
|
Options:
|
|
587
|
-
-socket path
|
|
602
|
+
-socket path Unix socket path (default: /tmp/gssh.sock)
|
|
588
603
|
-s session_id Session ID
|
|
589
604
|
-u user Username
|
|
590
605
|
-h host Host
|
|
591
606
|
-p port Port (default: 22)
|
|
592
|
-
-P password Password
|
|
593
|
-
-i key_path
|
|
594
|
-
-S password
|
|
595
|
-
--ask-
|
|
607
|
+
-P password Password
|
|
608
|
+
-i key_path SSH key path
|
|
609
|
+
-S password sudo password
|
|
610
|
+
--ask-pass Ask for password interactively
|
|
611
|
+
--ask-sudo-pass Ask for sudo password interactively
|
|
596
612
|
-l local Local port
|
|
597
613
|
-r remote Remote port
|
|
598
|
-
-R Remote port forward
|
|
599
|
-
-put Upload
|
|
600
|
-
-get Download
|
|
614
|
+
-R Remote port forward (default: local)
|
|
615
|
+
-put Upload (local -> remote)
|
|
616
|
+
-get Download (remote -> local)
|
|
601
617
|
-c command SFTP command (ls, mkdir, rm)
|
|
602
618
|
-p path Path for SFTP command
|
|
603
|
-
|
|
604
|
-
|
|
619
|
+
-v, --version Show version
|
|
620
|
+
|
|
621
|
+
Examples:
|
|
622
|
+
gssh connect -u admin -h 192.168.1.1 -P password
|
|
623
|
+
gssh exec "ls -la"
|
|
624
|
+
gssh forward -l 8080 -r 80
|
|
625
|
+
gssh forward -l 9000 -r 3000 -R
|
|
626
|
+
gssh scp -put local.txt /home/user/remote.txt
|
|
627
|
+
gssh sftp -c ls -p /home/user
|
|
628
|
+
`, version)
|
|
605
629
|
}
|
|
606
630
|
|
|
607
631
|
// Restore terminal on exit
|
|
@@ -2,6 +2,7 @@ package session
|
|
|
2
2
|
|
|
3
3
|
import (
|
|
4
4
|
"fmt"
|
|
5
|
+
"strings"
|
|
5
6
|
"sync"
|
|
6
7
|
"time"
|
|
7
8
|
|
|
@@ -45,6 +46,54 @@ func NewManager() *Manager {
|
|
|
45
46
|
}
|
|
46
47
|
}
|
|
47
48
|
|
|
49
|
+
// needsShell returns true if the command needs to be executed through a shell
|
|
50
|
+
func needsShell(cmd string) bool {
|
|
51
|
+
// Check for heredoc
|
|
52
|
+
if strings.Contains(cmd, "<<") {
|
|
53
|
+
return true
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// Check for newlines (multi-line commands)
|
|
57
|
+
if strings.Contains(cmd, "\n") {
|
|
58
|
+
return true
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// Check for pipe
|
|
62
|
+
if strings.Contains(cmd, " | ") {
|
|
63
|
+
return true
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// Check for redirection
|
|
67
|
+
if strings.ContainsAny(cmd, "><") {
|
|
68
|
+
// Make sure it's not in a string context
|
|
69
|
+
if strings.Contains(cmd, ">") || strings.Contains(cmd, "<") {
|
|
70
|
+
return true
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
// Check for logical operators
|
|
75
|
+
if strings.Contains(cmd, " && ") || strings.Contains(cmd, " || ") {
|
|
76
|
+
return true
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// Check for background execution
|
|
80
|
+
if strings.HasSuffix(strings.TrimSpace(cmd), "&") {
|
|
81
|
+
return true
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
// Check for command substitution
|
|
85
|
+
if strings.Contains(cmd, "$(") || strings.Contains(cmd, "`") {
|
|
86
|
+
return true
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
// Check for environment variables (but not $$ which is PID)
|
|
90
|
+
if strings.Contains(cmd, "${") || (strings.Contains(cmd, "$") && !strings.Contains(cmd, "$$")) {
|
|
91
|
+
return true
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
return false
|
|
95
|
+
}
|
|
96
|
+
|
|
48
97
|
// Connect creates a new SSH session
|
|
49
98
|
func (m *Manager) Connect(user, host string, port int, password, keyPath string) (*protocol.Session, error) {
|
|
50
99
|
m.mu.Lock()
|
|
@@ -194,9 +243,11 @@ func (m *Manager) Exec(sessionID, command string) (*protocol.ExecResult, error)
|
|
|
194
243
|
}
|
|
195
244
|
defer session.Close()
|
|
196
245
|
|
|
197
|
-
//
|
|
198
|
-
|
|
246
|
+
// 检测是否需要通过 shell 执行
|
|
199
247
|
fullCmd := command
|
|
248
|
+
if needsShell(command) {
|
|
249
|
+
fullCmd = fmt.Sprintf("/bin/zsh -c %q", command)
|
|
250
|
+
}
|
|
200
251
|
|
|
201
252
|
output, err := session.CombinedOutput(fullCmd)
|
|
202
253
|
if err != nil {
|