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 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", "-h", "--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.Println(`gssh - SSH Session Manager for Agents (Stateless)
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] "sudo command"
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] [-put|-get] <source> <dest>
582
- gssh sftp [-s session_id] -c <command> -p <path>
583
-
584
- Note: For sudo commands, use key-based authentication or configure passwordless sudo.
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 Unix socket path (default: /tmp/gssh.sock)
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 (or use --ask-pass for interactive input)
593
- -i key_path SSH key path
594
- -S password sudo password (for executing sudo commands)
595
- --ask-sudo-pass Interactively ask for sudo password
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 mode (local -> remote)
600
- -get Download mode (remote -> local)
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
- --ask-pass Interactively ask for SSH password (secure)
604
- --ask-passphrase Interactively ask for key passphrase (secure)`)
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
- // 直接执行命令,不通过 shell
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 {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gssh-agent",
3
- "version": "1.0.2",
3
+ "version": "1.0.3",
4
4
  "description": "SSH Session Manager for Agents - Stateless SSH client with SFTP support",
5
5
  "bin": {
6
6
  "gssh": "./bin/gssh",